1 /* -*- mode: C -*-  */
2 /* vim:set ts=4 sw=4 sts=4 et: */
3 /*
4    IGraph library.
5    Copyright (C) 2005-2012  Gabor Csardi <csardi.gabor@gmail.com>
6    334 Harvard street, Cambridge, MA 02139 USA
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301 USA
22 
23 */
24 
25 #include "igraph_structural.h"
26 #include "igraph_transitivity.h"
27 #include "igraph_paths.h"
28 #include "igraph_math.h"
29 #include "igraph_memory.h"
30 #include "igraph_random.h"
31 #include "igraph_adjlist.h"
32 #include "igraph_interface.h"
33 #include "igraph_progress.h"
34 #include "igraph_interrupt_internal.h"
35 #include "igraph_centrality.h"
36 #include "igraph_components.h"
37 #include "igraph_constructors.h"
38 #include "igraph_conversion.h"
39 #include "igraph_types_internal.h"
40 #include "igraph_dqueue.h"
41 #include "igraph_attributes.h"
42 #include "igraph_neighborhood.h"
43 #include "igraph_topology.h"
44 #include "igraph_qsort.h"
45 #include "config.h"
46 #include "structural_properties_internal.h"
47 
48 #include <assert.h>
49 #include <string.h>
50 #include <limits.h>
51 
52 /**
53  * \section about_structural
54  *
55  * <para>These functions usually calculate some structural property
56  * of a graph, like its diameter, the degree of the nodes, etc.</para>
57  */
58 
59 /**
60  * \ingroup structural
61  * \function igraph_diameter
62  * \brief Calculates the diameter of a graph (longest geodesic).
63  *
64  * \param graph The graph object.
65  * \param pres Pointer to an integer, if not \c NULL then it will contain
66  *        the diameter (the actual distance).
67  * \param pfrom Pointer to an integer, if not \c NULL it will be set to the
68  *        source vertex of the diameter path.
69  * \param pto Pointer to an integer, if not \c NULL it will be set to the
70  *        target vertex of the diameter path.
71  * \param path Pointer to an initialized vector. If not \c NULL the actual
72  *        longest geodesic path will be stored here. The vector will be
73  *        resized as needed.
74  * \param directed Boolean, whether to consider directed
75  *        paths. Ignored for undirected graphs.
76  * \param unconn What to do if the graph is not connected. If
77  *        \c TRUE the longest geodesic within a component
78  *        will be returned, otherwise the number of vertices is
79  *        returned. (The rationale behind the latter is that this is
80  *        always longer than the longest possible diameter in a
81  *        graph.)
82  * \return Error code:
83  *         \c IGRAPH_ENOMEM, not enough memory for
84  *         temporary data.
85  *
86  * Time complexity: O(|V||E|), the
87  * number of vertices times the number of edges.
88  *
89  * \example examples/simple/igraph_diameter.c
90  */
91 
igraph_diameter(const igraph_t * graph,igraph_integer_t * pres,igraph_integer_t * pfrom,igraph_integer_t * pto,igraph_vector_t * path,igraph_bool_t directed,igraph_bool_t unconn)92 int igraph_diameter(const igraph_t *graph, igraph_integer_t *pres,
93                     igraph_integer_t *pfrom, igraph_integer_t *pto,
94                     igraph_vector_t *path,
95                     igraph_bool_t directed, igraph_bool_t unconn) {
96 
97     long int no_of_nodes = igraph_vcount(graph);
98     long int i, j, n;
99     long int *already_added;
100     long int nodes_reached;
101     long int from = 0, to = 0;
102     long int res = 0;
103 
104     igraph_dqueue_t q = IGRAPH_DQUEUE_NULL;
105     igraph_vector_int_t *neis;
106     igraph_neimode_t dirmode;
107     igraph_adjlist_t allneis;
108 
109     if (directed) {
110         dirmode = IGRAPH_OUT;
111     } else {
112         dirmode = IGRAPH_ALL;
113     }
114     already_added = igraph_Calloc(no_of_nodes, long int);
115     if (already_added == 0) {
116         IGRAPH_ERROR("diameter failed", IGRAPH_ENOMEM);
117     }
118     IGRAPH_FINALLY(igraph_free, already_added);
119     IGRAPH_DQUEUE_INIT_FINALLY(&q, 100);
120 
121     IGRAPH_CHECK(igraph_adjlist_init(graph, &allneis, dirmode));
122     IGRAPH_FINALLY(igraph_adjlist_destroy, &allneis);
123 
124     for (i = 0; i < no_of_nodes; i++) {
125         nodes_reached = 1;
126         IGRAPH_CHECK(igraph_dqueue_push(&q, i));
127         IGRAPH_CHECK(igraph_dqueue_push(&q, 0));
128         already_added[i] = i + 1;
129 
130         IGRAPH_PROGRESS("Diameter: ", 100.0 * i / no_of_nodes, NULL);
131 
132         IGRAPH_ALLOW_INTERRUPTION();
133 
134         while (!igraph_dqueue_empty(&q)) {
135             long int actnode = (long int) igraph_dqueue_pop(&q);
136             long int actdist = (long int) igraph_dqueue_pop(&q);
137             if (actdist > res) {
138                 res = actdist;
139                 from = i;
140                 to = actnode;
141             }
142 
143             neis = igraph_adjlist_get(&allneis, actnode);
144             n = igraph_vector_int_size(neis);
145             for (j = 0; j < n; j++) {
146                 long int neighbor = (long int) VECTOR(*neis)[j];
147                 if (already_added[neighbor] == i + 1) {
148                     continue;
149                 }
150                 already_added[neighbor] = i + 1;
151                 nodes_reached++;
152                 IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor));
153                 IGRAPH_CHECK(igraph_dqueue_push(&q, actdist + 1));
154             }
155         } /* while !igraph_dqueue_empty */
156 
157         /* not connected, return largest possible */
158         if (nodes_reached != no_of_nodes && !unconn) {
159             res = no_of_nodes;
160             from = -1;
161             to = -1;
162             break;
163         }
164     } /* for i<no_of_nodes */
165 
166     IGRAPH_PROGRESS("Diameter: ", 100.0, NULL);
167 
168     /* return the requested info */
169     if (pres != 0) {
170         *pres = (igraph_integer_t) res;
171     }
172     if (pfrom != 0) {
173         *pfrom = (igraph_integer_t) from;
174     }
175     if (pto != 0) {
176         *pto = (igraph_integer_t) to;
177     }
178     if (path != 0) {
179         if (res == no_of_nodes) {
180             igraph_vector_clear(path);
181         } else {
182             igraph_vector_ptr_t tmpptr;
183             igraph_vector_ptr_init(&tmpptr, 1);
184             IGRAPH_FINALLY(igraph_vector_ptr_destroy, &tmpptr);
185             VECTOR(tmpptr)[0] = path;
186             IGRAPH_CHECK(igraph_get_shortest_paths(graph, &tmpptr, 0,
187                                                    (igraph_integer_t) from,
188                                                    igraph_vss_1((igraph_integer_t)to),
189                                                    dirmode, 0, 0));
190             igraph_vector_ptr_destroy(&tmpptr);
191             IGRAPH_FINALLY_CLEAN(1);
192         }
193     }
194 
195     /* clean */
196     igraph_Free(already_added);
197     igraph_dqueue_destroy(&q);
198     igraph_adjlist_destroy(&allneis);
199     IGRAPH_FINALLY_CLEAN(3);
200 
201     return 0;
202 }
203 
204 /**
205  * \ingroup structural
206  * \function igraph_average_path_length
207  * \brief Calculates the average shortest path length between all vertex pairs.
208  *
209  * \param graph The graph object.
210  * \param res Pointer to a real number, this will contain the result.
211  * \param directed Boolean, whether to consider directed
212  *        paths. Ignored for undirected graphs.
213  * \param unconn What to do if the graph is not connected. If
214  *        \c TRUE, only those vertex pairs will be included in the calculation
215  *        between which there is a path. If \c FALSE, the number of vertices is
216  *        used as the distance between vertices unreachable from each other.
217  *        The rationale behind this is that this is always longer than the longest
218  *        possible geodesic in a graph.
219  * \return Error code:
220  *         \c IGRAPH_ENOMEM, not enough memory for
221  *         data structures
222  *
223  * Time complexity: O(|V||E|), the
224  * number of vertices times the number of edges.
225  *
226  * \example examples/simple/igraph_average_path_length.c
227  */
228 
igraph_average_path_length(const igraph_t * graph,igraph_real_t * res,igraph_bool_t directed,igraph_bool_t unconn)229 int igraph_average_path_length(const igraph_t *graph, igraph_real_t *res,
230                                igraph_bool_t directed, igraph_bool_t unconn) {
231     long int no_of_nodes = igraph_vcount(graph);
232     long int i, j, n;
233     long int *already_added;
234     long int nodes_reached = 0;
235     igraph_real_t normfact = 0.0;
236 
237     igraph_dqueue_t q = IGRAPH_DQUEUE_NULL;
238     igraph_vector_int_t *neis;
239     igraph_neimode_t dirmode;
240     igraph_adjlist_t allneis;
241 
242     *res = 0;
243     if (directed) {
244         dirmode = IGRAPH_OUT;
245     } else {
246         dirmode = IGRAPH_ALL;
247     }
248     already_added = igraph_Calloc(no_of_nodes, long int);
249     if (already_added == 0) {
250         IGRAPH_ERROR("average path length failed", IGRAPH_ENOMEM);
251     }
252     IGRAPH_FINALLY(free, already_added); /* TODO: hack */
253     IGRAPH_DQUEUE_INIT_FINALLY(&q, 100);
254 
255     igraph_adjlist_init(graph, &allneis, dirmode);
256     IGRAPH_FINALLY(igraph_adjlist_destroy, &allneis);
257 
258     for (i = 0; i < no_of_nodes; i++) {
259         nodes_reached = 0;
260         IGRAPH_CHECK(igraph_dqueue_push(&q, i));
261         IGRAPH_CHECK(igraph_dqueue_push(&q, 0));
262         already_added[i] = i + 1;
263 
264         IGRAPH_ALLOW_INTERRUPTION();
265 
266         while (!igraph_dqueue_empty(&q)) {
267             long int actnode = (long int) igraph_dqueue_pop(&q);
268             long int actdist = (long int) igraph_dqueue_pop(&q);
269 
270             neis = igraph_adjlist_get(&allneis, actnode);
271             n = igraph_vector_int_size(neis);
272             for (j = 0; j < n; j++) {
273                 long int neighbor = (long int) VECTOR(*neis)[j];
274                 if (already_added[neighbor] == i + 1) {
275                     continue;
276                 }
277                 already_added[neighbor] = i + 1;
278                 nodes_reached++;
279                 *res += actdist + 1;
280                 normfact += 1;
281                 IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor));
282                 IGRAPH_CHECK(igraph_dqueue_push(&q, actdist + 1));
283             }
284         } /* while !igraph_dqueue_empty */
285 
286         /* not connected, return largest possible */
287         if (!unconn) {
288             *res += (no_of_nodes * (no_of_nodes - 1 - nodes_reached));
289             normfact += no_of_nodes - 1 - nodes_reached;
290         }
291     } /* for i<no_of_nodes */
292 
293 
294     if (normfact > 0) {
295         *res /= normfact;
296     } else {
297         *res = IGRAPH_NAN;
298     }
299 
300     /* clean */
301     igraph_Free(already_added);
302     igraph_dqueue_destroy(&q);
303     igraph_adjlist_destroy(&allneis);
304     IGRAPH_FINALLY_CLEAN(3);
305 
306     return 0;
307 }
308 
309 /**
310  * \function igraph_path_length_hist
311  * Create a histogram of all shortest path lengths.
312  *
313  * This function calculates a histogram, by calculating the
314  * shortest path length between each pair of vertices. For directed
315  * graphs both directions might be considered and then every pair of vertices
316  * appears twice in the histogram.
317  * \param graph The input graph.
318  * \param res Pointer to an initialized vector, the result is stored
319  *     here. The first (i.e. zeroth) element contains the number of
320  *     shortest paths of length 1, etc. The supplied vector is resized
321  *     as needed.
322  * \param unconnected Pointer to a real number, the number of
323  *     pairs for which the second vertex is not reachable from the
324  *     first is stored here.
325  * \param directed Whether to consider directed paths in a directed
326  *     graph (if not zero). This argument is ignored for undirected
327  *     graphs.
328  * \return Error code.
329  *
330  * Time complexity: O(|V||E|), the number of vertices times the number
331  * of edges.
332  *
333  * \sa \ref igraph_average_path_length() and \ref igraph_shortest_paths()
334  */
335 
igraph_path_length_hist(const igraph_t * graph,igraph_vector_t * res,igraph_real_t * unconnected,igraph_bool_t directed)336 int igraph_path_length_hist(const igraph_t *graph, igraph_vector_t *res,
337                             igraph_real_t *unconnected, igraph_bool_t directed) {
338 
339     long int no_of_nodes = igraph_vcount(graph);
340     long int i, j, n;
341     igraph_vector_long_t already_added;
342     long int nodes_reached;
343 
344     igraph_dqueue_t q = IGRAPH_DQUEUE_NULL;
345     igraph_vector_int_t *neis;
346     igraph_neimode_t dirmode;
347     igraph_adjlist_t allneis;
348     igraph_real_t unconn = 0;
349     long int ressize;
350 
351     if (directed) {
352         dirmode = IGRAPH_OUT;
353     } else {
354         dirmode = IGRAPH_ALL;
355     }
356 
357     IGRAPH_CHECK(igraph_vector_long_init(&already_added, no_of_nodes));
358     IGRAPH_FINALLY(igraph_vector_long_destroy, &already_added);
359     IGRAPH_DQUEUE_INIT_FINALLY(&q, 100);
360     IGRAPH_CHECK(igraph_adjlist_init(graph, &allneis, dirmode));
361     IGRAPH_FINALLY(igraph_adjlist_destroy, &allneis);
362 
363     IGRAPH_CHECK(igraph_vector_resize(res, 0));
364     ressize = 0;
365 
366     for (i = 0; i < no_of_nodes; i++) {
367         nodes_reached = 1;      /* itself */
368         IGRAPH_CHECK(igraph_dqueue_push(&q, i));
369         IGRAPH_CHECK(igraph_dqueue_push(&q, 0));
370         VECTOR(already_added)[i] = i + 1;
371 
372         IGRAPH_PROGRESS("Path-hist: ", 100.0 * i / no_of_nodes, NULL);
373 
374         IGRAPH_ALLOW_INTERRUPTION();
375 
376         while (!igraph_dqueue_empty(&q)) {
377             long int actnode = (long int) igraph_dqueue_pop(&q);
378             long int actdist = (long int) igraph_dqueue_pop(&q);
379 
380             neis = igraph_adjlist_get(&allneis, actnode);
381             n = igraph_vector_int_size(neis);
382             for (j = 0; j < n; j++) {
383                 long int neighbor = (long int) VECTOR(*neis)[j];
384                 if (VECTOR(already_added)[neighbor] == i + 1) {
385                     continue;
386                 }
387                 VECTOR(already_added)[neighbor] = i + 1;
388                 nodes_reached++;
389                 if (actdist + 1 > ressize) {
390                     IGRAPH_CHECK(igraph_vector_resize(res, actdist + 1));
391                     for (; ressize < actdist + 1; ressize++) {
392                         VECTOR(*res)[ressize] = 0;
393                     }
394                 }
395                 VECTOR(*res)[actdist] += 1;
396 
397                 IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor));
398                 IGRAPH_CHECK(igraph_dqueue_push(&q, actdist + 1));
399             }
400         } /* while !igraph_dqueue_empty */
401 
402         unconn += (no_of_nodes - nodes_reached);
403 
404     } /* for i<no_of_nodes */
405 
406     IGRAPH_PROGRESS("Path-hist: ", 100.0, NULL);
407 
408     /* count every pair only once for an undirected graph */
409     if (!directed || !igraph_is_directed(graph)) {
410         for (i = 0; i < ressize; i++) {
411             VECTOR(*res)[i] /= 2;
412         }
413         unconn /= 2;
414     }
415 
416     igraph_vector_long_destroy(&already_added);
417     igraph_dqueue_destroy(&q);
418     igraph_adjlist_destroy(&allneis);
419     IGRAPH_FINALLY_CLEAN(3);
420 
421     if (unconnected) {
422         *unconnected = unconn;
423     }
424 
425     return 0;
426 }
427 
428 /**
429  * \ingroup structural
430  * \function igraph_shortest_paths
431  * \brief The length of the shortest paths between vertices.
432  *
433  * \param graph The graph object.
434  * \param res The result of the calculation, a matrix. A pointer to an
435  *        initialized matrix, to be more precise. The matrix will be
436  *        resized if needed. It will have the same
437  *        number of rows as the length of the \c from
438  *        argument, and its number of columns is the number of
439  *        vertices in the \c to argument. One row of the matrix shows the
440  *        distances from/to a given vertex to the ones in \c to.
441  *        For the unreachable vertices IGRAPH_INFINITY is returned.
442  * \param from Vector of the vertex ids for which the path length
443  *        calculations are done.
444  * \param to Vector of the vertex ids to which the path length
445  *        calculations are done. It is not allowed to have duplicated
446  *        vertex ids here.
447  * \param mode The type of shortest paths to be used for the
448  *        calculation in directed graphs. Possible values:
449  *        \clist
450  *        \cli IGRAPH_OUT
451  *          the lengths of the outgoing paths are calculated.
452  *        \cli IGRAPH_IN
453  *          the lengths of the incoming paths are calculated.
454  *        \cli IGRAPH_ALL
455  *          the directed graph is considered as an undirected one for
456  *          the computation.
457  *        \endclist
458  * \return Error code:
459  *        \clist
460  *        \cli IGRAPH_ENOMEM
461  *           not enough memory for temporary
462  *           data.
463  *        \cli IGRAPH_EINVVID
464  *           invalid vertex id passed.
465  *        \cli IGRAPH_EINVMODE
466  *           invalid mode argument.
467  *        \endclist
468  *
469  * Time complexity: O(n(|V|+|E|)),
470  * n is the
471  * number of vertices to calculate, |V| and
472  * |E| are the number of vertices and
473  * edges in the graph.
474  *
475  * \sa \ref igraph_get_shortest_paths() to get the paths themselves,
476  * \ref igraph_shortest_paths_dijkstra() for the weighted version.
477  */
478 
igraph_shortest_paths(const igraph_t * graph,igraph_matrix_t * res,const igraph_vs_t from,const igraph_vs_t to,igraph_neimode_t mode)479 int igraph_shortest_paths(const igraph_t *graph, igraph_matrix_t *res,
480                           const igraph_vs_t from, const igraph_vs_t to,
481                           igraph_neimode_t mode) {
482 
483     long int no_of_nodes = igraph_vcount(graph);
484     long int no_of_from, no_of_to;
485     long int *already_counted;
486     igraph_adjlist_t adjlist;
487     igraph_dqueue_t q = IGRAPH_DQUEUE_NULL;
488     igraph_vector_int_t *neis;
489     igraph_bool_t all_to;
490 
491     long int i, j;
492     igraph_vit_t fromvit, tovit;
493     igraph_real_t my_infinity = IGRAPH_INFINITY;
494     igraph_vector_t indexv;
495 
496     if (mode != IGRAPH_OUT && mode != IGRAPH_IN &&
497         mode != IGRAPH_ALL) {
498         IGRAPH_ERROR("Invalid mode argument", IGRAPH_EINVMODE);
499     }
500 
501     IGRAPH_CHECK(igraph_vit_create(graph, from, &fromvit));
502     IGRAPH_FINALLY(igraph_vit_destroy, &fromvit);
503     no_of_from = IGRAPH_VIT_SIZE(fromvit);
504 
505     IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, mode));
506     IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist);
507 
508     already_counted = igraph_Calloc(no_of_nodes, long int);
509     if (already_counted == 0) {
510         IGRAPH_ERROR("shortest paths failed", IGRAPH_ENOMEM);
511     }
512     IGRAPH_FINALLY(free, already_counted);
513     IGRAPH_DQUEUE_INIT_FINALLY(&q, 100);
514 
515     if ( (all_to = igraph_vs_is_all(&to)) ) {
516         no_of_to = no_of_nodes;
517     } else {
518         IGRAPH_VECTOR_INIT_FINALLY(&indexv, no_of_nodes);
519         IGRAPH_CHECK(igraph_vit_create(graph, to, &tovit));
520         IGRAPH_FINALLY(igraph_vit_destroy, &tovit);
521         no_of_to = IGRAPH_VIT_SIZE(tovit);
522         for (i = 0; !IGRAPH_VIT_END(tovit); IGRAPH_VIT_NEXT(tovit)) {
523             long int v = IGRAPH_VIT_GET(tovit);
524             if (VECTOR(indexv)[v]) {
525                 IGRAPH_ERROR("Duplicate vertices in `to', this is not allowed",
526                              IGRAPH_EINVAL);
527             }
528             VECTOR(indexv)[v] = ++i;
529         }
530     }
531 
532     IGRAPH_CHECK(igraph_matrix_resize(res, no_of_from, no_of_to));
533     igraph_matrix_fill(res, my_infinity);
534 
535     for (IGRAPH_VIT_RESET(fromvit), i = 0;
536          !IGRAPH_VIT_END(fromvit);
537          IGRAPH_VIT_NEXT(fromvit), i++) {
538         long int reached = 0;
539         IGRAPH_CHECK(igraph_dqueue_push(&q, IGRAPH_VIT_GET(fromvit)));
540         IGRAPH_CHECK(igraph_dqueue_push(&q, 0));
541         already_counted[ (long int) IGRAPH_VIT_GET(fromvit) ] = i + 1;
542 
543         IGRAPH_ALLOW_INTERRUPTION();
544 
545         while (!igraph_dqueue_empty(&q)) {
546             long int act = (long int) igraph_dqueue_pop(&q);
547             long int actdist = (long int) igraph_dqueue_pop(&q);
548 
549             if (all_to) {
550                 MATRIX(*res, i, act) = actdist;
551             } else {
552                 if (VECTOR(indexv)[act]) {
553                     MATRIX(*res, i, (long int)(VECTOR(indexv)[act] - 1)) = actdist;
554                     reached++;
555                     if (reached == no_of_to) {
556                         igraph_dqueue_clear(&q);
557                         break;
558                     }
559                 }
560             }
561 
562             neis = igraph_adjlist_get(&adjlist, act);
563             for (j = 0; j < igraph_vector_int_size(neis); j++) {
564                 long int neighbor = (long int) VECTOR(*neis)[j];
565                 if (already_counted[neighbor] == i + 1) {
566                     continue;
567                 }
568                 already_counted[neighbor] = i + 1;
569                 IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor));
570                 IGRAPH_CHECK(igraph_dqueue_push(&q, actdist + 1));
571             }
572         }
573     }
574 
575     /* Clean */
576     if (!all_to) {
577         igraph_vit_destroy(&tovit);
578         igraph_vector_destroy(&indexv);
579         IGRAPH_FINALLY_CLEAN(2);
580     }
581 
582     igraph_Free(already_counted);
583     igraph_dqueue_destroy(&q);
584     igraph_vit_destroy(&fromvit);
585     igraph_adjlist_destroy(&adjlist);
586     IGRAPH_FINALLY_CLEAN(4);
587 
588     return 0;
589 }
590 
591 /**
592  * \ingroup structural
593  * \function igraph_get_shortest_paths
594  * \brief Calculates the shortest paths from/to one vertex.
595  *
596  * </para><para>
597  * If there is more than one geodesic between two vertices, this
598  * function gives only one of them.
599  * \param graph The graph object.
600  * \param vertices The result, the ids of the vertices along the paths.
601  *        This is a pointer vector, each element points to a vector
602  *        object. These should be initialized before passing them to
603  *        the function, which will properly clear and/or resize them
604  *        and fill the ids of the vertices along the geodesics from/to
605  *        the vertices. Supply a null pointer here if you don't need
606  *        these vectors.
607  * \param edges The result, the ids of the edges along the paths.
608  *        This is a pointer vector, each element points to a vector
609  *        object. These should be initialized before passing them to
610  *        the function, which will properly clear and/or resize them
611  *        and fill the ids of the vertices along the geodesics from/to
612  *        the vertices. Supply a null pointer here if you don't need
613  *        these vectors.
614  * \param from The id of the vertex from/to which the geodesics are
615  *        calculated.
616  * \param to Vertex sequence with the ids of the vertices to/from which the
617  *        shortest paths will be calculated. A vertex might be given multiple
618  *        times.
619  * \param mode The type of shortest paths to be used for the
620  *        calculation in directed graphs. Possible values:
621  *        \clist
622  *        \cli IGRAPH_OUT
623  *          the outgoing paths are calculated.
624  *        \cli IGRAPH_IN
625  *          the incoming paths are calculated.
626  *        \cli IGRAPH_ALL
627  *          the directed graph is considered as an
628  *          undirected one for the computation.
629  *        \endclist
630  * \param predecessors A pointer to an initialized igraph vector or null.
631  *        If not null, a vector containing the predecessor of each vertex in
632  *        the single source shortest path tree is returned here. The
633  *        predecessor of vertex i in the tree is the vertex from which vertex i
634  *        was reached. The predecessor of the start vertex (in the \c from
635  *        argument) is itself by definition. If the predecessor is -1, it means
636  *        that the given vertex was not reached from the source during the
637  *        search. Note that the search terminates if all the vertices in
638  *        \c to are reached.
639  * \param inbound_edges A pointer to an initialized igraph vector or null.
640  *        If not null, a vector containing the inbound edge of each vertex in
641  *        the single source shortest path tree is returned here. The
642  *        inbound edge of vertex i in the tree is the edge via which vertex i
643  *        was reached. The start vertex and vertices that were not reached
644  *        during the search will have -1 in the corresponding entry of the
645  *        vector. Note that the search terminates if all the vertices in
646  *        \c to are reached.
647  *
648  * \return Error code:
649  *        \clist
650  *        \cli IGRAPH_ENOMEM
651  *           not enough memory for temporary data.
652  *        \cli IGRAPH_EINVVID
653  *           \p from is invalid vertex id, or the length of \p to is
654  *           not the same as the length of \p res.
655  *        \cli IGRAPH_EINVMODE
656  *           invalid mode argument.
657  *        \endclist
658  *
659  * Time complexity: O(|V|+|E|),
660  * |V| is the number of vertices,
661  * |E| the number of edges in the
662  * graph.
663  *
664  * \sa \ref igraph_shortest_paths() if you only need the path length but
665  * not the paths themselves.
666  *
667  * \example examples/simple/igraph_get_shortest_paths.c
668  */
669 
670 
igraph_get_shortest_paths(const igraph_t * graph,igraph_vector_ptr_t * vertices,igraph_vector_ptr_t * edges,igraph_integer_t from,const igraph_vs_t to,igraph_neimode_t mode,igraph_vector_long_t * predecessors,igraph_vector_long_t * inbound_edges)671 int igraph_get_shortest_paths(const igraph_t *graph,
672                               igraph_vector_ptr_t *vertices,
673                               igraph_vector_ptr_t *edges,
674                               igraph_integer_t from, const igraph_vs_t to,
675                               igraph_neimode_t mode,
676                               igraph_vector_long_t *predecessors,
677                               igraph_vector_long_t *inbound_edges) {
678 
679     /* TODO: use inclist_t if to is long (longer than 1?) */
680 
681     long int no_of_nodes = igraph_vcount(graph);
682     long int *father;
683 
684     igraph_dqueue_t q = IGRAPH_DQUEUE_NULL;
685 
686     long int i, j;
687     igraph_vector_t tmp = IGRAPH_VECTOR_NULL;
688 
689     igraph_vit_t vit;
690 
691     long int to_reach;
692     long int reached = 0;
693 
694     if (from < 0 || from >= no_of_nodes) {
695         IGRAPH_ERROR("cannot get shortest paths", IGRAPH_EINVVID);
696     }
697     if (mode != IGRAPH_OUT && mode != IGRAPH_IN &&
698         mode != IGRAPH_ALL) {
699         IGRAPH_ERROR("Invalid mode argument", IGRAPH_EINVMODE);
700     }
701 
702     IGRAPH_CHECK(igraph_vit_create(graph, to, &vit));
703     IGRAPH_FINALLY(igraph_vit_destroy, &vit);
704 
705     if (vertices && IGRAPH_VIT_SIZE(vit) != igraph_vector_ptr_size(vertices)) {
706         IGRAPH_ERROR("Size of the `vertices' and the `to' should match", IGRAPH_EINVAL);
707     }
708     if (edges && IGRAPH_VIT_SIZE(vit) != igraph_vector_ptr_size(edges)) {
709         IGRAPH_ERROR("Size of the `edges' and the `to' should match", IGRAPH_EINVAL);
710     }
711 
712     father = igraph_Calloc(no_of_nodes, long int);
713     if (father == 0) {
714         IGRAPH_ERROR("cannot get shortest paths", IGRAPH_ENOMEM);
715     }
716     IGRAPH_FINALLY(igraph_free, father);
717     IGRAPH_VECTOR_INIT_FINALLY(&tmp, 0);
718     IGRAPH_DQUEUE_INIT_FINALLY(&q, 100);
719 
720     /* Mark the vertices we need to reach */
721     to_reach = IGRAPH_VIT_SIZE(vit);
722     for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) {
723         if (father[ (long int) IGRAPH_VIT_GET(vit) ] == 0) {
724             father[ (long int) IGRAPH_VIT_GET(vit) ] = -1;
725         } else {
726             to_reach--;       /* this node was given multiple times */
727         }
728     }
729 
730     /* Meaning of father[i]:
731      *
732      * - If father[i] < 0, it means that vertex i has to be reached and has not
733      *   been reached yet.
734      *
735      * - If father[i] = 0, it means that vertex i does not have to be reached and
736      *   it has not been reached yet.
737      *
738      * - If father[i] = 1, it means that vertex i is the start vertex.
739      *
740      * - Otherwise, father[i] is the ID of the edge from which vertex i was
741      *   reached plus 2.
742      */
743 
744     IGRAPH_CHECK(igraph_dqueue_push(&q, from + 1));
745     if (father[ (long int) from ] < 0) {
746         reached++;
747     }
748     father[ (long int)from ] = 1;
749 
750     while (!igraph_dqueue_empty(&q) && reached < to_reach) {
751         long int act = (long int) igraph_dqueue_pop(&q) - 1;
752 
753         IGRAPH_CHECK(igraph_incident(graph, &tmp, (igraph_integer_t) act, mode));
754         for (j = 0; j < igraph_vector_size(&tmp); j++) {
755             long int edge = (long int) VECTOR(tmp)[j];
756             long int neighbor = IGRAPH_OTHER(graph, edge, act);
757             if (father[neighbor] > 0) {
758                 continue;
759             } else if (father[neighbor] < 0) {
760                 reached++;
761             }
762             father[neighbor] = edge + 2;
763             IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor + 1));
764         }
765     }
766 
767     if (reached < to_reach) {
768         IGRAPH_WARNING("Couldn't reach some vertices");
769     }
770 
771     /* Create `predecessors' if needed */
772     if (predecessors) {
773         IGRAPH_CHECK(igraph_vector_long_resize(predecessors, no_of_nodes));
774 
775         for (i = 0; i < no_of_nodes; i++) {
776             if (father[i] <= 0) {
777                 /* i was not reached */
778                 VECTOR(*predecessors)[i] = -1;
779             } else if (father[i] == 1) {
780                 /* i is the start vertex */
781                 VECTOR(*predecessors)[i] = i;
782             } else {
783                 /* i was reached via the edge with ID = father[i] - 2 */
784                 VECTOR(*predecessors)[i] = IGRAPH_OTHER(graph, father[i] - 2, i);
785             }
786         }
787     }
788 
789     /* Create `inbound_edges' if needed */
790     if (inbound_edges) {
791         IGRAPH_CHECK(igraph_vector_long_resize(inbound_edges, no_of_nodes));
792 
793         for (i = 0; i < no_of_nodes; i++) {
794             if (father[i] <= 1) {
795                 /* i was not reached or i is the start vertex */
796                 VECTOR(*inbound_edges)[i] = -1;
797             } else {
798                 /* i was reached via the edge with ID = father[i] - 2 */
799                 VECTOR(*inbound_edges)[i] = father[i] - 2;
800             }
801         }
802     }
803 
804     /* Create `vertices' and `edges' if needed */
805     if (vertices || edges) {
806         for (IGRAPH_VIT_RESET(vit), j = 0;
807              !IGRAPH_VIT_END(vit);
808              IGRAPH_VIT_NEXT(vit), j++) {
809             long int node = IGRAPH_VIT_GET(vit);
810             igraph_vector_t *vvec = 0, *evec = 0;
811             if (vertices) {
812                 vvec = VECTOR(*vertices)[j];
813                 igraph_vector_clear(vvec);
814             }
815             if (edges) {
816                 evec = VECTOR(*edges)[j];
817                 igraph_vector_clear(evec);
818             }
819 
820             IGRAPH_ALLOW_INTERRUPTION();
821 
822             if (father[node] > 0) {
823                 long int act = node;
824                 long int size = 0;
825                 long int edge;
826                 while (father[act] > 1) {
827                     size++;
828                     edge = father[act] - 2;
829                     act = IGRAPH_OTHER(graph, edge, act);
830                 }
831                 if (vvec) {
832                     IGRAPH_CHECK(igraph_vector_resize(vvec, size + 1));
833                     VECTOR(*vvec)[size] = node;
834                 }
835                 if (evec) {
836                     IGRAPH_CHECK(igraph_vector_resize(evec, size));
837                 }
838                 act = node;
839                 while (father[act] > 1) {
840                     size--;
841                     edge = father[act] - 2;
842                     act = IGRAPH_OTHER(graph, edge, act);
843                     if (vvec) {
844                         VECTOR(*vvec)[size] = act;
845                     }
846                     if (evec) {
847                         VECTOR(*evec)[size] = edge;
848                     }
849                 }
850             }
851         }
852     }
853 
854     /* Clean */
855     igraph_Free(father);
856     igraph_dqueue_destroy(&q);
857     igraph_vector_destroy(&tmp);
858     igraph_vit_destroy(&vit);
859     IGRAPH_FINALLY_CLEAN(4);
860 
861     return 0;
862 }
863 
864 /**
865  * \function igraph_get_shortest_path
866  * Shortest path from one vertex to another one.
867  *
868  * Calculates and returns a single unweighted shortest path from a
869  * given vertex to another one. If there are more than one shortest
870  * paths between the two vertices, then an arbitrary one is returned.
871  *
872  * </para><para>This function is a wrapper to \ref
873  * igraph_get_shortest_paths(), for the special case when only one
874  * target vertex is considered.
875  * \param graph The input graph, it can be directed or
876  *        undirected. Directed paths are considered in directed
877  *        graphs.
878  * \param vertices Pointer to an initialized vector or a null
879  *        pointer. If not a null pointer, then the vertex ids along
880  *        the path are stored here, including the source and target
881  *        vertices.
882  * \param edges Pointer to an uninitialized vector or a null
883  *        pointer. If not a null pointer, then the edge ids along the
884  *        path are stored here.
885  * \param from The id of the source vertex.
886  * \param to The id of the target vertex.
887  * \param mode A constant specifying how edge directions are
888  *        considered in directed graphs. Valid modes are:
889  *        \c IGRAPH_OUT, follows edge directions;
890  *        \c IGRAPH_IN, follows the opposite directions; and
891  *        \c IGRAPH_ALL, ignores edge directions. This argument is
892  *        ignored for undirected graphs.
893  * \return Error code.
894  *
895  * Time complexity: O(|V|+|E|), linear in the number of vertices and
896  * edges in the graph.
897  *
898  * \sa \ref igraph_get_shortest_paths() for the version with more target
899  * vertices.
900  */
901 
igraph_get_shortest_path(const igraph_t * graph,igraph_vector_t * vertices,igraph_vector_t * edges,igraph_integer_t from,igraph_integer_t to,igraph_neimode_t mode)902 int igraph_get_shortest_path(const igraph_t *graph,
903                              igraph_vector_t *vertices,
904                              igraph_vector_t *edges,
905                              igraph_integer_t from,
906                              igraph_integer_t to,
907                              igraph_neimode_t mode) {
908 
909     igraph_vector_ptr_t vertices2, *vp = &vertices2;
910     igraph_vector_ptr_t edges2, *ep = &edges2;
911 
912     if (vertices) {
913         IGRAPH_CHECK(igraph_vector_ptr_init(&vertices2, 1));
914         IGRAPH_FINALLY(igraph_vector_ptr_destroy, &vertices2);
915         VECTOR(vertices2)[0] = vertices;
916     } else {
917         vp = 0;
918     }
919     if (edges) {
920         IGRAPH_CHECK(igraph_vector_ptr_init(&edges2, 1));
921         IGRAPH_FINALLY(igraph_vector_ptr_destroy, &edges2);
922         VECTOR(edges2)[0] = edges;
923     } else {
924         ep = 0;
925     }
926 
927     IGRAPH_CHECK(igraph_get_shortest_paths(graph, vp, ep, from,
928                                            igraph_vss_1(to), mode, 0, 0));
929 
930     if (edges) {
931         igraph_vector_ptr_destroy(&edges2);
932         IGRAPH_FINALLY_CLEAN(1);
933     }
934     if (vertices) {
935         igraph_vector_ptr_destroy(&vertices2);
936         IGRAPH_FINALLY_CLEAN(1);
937     }
938 
939     return 0;
940 }
941 
942 void igraph_i_gasp_paths_destroy(igraph_vector_ptr_t *v);
943 
igraph_i_gasp_paths_destroy(igraph_vector_ptr_t * v)944 void igraph_i_gasp_paths_destroy(igraph_vector_ptr_t *v) {
945     long int i;
946     for (i = 0; i < igraph_vector_ptr_size(v); i++) {
947         if (VECTOR(*v)[i] != 0) {
948             igraph_vector_destroy(VECTOR(*v)[i]);
949             igraph_Free(VECTOR(*v)[i]);
950         }
951     }
952     igraph_vector_ptr_destroy(v);
953 }
954 
955 /**
956  * \function igraph_get_all_shortest_paths
957  * \brief Finds all shortest paths (geodesics) from a vertex to all other vertices.
958  *
959  * \param graph The graph object.
960  * \param res Pointer to an initialized pointer vector, the result
961  *   will be stored here in igraph_vector_t objects. Each vector
962  *   object contains the vertices along a shortest path from \p from
963  *   to another vertex. The vectors are ordered according to their
964  *   target vertex: first the shortest paths to vertex 0, then to
965  *   vertex 1, etc. No data is included for unreachable vertices.
966  * \param nrgeo Pointer to an initialized igraph_vector_t object or
967  *   NULL. If not NULL the number of shortest paths from \p from are
968  *   stored here for every vertex in the graph. Note that the values
969  *   will be accurate only for those vertices that are in the target
970  *   vertex sequence (see \p to), since the search terminates as soon
971  *   as all the target vertices have been found.
972  * \param from The id of the vertex from/to which the geodesics are
973  *        calculated.
974  * \param to Vertex sequence with the ids of the vertices to/from which the
975  *        shortest paths will be calculated. A vertex might be given multiple
976  *        times.
977  * \param mode The type of shortest paths to be use for the
978  *        calculation in directed graphs. Possible values:
979  *        \clist
980  *        \cli IGRAPH_OUT
981  *          the lengths of the outgoing paths are calculated.
982  *        \cli IGRAPH_IN
983  *          the lengths of the incoming paths are calculated.
984  *        \cli IGRAPH_ALL
985  *          the directed graph is considered as an
986  *          undirected one for the computation.
987  *        \endclist
988  * \return Error code:
989  *        \clist
990  *        \cli IGRAPH_ENOMEM
991  *           not enough memory for temporary data.
992  *        \cli IGRAPH_EINVVID
993  *           \p from is invalid vertex id.
994  *        \cli IGRAPH_EINVMODE
995  *           invalid mode argument.
996  *        \endclist
997  *
998  * Added in version 0.2.</para><para>
999  *
1000  * Time complexity: O(|V|+|E|) for most graphs, O(|V|^2) in the worst
1001  * case.
1002  */
1003 
igraph_get_all_shortest_paths(const igraph_t * graph,igraph_vector_ptr_t * res,igraph_vector_t * nrgeo,igraph_integer_t from,const igraph_vs_t to,igraph_neimode_t mode)1004 int igraph_get_all_shortest_paths(const igraph_t *graph,
1005                                   igraph_vector_ptr_t *res,
1006                                   igraph_vector_t *nrgeo,
1007                                   igraph_integer_t from, const igraph_vs_t to,
1008                                   igraph_neimode_t mode) {
1009 
1010     long int no_of_nodes = igraph_vcount(graph);
1011     long int *geodist;
1012     igraph_vector_ptr_t paths;
1013     igraph_dqueue_t q;
1014     igraph_vector_t *vptr;
1015     igraph_vector_t neis;
1016     igraph_vector_t ptrlist;
1017     igraph_vector_t ptrhead;
1018     long int n, j, i;
1019     long int to_reach, reached = 0, maxdist = 0;
1020 
1021     igraph_vit_t vit;
1022 
1023     if (from < 0 || from >= no_of_nodes) {
1024         IGRAPH_ERROR("cannot get shortest paths", IGRAPH_EINVVID);
1025     }
1026     if (mode != IGRAPH_OUT && mode != IGRAPH_IN &&
1027         mode != IGRAPH_ALL) {
1028         IGRAPH_ERROR("Invalid mode argument", IGRAPH_EINVMODE);
1029     }
1030 
1031     IGRAPH_CHECK(igraph_vit_create(graph, to, &vit));
1032     IGRAPH_FINALLY(igraph_vit_destroy, &vit);
1033 
1034     /* paths will store the shortest paths during the search */
1035     IGRAPH_CHECK(igraph_vector_ptr_init(&paths, 0));
1036     IGRAPH_FINALLY(igraph_i_gasp_paths_destroy, &paths);
1037     /* neis is a temporary vector holding the neighbors of the
1038      * node being examined */
1039     IGRAPH_VECTOR_INIT_FINALLY(&neis, 0);
1040     /* ptrlist stores indices into the paths vector, in the order
1041      * of how they were found. ptrhead is a second-level index that
1042      * will be used to find paths that terminate in a given vertex */
1043     IGRAPH_VECTOR_INIT_FINALLY(&ptrlist, 0);
1044     /* ptrhead contains indices into ptrlist.
1045      * ptrhead[i] = j means that element #j-1 in ptrlist contains
1046      * the shortest path from the root to node i. ptrhead[i] = 0
1047      * means that node i was not reached so far */
1048     IGRAPH_VECTOR_INIT_FINALLY(&ptrhead, no_of_nodes);
1049     /* geodist[i] == 0 if i was not reached yet and it is not in the
1050      * target vertex sequence, or -1 if i was not reached yet and it
1051      * is in the target vertex sequence. Otherwise it is
1052      * one larger than the length of the shortest path from the
1053      * source */
1054     geodist = igraph_Calloc(no_of_nodes, long int);
1055     if (geodist == 0) {
1056         IGRAPH_ERROR("Cannot calculate shortest paths", IGRAPH_ENOMEM);
1057     }
1058     IGRAPH_FINALLY(igraph_free, geodist);
1059     /* dequeue to store the BFS queue -- odd elements are the vertex indices,
1060      * even elements are the distances from the root */
1061     IGRAPH_CHECK(igraph_dqueue_init(&q, 100));
1062     IGRAPH_FINALLY(igraph_dqueue_destroy, &q);
1063 
1064     if (nrgeo) {
1065         IGRAPH_CHECK(igraph_vector_resize(nrgeo, no_of_nodes));
1066         igraph_vector_null(nrgeo);
1067     }
1068 
1069     /* use geodist to count how many vertices we have to reach */
1070     to_reach = IGRAPH_VIT_SIZE(vit);
1071     for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) {
1072         if (geodist[ (long int) IGRAPH_VIT_GET(vit) ] == 0) {
1073             geodist[ (long int) IGRAPH_VIT_GET(vit) ] = -1;
1074         } else {
1075             to_reach--;       /* this node was given multiple times */
1076         }
1077     }
1078 
1079     if (geodist[ (long int) from ] < 0) {
1080         reached++;
1081     }
1082 
1083     /* from -> from */
1084     vptr = igraph_Calloc(1, igraph_vector_t); /* TODO: dirty */
1085     IGRAPH_CHECK(igraph_vector_ptr_push_back(&paths, vptr));
1086     IGRAPH_CHECK(igraph_vector_init(vptr, 1));
1087     VECTOR(*vptr)[0] = from;
1088     geodist[(long int)from] = 1;
1089     VECTOR(ptrhead)[(long int)from] = 1;
1090     IGRAPH_CHECK(igraph_vector_push_back(&ptrlist, 0));
1091     if (nrgeo) {
1092         VECTOR(*nrgeo)[(long int)from] = 1;
1093     }
1094 
1095     /* Init queue */
1096     IGRAPH_CHECK(igraph_dqueue_push(&q, from));
1097     IGRAPH_CHECK(igraph_dqueue_push(&q, 0.0));
1098     while (!igraph_dqueue_empty(&q)) {
1099         long int actnode = (long int) igraph_dqueue_pop(&q);
1100         long int actdist = (long int) igraph_dqueue_pop(&q);
1101 
1102         IGRAPH_ALLOW_INTERRUPTION();
1103 
1104         if (reached >= to_reach) {
1105             /* all nodes were reached. Since we need all the shortest paths
1106              * to all these nodes, we can stop the search only if the distance
1107              * of the current node to the root is larger than the distance of
1108              * any of the nodes we wanted to reach */
1109             if (actdist > maxdist) {
1110                 /* safety check, maxdist should have been set when we reached the last node */
1111                 if (maxdist < 0) {
1112                     IGRAPH_ERROR("possible bug in igraph_get_all_shortest_paths, "
1113                                  "maxdist is negative", IGRAPH_EINVAL);
1114                 }
1115                 break;
1116             }
1117         }
1118 
1119         IGRAPH_CHECK(igraph_neighbors(graph, &neis, (igraph_integer_t) actnode,
1120                                       mode));
1121         n = igraph_vector_size(&neis);
1122         for (j = 0; j < n; j++) {
1123             long int neighbor = (long int) VECTOR(neis)[j];
1124             long int fatherptr;
1125 
1126             if (geodist[neighbor] > 0 &&
1127                 geodist[neighbor] - 1 < actdist + 1) {
1128                 /* this node was reached via a shorter path before */
1129                 continue;
1130             }
1131 
1132             /* yay, found another shortest path to neighbor */
1133 
1134             if (nrgeo) {
1135                 /* the number of geodesics leading to neighbor must be
1136                  * increased by the number of geodesics leading to actnode */
1137                 VECTOR(*nrgeo)[neighbor] += VECTOR(*nrgeo)[actnode];
1138             }
1139             if (geodist[neighbor] <= 0) {
1140                 /* this node was not reached yet, push it into the queue */
1141                 IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor));
1142                 IGRAPH_CHECK(igraph_dqueue_push(&q, actdist + 1));
1143                 if (geodist[neighbor] < 0) {
1144                     reached++;
1145                 }
1146                 if (reached == to_reach) {
1147                     maxdist = actdist;
1148                 }
1149             }
1150             geodist[neighbor] = actdist + 2;
1151 
1152             /* copy all existing paths to the parent */
1153             fatherptr = (long int) VECTOR(ptrhead)[actnode];
1154             while (fatherptr != 0) {
1155                 /* allocate a new igraph_vector_t at the end of paths */
1156                 vptr = igraph_Calloc(1, igraph_vector_t);
1157                 IGRAPH_CHECK(igraph_vector_ptr_push_back(&paths, vptr));
1158                 IGRAPH_CHECK(igraph_vector_copy(vptr, VECTOR(paths)[fatherptr - 1]));
1159                 IGRAPH_CHECK(igraph_vector_reserve(vptr, actdist + 2));
1160                 IGRAPH_CHECK(igraph_vector_push_back(vptr, neighbor));
1161 
1162                 IGRAPH_CHECK(igraph_vector_push_back(&ptrlist,
1163                                                      VECTOR(ptrhead)[neighbor]));
1164                 VECTOR(ptrhead)[neighbor] = igraph_vector_size(&ptrlist);
1165 
1166                 fatherptr = (long int) VECTOR(ptrlist)[fatherptr - 1];
1167             }
1168         }
1169     }
1170 
1171     igraph_dqueue_destroy(&q);
1172     IGRAPH_FINALLY_CLEAN(1);
1173 
1174     /* mark the nodes for which we need the result */
1175     memset(geodist, 0, sizeof(long int) * (size_t) no_of_nodes);
1176     for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) {
1177         geodist[ (long int) IGRAPH_VIT_GET(vit) ] = 1;
1178     }
1179 
1180     /* count the number of paths in the result */
1181     n = 0;
1182     for (i = 0; i < no_of_nodes; i++) {
1183         long int fatherptr = (long int) VECTOR(ptrhead)[i];
1184         if (geodist[i] > 0) {
1185             while (fatherptr != 0) {
1186                 n++;
1187                 fatherptr = (long int) VECTOR(ptrlist)[fatherptr - 1];
1188             }
1189         }
1190     }
1191 
1192     IGRAPH_CHECK(igraph_vector_ptr_resize(res, n));
1193     j = 0;
1194     for (i = 0; i < no_of_nodes; i++) {
1195         long int fatherptr = (long int) VECTOR(ptrhead)[i];
1196 
1197         IGRAPH_ALLOW_INTERRUPTION();
1198 
1199         /* do we need the paths leading to vertex i? */
1200         if (geodist[i] > 0) {
1201             /* yes, copy them to the result vector */
1202             while (fatherptr != 0) {
1203                 VECTOR(*res)[j++] = VECTOR(paths)[fatherptr - 1];
1204                 fatherptr = (long int) VECTOR(ptrlist)[fatherptr - 1];
1205             }
1206         } else {
1207             /* no, free them */
1208             while (fatherptr != 0) {
1209                 igraph_vector_destroy(VECTOR(paths)[fatherptr - 1]);
1210                 igraph_Free(VECTOR(paths)[fatherptr - 1]);
1211                 fatherptr = (long int) VECTOR(ptrlist)[fatherptr - 1];
1212             }
1213         }
1214     }
1215 
1216     igraph_Free(geodist);
1217     igraph_vector_destroy(&ptrlist);
1218     igraph_vector_destroy(&ptrhead);
1219     igraph_vector_destroy(&neis);
1220     igraph_vector_ptr_destroy(&paths);
1221     igraph_vit_destroy(&vit);
1222     IGRAPH_FINALLY_CLEAN(6);
1223 
1224     return 0;
1225 }
1226 
1227 
1228 /**
1229  * \ingroup structural
1230  * \function igraph_subcomponent
1231  * \brief The vertices in the same component as a given vertex.
1232  *
1233  * \param graph The graph object.
1234  * \param res The result, vector with the ids of the vertices in the
1235  *        same component.
1236  * \param vertex The id of the vertex of which the component is
1237  *        searched.
1238  * \param mode Type of the component for directed graphs, possible
1239  *        values:
1240  *        \clist
1241  *        \cli IGRAPH_OUT
1242  *          the set of vertices reachable \em from the
1243  *          \p vertex,
1244  *        \cli IGRAPH_IN
1245  *          the set of vertices from which the
1246  *          \p vertex is reachable.
1247  *        \cli IGRAPH_ALL
1248  *          the graph is considered as an
1249  *          undirected graph. Note that this is \em not the same
1250  *          as the union of the previous two.
1251  *        \endclist
1252  * \return Error code:
1253  *        \clist
1254  *        \cli IGRAPH_ENOMEM
1255  *          not enough memory for temporary data.
1256  *        \cli IGRAPH_EINVVID
1257  *           \p vertex is an invalid vertex id
1258  *        \cli IGRAPH_EINVMODE
1259  *           invalid mode argument passed.
1260  *        \endclist
1261  *
1262  * Time complexity: O(|V|+|E|),
1263  * |V| and
1264  * |E| are the number of vertices and
1265  * edges in the graph.
1266  *
1267  * \sa \ref igraph_subgraph() if you want a graph object consisting only
1268  * a given set of vertices and the edges between them.
1269  */
1270 
igraph_subcomponent(const igraph_t * graph,igraph_vector_t * res,igraph_real_t vertex,igraph_neimode_t mode)1271 int igraph_subcomponent(const igraph_t *graph, igraph_vector_t *res, igraph_real_t vertex,
1272                         igraph_neimode_t mode) {
1273 
1274     long int no_of_nodes = igraph_vcount(graph);
1275     igraph_dqueue_t q = IGRAPH_DQUEUE_NULL;
1276     char *already_added;
1277     long int i;
1278     igraph_vector_t tmp = IGRAPH_VECTOR_NULL;
1279 
1280     if (!IGRAPH_FINITE(vertex) || vertex < 0 || vertex >= no_of_nodes) {
1281         IGRAPH_ERROR("subcomponent failed", IGRAPH_EINVVID);
1282     }
1283     if (mode != IGRAPH_OUT && mode != IGRAPH_IN &&
1284         mode != IGRAPH_ALL) {
1285         IGRAPH_ERROR("invalid mode argument", IGRAPH_EINVMODE);
1286     }
1287 
1288     already_added = igraph_Calloc(no_of_nodes, char);
1289     if (already_added == 0) {
1290         IGRAPH_ERROR("subcomponent failed", IGRAPH_ENOMEM);
1291     }
1292     IGRAPH_FINALLY(free, already_added); /* TODO: hack */
1293 
1294     igraph_vector_clear(res);
1295 
1296     IGRAPH_VECTOR_INIT_FINALLY(&tmp, 0);
1297     IGRAPH_DQUEUE_INIT_FINALLY(&q, 100);
1298 
1299     IGRAPH_CHECK(igraph_dqueue_push(&q, vertex));
1300     IGRAPH_CHECK(igraph_vector_push_back(res, vertex));
1301     already_added[(long int)vertex] = 1;
1302 
1303     while (!igraph_dqueue_empty(&q)) {
1304         long int actnode = (long int) igraph_dqueue_pop(&q);
1305 
1306         IGRAPH_ALLOW_INTERRUPTION();
1307 
1308         IGRAPH_CHECK(igraph_neighbors(graph, &tmp, (igraph_integer_t) actnode,
1309                                       mode));
1310         for (i = 0; i < igraph_vector_size(&tmp); i++) {
1311             long int neighbor = (long int) VECTOR(tmp)[i];
1312 
1313             if (already_added[neighbor]) {
1314                 continue;
1315             }
1316             already_added[neighbor] = 1;
1317             IGRAPH_CHECK(igraph_vector_push_back(res, neighbor));
1318             IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor));
1319         }
1320     }
1321 
1322     igraph_dqueue_destroy(&q);
1323     igraph_vector_destroy(&tmp);
1324     igraph_Free(already_added);
1325     IGRAPH_FINALLY_CLEAN(3);
1326 
1327     return 0;
1328 }
1329 
1330 /**
1331  * \ingroup structural
1332  * \function igraph_pagerank_old
1333  * \brief Calculates the Google PageRank for the specified vertices.
1334  *
1335  * </para><para>This is an old implementation,
1336  * it is provided for compatibility with igraph versions earlier than
1337  * 0.5. Please use the new implementation \ref igraph_pagerank() in
1338  * new projects.
1339  *
1340  * </para><para>
1341  * From version 0.7 this function is deprecated and its use gives a
1342  * warning message.
1343  *
1344  * </para><para>
1345  * Please note that the PageRank of a given vertex depends on the PageRank
1346  * of all other vertices, so even if you want to calculate the PageRank for
1347  * only some of the vertices, all of them must be calculated. Requesting
1348  * the PageRank for only some of the vertices does not result in any
1349  * performance increase at all.
1350  * </para>
1351  * <para>
1352  * Since the calculation is an iterative
1353  * process, the algorithm is stopped after a given count of iterations
1354  * or if the PageRank value differences between iterations are less than
1355  * a predefined value.
1356  * </para>
1357  *
1358  * <para>
1359  * For the explanation of the PageRank algorithm, see the following
1360  * webpage:
1361  * http://infolab.stanford.edu/~backrub/google.html , or the
1362  * following reference:
1363  * </para>
1364  *
1365  * <para>
1366  * Sergey Brin and Larry Page: The Anatomy of a Large-Scale Hypertextual
1367  * Web Search Engine. Proceedings of the 7th World-Wide Web Conference,
1368  * Brisbane, Australia, April 1998.
1369  * </para>
1370  * <para>
1371  * \param graph The graph object.
1372  * \param res The result vector containing the PageRank values for the
1373  * given nodes.
1374  * \param vids Vector with the vertex ids
1375  * \param directed Logical, if true directed paths will be considered
1376  *        for directed graphs. It is ignored for undirected graphs.
1377  * \param niter The maximum number of iterations to perform
1378  * \param eps The algorithm will consider the calculation as complete
1379  *        if the difference of PageRank values between iterations change
1380  *        less than this value for every node
1381  * \param damping The damping factor ("d" in the original paper)
1382  * \param old Boolean, whether to use the pre-igraph 0.5 way to
1383  *        calculate page rank. Not recommended for new applications,
1384  *        only included for compatibility. If this is non-zero then the damping
1385  *        factor is not divided by the number of vertices before adding it
1386  *        to the weighted page rank scores to calculate the
1387  *        new scores. I.e. the formula in the original PageRank paper
1388  *        is used. Furthermore, if this is non-zero then the PageRank
1389  *        vector is renormalized after each iteration.
1390  * \return Error code:
1391  *         \c IGRAPH_ENOMEM, not enough memory for
1392  *         temporary data.
1393  *         \c IGRAPH_EINVVID, invalid vertex id in
1394  *         \p vids.
1395  *
1396  * Time complexity: O(|V|+|E|) per iteration. A handful iterations
1397  * should be enough. Note that if the old-style dumping is used then
1398  * the iteration might not converge at all.
1399  *
1400  * \sa \ref igraph_pagerank() for the new implementation.
1401  */
1402 
igraph_pagerank_old(const igraph_t * graph,igraph_vector_t * res,const igraph_vs_t vids,igraph_bool_t directed,igraph_integer_t niter,igraph_real_t eps,igraph_real_t damping,igraph_bool_t old)1403 int igraph_pagerank_old(const igraph_t *graph, igraph_vector_t *res,
1404                         const igraph_vs_t vids, igraph_bool_t directed,
1405                         igraph_integer_t niter, igraph_real_t eps,
1406                         igraph_real_t damping, igraph_bool_t old) {
1407     long int no_of_nodes = igraph_vcount(graph);
1408     long int i, j, n, nodes_to_calc;
1409     igraph_real_t *prvec, *prvec_new, *prvec_aux, *prvec_scaled;
1410     igraph_vector_int_t *neis;
1411     igraph_vector_t outdegree;
1412     igraph_neimode_t dirmode;
1413     igraph_adjlist_t allneis;
1414     igraph_real_t maxdiff = eps;
1415     igraph_vit_t vit;
1416 
1417     IGRAPH_WARNING("igraph_pagerank_old is deprecated from igraph 0.7, "
1418                    "use igraph_pagerank instead");
1419 
1420     if (niter <= 0) {
1421         IGRAPH_ERROR("Invalid iteration count", IGRAPH_EINVAL);
1422     }
1423     if (eps <= 0) {
1424         IGRAPH_ERROR("Invalid epsilon value", IGRAPH_EINVAL);
1425     }
1426     if (damping <= 0 || damping >= 1) {
1427         IGRAPH_ERROR("Invalid damping factor", IGRAPH_EINVAL);
1428     }
1429 
1430     IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
1431     IGRAPH_FINALLY(igraph_vit_destroy, &vit);
1432     nodes_to_calc = IGRAPH_VIT_SIZE(vit);
1433 
1434     IGRAPH_CHECK(igraph_vector_resize(res, nodes_to_calc));
1435     igraph_vector_null(res);
1436 
1437     IGRAPH_VECTOR_INIT_FINALLY(&outdegree, no_of_nodes);
1438 
1439     prvec = igraph_Calloc(no_of_nodes, igraph_real_t);
1440     if (prvec == 0) {
1441         IGRAPH_ERROR("pagerank failed", IGRAPH_ENOMEM);
1442     }
1443     IGRAPH_FINALLY(igraph_free, prvec);
1444 
1445     prvec_new = igraph_Calloc(no_of_nodes, igraph_real_t);
1446     if (prvec_new == 0) {
1447         IGRAPH_ERROR("pagerank failed", IGRAPH_ENOMEM);
1448     }
1449     IGRAPH_FINALLY(igraph_free, prvec_new);
1450 
1451     prvec_scaled = igraph_Calloc(no_of_nodes, igraph_real_t);
1452     if (prvec_scaled == 0) {
1453         IGRAPH_ERROR("pagerank failed", IGRAPH_ENOMEM);
1454     }
1455     IGRAPH_FINALLY(igraph_free, prvec_scaled);
1456 
1457     if (directed) {
1458         dirmode = IGRAPH_IN;
1459     } else {
1460         dirmode = IGRAPH_ALL;
1461     }
1462     igraph_adjlist_init(graph, &allneis, dirmode);
1463     IGRAPH_FINALLY(igraph_adjlist_destroy, &allneis);
1464 
1465     /* Calculate outdegrees for every node */
1466     igraph_degree(graph, &outdegree, igraph_vss_all(),
1467                   directed ? IGRAPH_OUT : IGRAPH_ALL, 0);
1468     /* Initialize PageRank values */
1469     for (i = 0; i < no_of_nodes; i++) {
1470         prvec[i] = 1 - damping;
1471         /* The next line is necessary to avoid division by zero in the
1472          * calculation of prvec_scaled. This won't cause any problem,
1473          * since if a node doesn't have any outgoing links, its
1474          * prvec_scaled value won't be used anywhere */
1475         if (VECTOR(outdegree)[i] == 0) {
1476             VECTOR(outdegree)[i] = 1;
1477         }
1478     }
1479 
1480     /* We will always calculate the new PageRank values into prvec_new
1481      * based on the existing values from prvec. To avoid unnecessary
1482      * copying from prvec_new to prvec at the end of every iteration,
1483      * the pointers are swapped after every iteration */
1484     while (niter > 0 && maxdiff >= eps) {
1485         igraph_real_t sumfrom = 0, sum = 0;
1486         niter--;
1487         maxdiff = 0;
1488 
1489         /* Calculate the quotient of the actual PageRank value and the
1490          * outdegree for every node */
1491         sumfrom = 0.0; sum = 0.0;
1492         for (i = 0; i < no_of_nodes; i++) {
1493             sumfrom += prvec[i];
1494             prvec_scaled[i] = prvec[i] / VECTOR(outdegree)[i];
1495         }
1496 
1497         /* Calculate new PageRank values based on the old ones */
1498         for (i = 0; i < no_of_nodes; i++) {
1499 
1500             IGRAPH_ALLOW_INTERRUPTION();
1501 
1502             prvec_new[i] = 0;
1503             neis = igraph_adjlist_get(&allneis, i);
1504             n = igraph_vector_int_size(neis);
1505             for (j = 0; j < n; j++) {
1506                 long int neighbor = (long int) VECTOR(*neis)[j];
1507                 prvec_new[i] += prvec_scaled[neighbor];
1508             }
1509             prvec_new[i] *= damping;
1510             if (!old) {
1511                 prvec_new[i] += (1 - damping) / no_of_nodes;
1512             } else {
1513                 prvec_new[i] += (1 - damping);
1514             }
1515             sum += prvec_new[i];
1516 
1517         }
1518         for (i = 0; i < no_of_nodes; i++) {
1519             if (!old) {
1520                 prvec_new[i] /= sum;
1521             }
1522 
1523             if (prvec_new[i] - prvec[i] > maxdiff) {
1524                 maxdiff = prvec_new[i] - prvec[i];
1525             } else if (prvec[i] - prvec_new[i] > maxdiff) {
1526                 maxdiff = prvec[i] - prvec_new[i];
1527             }
1528         }
1529 
1530         /* Swap the vectors */
1531         prvec_aux = prvec_new;
1532         prvec_new = prvec;
1533         prvec = prvec_aux;
1534     }
1535 
1536     /* Copy results from prvec to res */
1537     for (IGRAPH_VIT_RESET(vit), i = 0;
1538          !IGRAPH_VIT_END(vit);
1539          IGRAPH_VIT_NEXT(vit), i++) {
1540         long int vid = IGRAPH_VIT_GET(vit);
1541         VECTOR(*res)[i] = prvec[vid];
1542     }
1543 
1544     igraph_adjlist_destroy(&allneis);
1545     igraph_vit_destroy(&vit);
1546     igraph_vector_destroy(&outdegree);
1547     igraph_Free(prvec);
1548     igraph_Free(prvec_new);
1549     igraph_Free(prvec_scaled);
1550 
1551     IGRAPH_FINALLY_CLEAN(6);
1552 
1553     return 0;
1554 }
1555 
1556 /* Not declared static so that the testsuite can use it, but not part of the public API. */
igraph_i_rewire(igraph_t * graph,igraph_integer_t n,igraph_rewiring_t mode,igraph_bool_t use_adjlist)1557 int igraph_i_rewire(igraph_t *graph, igraph_integer_t n, igraph_rewiring_t mode, igraph_bool_t use_adjlist) {
1558     long int no_of_nodes = igraph_vcount(graph);
1559     long int no_of_edges = igraph_ecount(graph);
1560     char message[256];
1561     igraph_integer_t a, b, c, d, dummy, num_swaps, num_successful_swaps;
1562     igraph_vector_t eids, edgevec, alledges;
1563     igraph_bool_t directed, loops, ok;
1564     igraph_es_t es;
1565     igraph_adjlist_t al;
1566 
1567     if (no_of_nodes < 4) {
1568         IGRAPH_ERROR("graph unsuitable for rewiring", IGRAPH_EINVAL);
1569     }
1570 
1571     directed = igraph_is_directed(graph);
1572     loops = (mode & IGRAPH_REWIRING_SIMPLE_LOOPS);
1573 
1574     RNG_BEGIN();
1575 
1576     IGRAPH_VECTOR_INIT_FINALLY(&eids, 2);
1577 
1578     if (use_adjlist) {
1579         /* As well as the sorted adjacency list, we maintain an unordered
1580          * list of edges for picking a random edge in constant time.
1581          */
1582         IGRAPH_CHECK(igraph_adjlist_init(graph, &al, IGRAPH_OUT));
1583         IGRAPH_FINALLY(igraph_adjlist_destroy, &al);
1584         IGRAPH_VECTOR_INIT_FINALLY(&alledges, no_of_edges * 2);
1585         igraph_get_edgelist(graph, &alledges, /*bycol=*/ 0);
1586     } else {
1587         IGRAPH_VECTOR_INIT_FINALLY(&edgevec, 4);
1588         es = igraph_ess_vector(&eids);
1589     }
1590 
1591     /* We don't want the algorithm to get stuck in an infinite loop when
1592      * it can't choose two edges satisfying the conditions. Instead of
1593      * this, we choose two arbitrary edges and if they have endpoints
1594      * in common, we just decrease the number of trials left and continue
1595      * (so unsuccessful rewirings still count as a trial)
1596      */
1597 
1598     num_swaps = num_successful_swaps = 0;
1599     while (num_swaps < n) {
1600 
1601         IGRAPH_ALLOW_INTERRUPTION();
1602         if (num_swaps % 1000 == 0) {
1603             snprintf(message, sizeof(message),
1604                      "Random rewiring (%.2f%% of the trials were successful)",
1605                      num_swaps > 0 ? ((100.0 * num_successful_swaps) / num_swaps) : 0.0);
1606             IGRAPH_PROGRESS(message, (100.0 * num_swaps) / n, 0);
1607         }
1608 
1609         switch (mode) {
1610         case IGRAPH_REWIRING_SIMPLE:
1611         case IGRAPH_REWIRING_SIMPLE_LOOPS:
1612             ok = 1;
1613 
1614             /* Choose two edges randomly */
1615             VECTOR(eids)[0] = RNG_INTEGER(0, no_of_edges - 1);
1616             do {
1617                 VECTOR(eids)[1] = RNG_INTEGER(0, no_of_edges - 1);
1618             } while (VECTOR(eids)[0] == VECTOR(eids)[1]);
1619 
1620             /* Get the endpoints */
1621             if (use_adjlist) {
1622                 a = VECTOR(alledges)[((igraph_integer_t)VECTOR(eids)[0]) * 2];
1623                 b = VECTOR(alledges)[(((igraph_integer_t)VECTOR(eids)[0]) * 2) + 1];
1624                 c = VECTOR(alledges)[((igraph_integer_t)VECTOR(eids)[1]) * 2];
1625                 d = VECTOR(alledges)[(((igraph_integer_t)VECTOR(eids)[1]) * 2) + 1];
1626             } else {
1627                 IGRAPH_CHECK(igraph_edge(graph, (igraph_integer_t) VECTOR(eids)[0],
1628                                          &a, &b));
1629                 IGRAPH_CHECK(igraph_edge(graph, (igraph_integer_t) VECTOR(eids)[1],
1630                                          &c, &d));
1631             }
1632 
1633             /* For an undirected graph, we have two "variants" of each edge, i.e.
1634              * a -- b and b -- a. Since some rewirings can be performed only when we
1635              * "swap" the endpoints, we do it now with probability 0.5 */
1636             if (!directed && RNG_UNIF01() < 0.5) {
1637                 dummy = c; c = d; d = dummy;
1638                 if (use_adjlist) {
1639                     /* Flip the edge in the unordered edge-list, so the update later on
1640                      * hits the correct end. */
1641                     VECTOR(alledges)[((igraph_integer_t)VECTOR(eids)[1]) * 2] = c;
1642                     VECTOR(alledges)[(((igraph_integer_t)VECTOR(eids)[1]) * 2) + 1] = d;
1643                 }
1644             }
1645 
1646             /* If we do not touch loops, check whether a == b or c == d and disallow
1647              * the swap if needed */
1648             if (!loops && (a == b || c == d)) {
1649                 ok = 0;
1650             } else {
1651                 /* Check whether they are suitable for rewiring */
1652                 if (a == c || b == d) {
1653                     /* Swapping would have no effect */
1654                     ok = 0;
1655                 } else {
1656                     /* a != c && b != d */
1657                     /* If a == d or b == c, the swap would generate at least one loop, so
1658                      * we disallow them unless we want to have loops */
1659                     ok = loops || (a != d && b != c);
1660                     /* Also, if a == b and c == d and we allow loops, doing the swap
1661                      * would result in a multiple edge if the graph is undirected */
1662                     ok = ok && (directed || a != b || c != d);
1663                 }
1664             }
1665 
1666             /* All good so far. Now check for the existence of a --> d and c --> b to
1667              * disallow the creation of multiple edges */
1668             if (ok) {
1669                 if (use_adjlist) {
1670                     if (igraph_adjlist_has_edge(&al, a, d, directed)) {
1671                         ok = 0;
1672                     }
1673                 } else {
1674                     IGRAPH_CHECK(igraph_are_connected(graph, a, d, &ok));
1675                     ok = !ok;
1676                 }
1677             }
1678             if (ok) {
1679                 if (use_adjlist) {
1680                     if (igraph_adjlist_has_edge(&al, c, b, directed)) {
1681                         ok = 0;
1682                     }
1683                 } else {
1684                     IGRAPH_CHECK(igraph_are_connected(graph, c, b, &ok));
1685                     ok = !ok;
1686                 }
1687             }
1688 
1689             /* If we are still okay, we can perform the rewiring */
1690             if (ok) {
1691                 /* printf("Deleting: %ld -> %ld, %ld -> %ld\n",
1692                               (long)a, (long)b, (long)c, (long)d); */
1693                 if (use_adjlist) {
1694                     // Replace entry in sorted adjlist:
1695                     IGRAPH_CHECK(igraph_adjlist_replace_edge(&al, a, b, d, directed));
1696                     IGRAPH_CHECK(igraph_adjlist_replace_edge(&al, c, d, b, directed));
1697                     // Also replace in unsorted edgelist:
1698                     VECTOR(alledges)[(((igraph_integer_t)VECTOR(eids)[0]) * 2) + 1] = d;
1699                     VECTOR(alledges)[(((igraph_integer_t)VECTOR(eids)[1]) * 2) + 1] = b;
1700                 } else {
1701                     IGRAPH_CHECK(igraph_delete_edges(graph, es));
1702                     VECTOR(edgevec)[0] = a; VECTOR(edgevec)[1] = d;
1703                     VECTOR(edgevec)[2] = c; VECTOR(edgevec)[3] = b;
1704                     /* printf("Adding: %ld -> %ld, %ld -> %ld\n",
1705                                 (long)a, (long)d, (long)c, (long)b); */
1706                     igraph_add_edges(graph, &edgevec, 0);
1707                 }
1708                 num_successful_swaps++;
1709             }
1710             break;
1711         default:
1712             RNG_END();
1713             IGRAPH_ERROR("unknown rewiring mode", IGRAPH_EINVMODE);
1714         }
1715         num_swaps++;
1716     }
1717 
1718     if (use_adjlist) {
1719         /* Replace graph edges with the adjlist current state */
1720         IGRAPH_CHECK(igraph_delete_edges(graph, igraph_ess_all(IGRAPH_EDGEORDER_ID)));
1721         IGRAPH_CHECK(igraph_add_edges(graph, &alledges, 0));
1722     }
1723 
1724     IGRAPH_PROGRESS("Random rewiring: ", 100.0, 0);
1725 
1726     if (use_adjlist) {
1727         igraph_vector_destroy(&alledges);
1728         igraph_adjlist_destroy(&al);
1729     } else {
1730         igraph_vector_destroy(&edgevec);
1731     }
1732 
1733     igraph_vector_destroy(&eids);
1734     IGRAPH_FINALLY_CLEAN(use_adjlist ? 3 : 2);
1735 
1736     RNG_END();
1737 
1738     return 0;
1739 }
1740 
1741 /**
1742  * \ingroup structural
1743  * \function igraph_rewire
1744  * \brief Randomly rewires a graph while preserving the degree distribution.
1745  *
1746  * </para><para>
1747  * This function generates a new graph based on the original one by randomly
1748  * rewiring edges while preserving the original graph's degree distribution.
1749  * Please note that the rewiring is done "in place", so no new graph will
1750  * be allocated. If you would like to keep the original graph intact, use
1751  * \ref igraph_copy() beforehand.
1752  *
1753  * \param graph The graph object to be rewired.
1754  * \param n Number of rewiring trials to perform.
1755  * \param mode The rewiring algorithm to be used. It can be one of the following flags:
1756  *         \clist
1757  *           \cli IGRAPH_REWIRING_SIMPLE
1758  *                Simple rewiring algorithm which chooses two arbitrary edges
1759  *                in each step (namely (a,b) and (c,d)) and substitutes them
1760  *                with (a,d) and (c,b) if they don't exist.  The method will
1761  *                neither destroy nor create self-loops.
1762  *           \cli IGRAPH_REWIRING_SIMPLE_LOOPS
1763  *                Same as \c IGRAPH_REWIRING_SIMPLE but allows the creation or
1764  *                destruction of self-loops.
1765  *         \endclist
1766  *
1767  * \return Error code:
1768  *         \clist
1769  *           \cli IGRAPH_EINVMODE
1770  *                Invalid rewiring mode.
1771  *           \cli IGRAPH_EINVAL
1772  *                Graph unsuitable for rewiring (e.g. it has
1773  *                less than 4 nodes in case of \c IGRAPH_REWIRING_SIMPLE)
1774  *           \cli IGRAPH_ENOMEM
1775  *                Not enough memory for temporary data.
1776  *         \endclist
1777  *
1778  * Time complexity: TODO.
1779  *
1780  * \example examples/simple/igraph_rewire.c
1781  */
1782 
1783 #define REWIRE_ADJLIST_THRESHOLD 10
1784 
igraph_rewire(igraph_t * graph,igraph_integer_t n,igraph_rewiring_t mode)1785 int igraph_rewire(igraph_t *graph, igraph_integer_t n, igraph_rewiring_t mode) {
1786 
1787     igraph_bool_t use_adjlist = n >= REWIRE_ADJLIST_THRESHOLD;
1788     return igraph_i_rewire(graph, n, mode, use_adjlist);
1789 
1790 }
1791 
1792 /**
1793  * Subgraph creation, old version: it copies the graph and then deletes
1794  * unneeded vertices.
1795  */
igraph_i_subgraph_copy_and_delete(const igraph_t * graph,igraph_t * res,const igraph_vs_t vids,igraph_vector_t * map,igraph_vector_t * invmap)1796 int igraph_i_subgraph_copy_and_delete(const igraph_t *graph, igraph_t *res,
1797                                       const igraph_vs_t vids,
1798                                       igraph_vector_t *map,
1799                                       igraph_vector_t *invmap) {
1800     long int no_of_nodes = igraph_vcount(graph);
1801     igraph_vector_t delete = IGRAPH_VECTOR_NULL;
1802     char *remain;
1803     long int i;
1804     igraph_vit_t vit;
1805 
1806     IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
1807     IGRAPH_FINALLY(igraph_vit_destroy, &vit);
1808 
1809     IGRAPH_VECTOR_INIT_FINALLY(&delete, 0);
1810     remain = igraph_Calloc(no_of_nodes, char);
1811     if (remain == 0) {
1812         IGRAPH_ERROR("subgraph failed", IGRAPH_ENOMEM);
1813     }
1814     IGRAPH_FINALLY(free, remain); /* TODO: hack */
1815     IGRAPH_CHECK(igraph_vector_reserve(&delete, no_of_nodes - IGRAPH_VIT_SIZE(vit)));
1816 
1817     for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) {
1818         remain[ (long int) IGRAPH_VIT_GET(vit) ] = 1;
1819     }
1820 
1821     for (i = 0; i < no_of_nodes; i++) {
1822 
1823         IGRAPH_ALLOW_INTERRUPTION();
1824 
1825         if (remain[i] == 0) {
1826             IGRAPH_CHECK(igraph_vector_push_back(&delete, i));
1827         }
1828     }
1829 
1830     igraph_Free(remain);
1831     IGRAPH_FINALLY_CLEAN(1);
1832 
1833     /* must set res->attr to 0 before calling igraph_copy */
1834     res->attr = 0;         /* Why is this needed? TODO */
1835     IGRAPH_CHECK(igraph_copy(res, graph));
1836     IGRAPH_FINALLY(igraph_destroy, res);
1837     IGRAPH_CHECK(igraph_delete_vertices_idx(res, igraph_vss_vector(&delete),
1838                                             map, invmap));
1839 
1840     igraph_vector_destroy(&delete);
1841     igraph_vit_destroy(&vit);
1842     IGRAPH_FINALLY_CLEAN(3);
1843     return 0;
1844 }
1845 
1846 /**
1847  * Subgraph creation, new version: creates the new graph instead of
1848  * copying the old one.
1849  */
igraph_i_subgraph_create_from_scratch(const igraph_t * graph,igraph_t * res,const igraph_vs_t vids,igraph_vector_t * map,igraph_vector_t * invmap)1850 int igraph_i_subgraph_create_from_scratch(const igraph_t *graph,
1851         igraph_t *res,
1852         const igraph_vs_t vids,
1853         igraph_vector_t *map,
1854         igraph_vector_t *invmap) {
1855     igraph_bool_t directed = igraph_is_directed(graph);
1856     long int no_of_nodes = igraph_vcount(graph);
1857     long int no_of_new_nodes = 0;
1858     long int i, j, n;
1859     long int to;
1860     igraph_integer_t eid;
1861     igraph_vector_t vids_old2new, vids_new2old;
1862     igraph_vector_t eids_new2old;
1863     igraph_vector_t nei_edges;
1864     igraph_vector_t new_edges;
1865     igraph_vit_t vit;
1866     igraph_vector_t *my_vids_old2new = &vids_old2new,
1867                      *my_vids_new2old = &vids_new2old;
1868 
1869     /* The order of initialization is important here, they will be destroyed in the
1870      * opposite order */
1871     IGRAPH_VECTOR_INIT_FINALLY(&eids_new2old, 0);
1872     if (invmap) {
1873         my_vids_new2old = invmap;
1874         igraph_vector_clear(my_vids_new2old);
1875     } else {
1876         IGRAPH_VECTOR_INIT_FINALLY(&vids_new2old, 0);
1877     }
1878     IGRAPH_VECTOR_INIT_FINALLY(&new_edges, 0);
1879     IGRAPH_VECTOR_INIT_FINALLY(&nei_edges, 0);
1880     if (map) {
1881         my_vids_old2new = map;
1882         IGRAPH_CHECK(igraph_vector_resize(map, no_of_nodes));
1883         igraph_vector_null(map);
1884     } else {
1885         IGRAPH_VECTOR_INIT_FINALLY(&vids_old2new, no_of_nodes);
1886     }
1887 
1888     IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
1889     IGRAPH_FINALLY(igraph_vit_destroy, &vit);
1890 
1891     /* Calculate the mapping from the old node IDs to the new ones. The other
1892      * igraph_simplify implementation in igraph_i_simplify_copy_and_delete
1893      * ensures that the order of vertex IDs is kept during remapping (i.e.
1894      * if the old ID of vertex A is less than the old ID of vertex B, then
1895      * the same will also be true for the new IDs). To ensure compatibility
1896      * with the other implementation, we have to fetch the vertex IDs into
1897      * a vector first and then sort it. We temporarily use new_edges for that.
1898      */
1899     IGRAPH_CHECK(igraph_vit_as_vector(&vit, &nei_edges));
1900     igraph_vit_destroy(&vit);
1901     IGRAPH_FINALLY_CLEAN(1);
1902 
1903     igraph_vector_sort(&nei_edges);
1904     n = igraph_vector_size(&nei_edges);
1905     for (i = 0; i < n; i++) {
1906         long int vid = (long int) VECTOR(nei_edges)[i];
1907         if (VECTOR(*my_vids_old2new)[vid] == 0) {
1908             IGRAPH_CHECK(igraph_vector_push_back(my_vids_new2old, vid));
1909             no_of_new_nodes++;
1910             VECTOR(*my_vids_old2new)[vid] = no_of_new_nodes;
1911         }
1912     }
1913 
1914     /* Create the new edge list */
1915     for (i = 0; i < no_of_new_nodes; i++) {
1916         long int old_vid = (long int) VECTOR(*my_vids_new2old)[i];
1917         long int new_vid = i;
1918         igraph_bool_t skip_loop_edge;
1919 
1920         IGRAPH_CHECK(igraph_incident(graph, &nei_edges, old_vid, IGRAPH_OUT));
1921         n = igraph_vector_size(&nei_edges);
1922 
1923         if (directed) {
1924             /* directed graph; this is easier */
1925             for (j = 0; j < n; j++) {
1926                 eid = (igraph_integer_t) VECTOR(nei_edges)[j];
1927 
1928                 to = (long int) VECTOR(*my_vids_old2new)[ (long int)IGRAPH_TO(graph, eid) ];
1929                 if (!to) {
1930                     continue;
1931                 }
1932 
1933                 IGRAPH_CHECK(igraph_vector_push_back(&new_edges, new_vid));
1934                 IGRAPH_CHECK(igraph_vector_push_back(&new_edges, to - 1));
1935                 IGRAPH_CHECK(igraph_vector_push_back(&eids_new2old, eid));
1936             }
1937         } else {
1938             /* undirected graph. We need to be careful with loop edges as each
1939              * loop edge will appear twice. We use a boolean flag to skip every
1940              * second loop edge */
1941             skip_loop_edge = 0;
1942             for (j = 0; j < n; j++) {
1943                 eid = (igraph_integer_t) VECTOR(nei_edges)[j];
1944 
1945                 if (IGRAPH_FROM(graph, eid) != old_vid) {
1946                     /* avoid processing edges twice */
1947                     continue;
1948                 }
1949 
1950                 to = (long int) VECTOR(*my_vids_old2new)[ (long int)IGRAPH_TO(graph, eid) ];
1951                 if (!to) {
1952                     continue;
1953                 }
1954                 to -= 1;
1955 
1956                 if (new_vid == to) {
1957                     /* this is a loop edge; check whether we need to skip it */
1958                     skip_loop_edge = !skip_loop_edge;
1959                     if (skip_loop_edge) {
1960                         continue;
1961                     }
1962                 }
1963 
1964                 IGRAPH_CHECK(igraph_vector_push_back(&new_edges, new_vid));
1965                 IGRAPH_CHECK(igraph_vector_push_back(&new_edges, to));
1966                 IGRAPH_CHECK(igraph_vector_push_back(&eids_new2old, eid));
1967             }
1968         }
1969     }
1970 
1971     /* Get rid of some vectors that are not needed anymore */
1972     if (!map) {
1973         igraph_vector_destroy(&vids_old2new);
1974         IGRAPH_FINALLY_CLEAN(1);
1975     }
1976     igraph_vector_destroy(&nei_edges);
1977     IGRAPH_FINALLY_CLEAN(1);
1978 
1979     /* Create the new graph */
1980     IGRAPH_CHECK(igraph_create(res, &new_edges, (igraph_integer_t)
1981                                no_of_new_nodes, directed));
1982     IGRAPH_I_ATTRIBUTE_DESTROY(res);
1983 
1984     /* Now we can also get rid of the new_edges vector */
1985     igraph_vector_destroy(&new_edges);
1986     IGRAPH_FINALLY_CLEAN(1);
1987 
1988     /* Make sure that the newly created graph is destroyed if something happens from
1989      * now on */
1990     IGRAPH_FINALLY(igraph_destroy, res);
1991 
1992     /* Copy the graph attributes */
1993     IGRAPH_CHECK(igraph_i_attribute_copy(res, graph,
1994                                          /* ga = */ 1, /* va = */ 0, /* ea = */ 0));
1995 
1996     /* Copy the vertex attributes */
1997     IGRAPH_CHECK(igraph_i_attribute_permute_vertices(graph, res,
1998                  my_vids_new2old));
1999 
2000     /* Copy the edge attributes */
2001     IGRAPH_CHECK(igraph_i_attribute_permute_edges(graph, res, &eids_new2old));
2002 
2003     if (!invmap) {
2004         igraph_vector_destroy(my_vids_new2old);
2005         IGRAPH_FINALLY_CLEAN(1);
2006     }
2007     igraph_vector_destroy(&eids_new2old);
2008     IGRAPH_FINALLY_CLEAN(2);   /* 1 + 1 since we don't need to destroy res */
2009 
2010     return 0;
2011 }
2012 
2013 /**
2014  * \ingroup structural
2015  * \function igraph_subgraph
2016  * \brief Creates a subgraph induced by the specified vertices.
2017  *
2018  * </para><para>
2019  * This function is an alias to \ref igraph_induced_subgraph(), it is
2020  * left here to ensure API compatibility with igraph versions prior to 0.6.
2021  *
2022  * </para><para>
2023  * This function collects the specified vertices and all edges between
2024  * them to a new graph.
2025  * As the vertex ids in a graph always start with zero, this function
2026  * very likely needs to reassign ids to the vertices.
2027  * \param graph The graph object.
2028  * \param res The subgraph, another graph object will be stored here,
2029  *        do \em not initialize this object before calling this
2030  *        function, and call \ref igraph_destroy() on it if you don't need
2031  *        it any more.
2032  * \param vids A vertex selector describing which vertices to keep.
2033  * \return Error code:
2034  *         \c IGRAPH_ENOMEM, not enough memory for
2035  *         temporary data.
2036  *         \c IGRAPH_EINVVID, invalid vertex id in
2037  *         \p vids.
2038  *
2039  * Time complexity: O(|V|+|E|),
2040  * |V| and
2041  * |E| are the number of vertices and
2042  * edges in the original graph.
2043  *
2044  * \sa \ref igraph_delete_vertices() to delete the specified set of
2045  * vertices from a graph, the opposite of this function.
2046  */
2047 
igraph_subgraph(const igraph_t * graph,igraph_t * res,const igraph_vs_t vids)2048 int igraph_subgraph(const igraph_t *graph, igraph_t *res,
2049                     const igraph_vs_t vids) {
2050     IGRAPH_WARNING("igraph_subgraph is deprecated from igraph 0.6, "
2051                    "use igraph_induced_subgraph instead");
2052     return igraph_induced_subgraph(graph, res, vids, IGRAPH_SUBGRAPH_AUTO);
2053 }
2054 
2055 /**
2056  * \ingroup structural
2057  * \function igraph_induced_subgraph
2058  * \brief Creates a subgraph induced by the specified vertices.
2059  *
2060  * </para><para>
2061  * This function collects the specified vertices and all edges between
2062  * them to a new graph.
2063  * As the vertex ids in a graph always start with zero, this function
2064  * very likely needs to reassign ids to the vertices.
2065  * \param graph The graph object.
2066  * \param res The subgraph, another graph object will be stored here,
2067  *        do \em not initialize this object before calling this
2068  *        function, and call \ref igraph_destroy() on it if you don't need
2069  *        it any more.
2070  * \param vids A vertex selector describing which vertices to keep.
2071  * \param impl This parameter selects which implementation should we
2072  *        use when constructing the new graph. Basically there are two
2073  *        possibilities: \c IGRAPH_SUBGRAPH_COPY_AND_DELETE copies the
2074  *        existing graph and deletes the vertices that are not needed
2075  *        in the new graph, while \c IGRAPH_SUBGRAPH_CREATE_FROM_SCRATCH
2076  *        constructs the new graph from scratch without copying the old
2077  *        one. The latter is more efficient if you are extracting a
2078  *        relatively small subpart of a very large graph, while the
2079  *        former is better if you want to extract a subgraph whose size
2080  *        is comparable to the size of the whole graph. There is a third
2081  *        possibility: \c IGRAPH_SUBGRAPH_AUTO will select one of the
2082  *        two methods automatically based on the ratio of the number
2083  *        of vertices in the new and the old graph.
2084  *
2085  * \return Error code:
2086  *         \c IGRAPH_ENOMEM, not enough memory for
2087  *         temporary data.
2088  *         \c IGRAPH_EINVVID, invalid vertex id in
2089  *         \p vids.
2090  *
2091  * Time complexity: O(|V|+|E|),
2092  * |V| and
2093  * |E| are the number of vertices and
2094  * edges in the original graph.
2095  *
2096  * \sa \ref igraph_delete_vertices() to delete the specified set of
2097  * vertices from a graph, the opposite of this function.
2098  */
igraph_induced_subgraph(const igraph_t * graph,igraph_t * res,const igraph_vs_t vids,igraph_subgraph_implementation_t impl)2099 int igraph_induced_subgraph(const igraph_t *graph, igraph_t *res,
2100                             const igraph_vs_t vids, igraph_subgraph_implementation_t impl) {
2101     return igraph_induced_subgraph_map(graph, res, vids, impl, /* map= */ 0,
2102                                        /* invmap= */ 0);
2103 }
2104 
igraph_i_induced_subgraph_suggest_implementation(const igraph_t * graph,const igraph_vs_t vids,igraph_subgraph_implementation_t * result)2105 int igraph_i_induced_subgraph_suggest_implementation(
2106     const igraph_t *graph, const igraph_vs_t vids,
2107     igraph_subgraph_implementation_t *result) {
2108     double ratio;
2109     igraph_integer_t num_vs;
2110 
2111     if (igraph_vs_is_all(&vids)) {
2112         ratio = 1.0;
2113     } else {
2114         IGRAPH_CHECK(igraph_vs_size(graph, &vids, &num_vs));
2115         ratio = (igraph_real_t) num_vs / igraph_vcount(graph);
2116     }
2117 
2118     /* TODO: needs benchmarking; threshold was chosen totally arbitrarily */
2119     if (ratio > 0.5) {
2120         *result = IGRAPH_SUBGRAPH_COPY_AND_DELETE;
2121     } else {
2122         *result = IGRAPH_SUBGRAPH_CREATE_FROM_SCRATCH;
2123     }
2124 
2125     return 0;
2126 }
2127 
igraph_induced_subgraph_map(const igraph_t * graph,igraph_t * res,const igraph_vs_t vids,igraph_subgraph_implementation_t impl,igraph_vector_t * map,igraph_vector_t * invmap)2128 int igraph_induced_subgraph_map(const igraph_t *graph, igraph_t *res,
2129                                 const igraph_vs_t vids,
2130                                 igraph_subgraph_implementation_t impl,
2131                                 igraph_vector_t *map,
2132                                 igraph_vector_t *invmap) {
2133 
2134     if (impl == IGRAPH_SUBGRAPH_AUTO) {
2135         IGRAPH_CHECK(igraph_i_induced_subgraph_suggest_implementation(graph, vids, &impl));
2136     }
2137 
2138     switch (impl) {
2139     case IGRAPH_SUBGRAPH_COPY_AND_DELETE:
2140         return igraph_i_subgraph_copy_and_delete(graph, res, vids, map, invmap);
2141 
2142     case IGRAPH_SUBGRAPH_CREATE_FROM_SCRATCH:
2143         return igraph_i_subgraph_create_from_scratch(graph, res, vids, map,
2144                 invmap);
2145 
2146     default:
2147         IGRAPH_ERROR("unknown subgraph implementation type", IGRAPH_EINVAL);
2148     }
2149     return 0;
2150 }
2151 
2152 /**
2153  * \ingroup structural
2154  * \function igraph_subgraph_edges
2155  * \brief Creates a subgraph with the specified edges and their endpoints.
2156  *
2157  * </para><para>
2158  * This function collects the specified edges and their endpoints to a new
2159  * graph.
2160  * As the vertex ids in a graph always start with zero, this function
2161  * very likely needs to reassign ids to the vertices.
2162  * \param graph The graph object.
2163  * \param res The subgraph, another graph object will be stored here,
2164  *        do \em not initialize this object before calling this
2165  *        function, and call \ref igraph_destroy() on it if you don't need
2166  *        it any more.
2167  * \param eids An edge selector describing which edges to keep.
2168  * \param delete_vertices Whether to delete the vertices not incident on any
2169  *        of the specified edges as well. If \c FALSE, the number of vertices
2170  *        in the result graph will always be equal to the number of vertices
2171  *        in the input graph.
2172  * \return Error code:
2173  *         \c IGRAPH_ENOMEM, not enough memory for
2174  *         temporary data.
2175  *         \c IGRAPH_EINVEID, invalid edge id in
2176  *         \p eids.
2177  *
2178  * Time complexity: O(|V|+|E|),
2179  * |V| and
2180  * |E| are the number of vertices and
2181  * edges in the original graph.
2182  *
2183  * \sa \ref igraph_delete_edges() to delete the specified set of
2184  * edges from a graph, the opposite of this function.
2185  */
2186 
igraph_subgraph_edges(const igraph_t * graph,igraph_t * res,const igraph_es_t eids,igraph_bool_t delete_vertices)2187 int igraph_subgraph_edges(const igraph_t *graph, igraph_t *res,
2188                           const igraph_es_t eids, igraph_bool_t delete_vertices) {
2189 
2190     long int no_of_nodes = igraph_vcount(graph);
2191     long int no_of_edges = igraph_ecount(graph);
2192     igraph_vector_t delete = IGRAPH_VECTOR_NULL;
2193     char *vremain, *eremain;
2194     long int i;
2195     igraph_eit_t eit;
2196 
2197     IGRAPH_CHECK(igraph_eit_create(graph, eids, &eit));
2198     IGRAPH_FINALLY(igraph_eit_destroy, &eit);
2199 
2200     IGRAPH_VECTOR_INIT_FINALLY(&delete, 0);
2201     vremain = igraph_Calloc(no_of_nodes, char);
2202     if (vremain == 0) {
2203         IGRAPH_ERROR("subgraph_edges failed", IGRAPH_ENOMEM);
2204     }
2205     eremain = igraph_Calloc(no_of_edges, char);
2206     if (eremain == 0) {
2207         IGRAPH_ERROR("subgraph_edges failed", IGRAPH_ENOMEM);
2208     }
2209     IGRAPH_FINALLY(free, vremain);    /* TODO: hack */
2210     IGRAPH_FINALLY(free, eremain);    /* TODO: hack */
2211     IGRAPH_CHECK(igraph_vector_reserve(&delete, no_of_edges - IGRAPH_EIT_SIZE(eit)));
2212 
2213     /* Collect the vertex and edge IDs that will remain */
2214     for (IGRAPH_EIT_RESET(eit); !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) {
2215         igraph_integer_t from, to;
2216         long int eid = (long int) IGRAPH_EIT_GET(eit);
2217         IGRAPH_CHECK(igraph_edge(graph, (igraph_integer_t) eid, &from, &to));
2218         eremain[eid] = vremain[(long int)from] = vremain[(long int)to] = 1;
2219     }
2220 
2221     /* Collect the edge IDs to be deleted */
2222     for (i = 0; i < no_of_edges; i++) {
2223         IGRAPH_ALLOW_INTERRUPTION();
2224         if (eremain[i] == 0) {
2225             IGRAPH_CHECK(igraph_vector_push_back(&delete, i));
2226         }
2227     }
2228 
2229     igraph_Free(eremain);
2230     IGRAPH_FINALLY_CLEAN(1);
2231 
2232     /* Delete the unnecessary edges */
2233     /* must set res->attr to 0 before calling igraph_copy */
2234     res->attr = 0;         /* Why is this needed? TODO */
2235     IGRAPH_CHECK(igraph_copy(res, graph));
2236     IGRAPH_FINALLY(igraph_destroy, res);
2237     IGRAPH_CHECK(igraph_delete_edges(res, igraph_ess_vector(&delete)));
2238 
2239     if (delete_vertices) {
2240         /* Collect the vertex IDs to be deleted */
2241         igraph_vector_clear(&delete);
2242         for (i = 0; i < no_of_nodes; i++) {
2243             IGRAPH_ALLOW_INTERRUPTION();
2244             if (vremain[i] == 0) {
2245                 IGRAPH_CHECK(igraph_vector_push_back(&delete, i));
2246             }
2247         }
2248     }
2249 
2250     igraph_Free(vremain);
2251     IGRAPH_FINALLY_CLEAN(1);
2252 
2253     /* Delete the unnecessary vertices */
2254     if (delete_vertices) {
2255         IGRAPH_CHECK(igraph_delete_vertices(res, igraph_vss_vector(&delete)));
2256     }
2257 
2258     igraph_vector_destroy(&delete);
2259     igraph_eit_destroy(&eit);
2260     IGRAPH_FINALLY_CLEAN(3);
2261     return 0;
2262 }
2263 
2264 void igraph_i_simplify_free(igraph_vector_ptr_t *p);
2265 
igraph_i_simplify_free(igraph_vector_ptr_t * p)2266 void igraph_i_simplify_free(igraph_vector_ptr_t *p) {
2267     long int i, n = igraph_vector_ptr_size(p);
2268     for (i = 0; i < n; i++) {
2269         igraph_vector_t *v = VECTOR(*p)[i];
2270         if (v) {
2271             igraph_vector_destroy(v);
2272         }
2273     }
2274     igraph_vector_ptr_destroy(p);
2275 }
2276 
2277 /**
2278  * \ingroup structural
2279  * \function igraph_simplify
2280  * \brief Removes loop and/or multiple edges from the graph.
2281  *
2282  * \param graph The graph object.
2283  * \param multiple Logical, if true, multiple edges will be removed.
2284  * \param loops Logical, if true, loops (self edges) will be removed.
2285  * \param edge_comb What to do with the edge attributes. See the igraph
2286  *        manual section about attributes for details.
2287  * \return Error code:
2288  *    \c IGRAPH_ENOMEM if we are out of memory.
2289  *
2290  * Time complexity: O(|V|+|E|).
2291  *
2292  * \example examples/simple/igraph_simplify.c
2293  */
2294 
igraph_simplify(igraph_t * graph,igraph_bool_t multiple,igraph_bool_t loops,const igraph_attribute_combination_t * edge_comb)2295 int igraph_simplify(igraph_t *graph, igraph_bool_t multiple,
2296                     igraph_bool_t loops,
2297                     const igraph_attribute_combination_t *edge_comb) {
2298 
2299     igraph_vector_t edges = IGRAPH_VECTOR_NULL;
2300     long int no_of_nodes = igraph_vcount(graph);
2301     long int no_of_edges = igraph_ecount(graph);
2302     long int edge;
2303     igraph_bool_t attr = edge_comb && igraph_has_attribute_table();
2304     long int from, to, pfrom = -1, pto = -2;
2305     igraph_t res;
2306     igraph_es_t es;
2307     igraph_eit_t eit;
2308     igraph_vector_t mergeinto;
2309     long int actedge;
2310 
2311     if (!multiple && !loops)
2312         /* nothing to do */
2313     {
2314         return IGRAPH_SUCCESS;
2315     }
2316 
2317     if (!multiple) {
2318         /* removing loop edges only, this is simple. No need to combine anything
2319          * and the whole process can be done in-place */
2320         IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
2321         IGRAPH_CHECK(igraph_es_all(&es, IGRAPH_EDGEORDER_ID));
2322         IGRAPH_FINALLY(igraph_es_destroy, &es);
2323         IGRAPH_CHECK(igraph_eit_create(graph, es, &eit));
2324         IGRAPH_FINALLY(igraph_eit_destroy, &eit);
2325 
2326         while (!IGRAPH_EIT_END(eit)) {
2327             edge = IGRAPH_EIT_GET(eit);
2328             from = IGRAPH_FROM(graph, edge);
2329             to = IGRAPH_TO(graph, edge);
2330             if (from == to) {
2331                 IGRAPH_CHECK(igraph_vector_push_back(&edges, edge));
2332             }
2333             IGRAPH_EIT_NEXT(eit);
2334         }
2335 
2336         igraph_eit_destroy(&eit);
2337         igraph_es_destroy(&es);
2338         IGRAPH_FINALLY_CLEAN(2);
2339 
2340         if (igraph_vector_size(&edges) > 0) {
2341             IGRAPH_CHECK(igraph_delete_edges(graph, igraph_ess_vector(&edges)));
2342         }
2343 
2344         igraph_vector_destroy(&edges);
2345         IGRAPH_FINALLY_CLEAN(1);
2346 
2347         return IGRAPH_SUCCESS;
2348     }
2349 
2350     if (attr) {
2351         IGRAPH_VECTOR_INIT_FINALLY(&mergeinto, no_of_edges);
2352     }
2353     IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
2354     IGRAPH_CHECK(igraph_vector_reserve(&edges, no_of_edges * 2));
2355 
2356     IGRAPH_CHECK(igraph_es_all(&es, IGRAPH_EDGEORDER_FROM));
2357     IGRAPH_FINALLY(igraph_es_destroy, &es);
2358     IGRAPH_CHECK(igraph_eit_create(graph, es, &eit));
2359     IGRAPH_FINALLY(igraph_eit_destroy, &eit);
2360 
2361     for (actedge = -1; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) {
2362         edge = IGRAPH_EIT_GET(eit);
2363         from = IGRAPH_FROM(graph, edge);
2364         to = IGRAPH_TO(graph, edge);
2365 
2366         if (loops && from == to) {
2367             /* Loop edge to be removed */
2368             if (attr) {
2369                 VECTOR(mergeinto)[edge] = -1;
2370             }
2371         } else if (multiple && from == pfrom && to == pto) {
2372             /* Multiple edge to be contracted */
2373             if (attr) {
2374                 VECTOR(mergeinto)[edge] = actedge;
2375             }
2376         } else {
2377             /* Edge to be kept */
2378             igraph_vector_push_back(&edges, from);
2379             igraph_vector_push_back(&edges, to);
2380             if (attr) {
2381                 actedge++;
2382                 VECTOR(mergeinto)[edge] = actedge;
2383             }
2384         }
2385         pfrom = from; pto = to;
2386     }
2387 
2388     igraph_eit_destroy(&eit);
2389     igraph_es_destroy(&es);
2390     IGRAPH_FINALLY_CLEAN(2);
2391 
2392     IGRAPH_CHECK(igraph_create(&res, &edges, (igraph_integer_t) no_of_nodes,
2393                                igraph_is_directed(graph)));
2394 
2395     igraph_vector_destroy(&edges);
2396     IGRAPH_FINALLY_CLEAN(1);
2397 
2398     IGRAPH_FINALLY(igraph_destroy, &res);
2399 
2400     IGRAPH_I_ATTRIBUTE_DESTROY(&res);
2401     IGRAPH_I_ATTRIBUTE_COPY(&res, graph, /*graph=*/ 1,
2402                             /*vertex=*/ 1, /*edge=*/ 0);
2403 
2404     if (attr) {
2405         igraph_fixed_vectorlist_t vl;
2406         IGRAPH_CHECK(igraph_fixed_vectorlist_convert(&vl, &mergeinto,
2407                      actedge + 1));
2408         IGRAPH_FINALLY(igraph_fixed_vectorlist_destroy, &vl);
2409 
2410         IGRAPH_CHECK(igraph_i_attribute_combine_edges(graph, &res, &vl.v,
2411                      edge_comb));
2412 
2413         igraph_fixed_vectorlist_destroy(&vl);
2414         igraph_vector_destroy(&mergeinto);
2415         IGRAPH_FINALLY_CLEAN(2);
2416     }
2417 
2418     IGRAPH_FINALLY_CLEAN(1);
2419     igraph_destroy(graph);
2420     *graph = res;
2421 
2422     return 0;
2423 }
2424 
2425 /**
2426  * \ingroup structural
2427  * \function igraph_reciprocity
2428  * \brief Calculates the reciprocity of a directed graph.
2429  *
2430  * </para><para>
2431  * The measure of reciprocity defines the proportion of mutual
2432  * connections, in a directed graph. It is most commonly defined as
2433  * the probability that the opposite counterpart of a directed edge is
2434  * also included in the graph. In adjacency matrix notation:
2435  * <code>sum(i, j, (A.*A')ij) / sum(i, j, Aij)</code>, where
2436  * <code>A.*A'</code> is the element-wise product of matrix
2437  * <code>A</code> and its transpose. This measure is
2438  * calculated if the \p mode argument is \c
2439  * IGRAPH_RECIPROCITY_DEFAULT.
2440  *
2441  * </para><para>
2442  * Prior to igraph version 0.6, another measure was implemented,
2443  * defined as the probability of mutual connection between a vertex
2444  * pair if we know that there is a (possibly non-mutual) connection
2445  * between them. In other words, (unordered) vertex pairs are
2446  * classified into three groups: (1) disconnected, (2)
2447  * non-reciprocally connected, (3) reciprocally connected.
2448  * The result is the size of group (3), divided by the sum of group
2449  * sizes (2)+(3). This measure is calculated if \p mode is \c
2450  * IGRAPH_RECIPROCITY_RATIO.
2451  *
2452  * \param graph The graph object.
2453  * \param res Pointer to an \c igraph_real_t which will contain the result.
2454  * \param ignore_loops Whether to ignore loop edges.
2455  * \param mode Type of reciprocity to calculate, possible values are
2456  *    \c IGRAPH_RECIPROCITY_DEFAULT and \c IGRAPH_RECIPROCITY_RATIO,
2457  *    please see their description above.
2458  * \return Error code:
2459  *         \c IGRAPH_EINVAL: graph has no edges
2460  *         \c IGRAPH_ENOMEM: not enough memory for
2461  *         temporary data.
2462  *
2463  * Time complexity: O(|V|+|E|), |V| is the number of vertices,
2464  * |E| is the number of edges.
2465  *
2466  * \example examples/simple/igraph_reciprocity.c
2467  */
2468 
igraph_reciprocity(const igraph_t * graph,igraph_real_t * res,igraph_bool_t ignore_loops,igraph_reciprocity_t mode)2469 int igraph_reciprocity(const igraph_t *graph, igraph_real_t *res,
2470                        igraph_bool_t ignore_loops,
2471                        igraph_reciprocity_t mode) {
2472 
2473     igraph_integer_t nonrec = 0, rec = 0, loops = 0;
2474     igraph_vector_t inneis, outneis;
2475     long int i;
2476     long int no_of_nodes = igraph_vcount(graph);
2477 
2478     if (mode != IGRAPH_RECIPROCITY_DEFAULT &&
2479         mode != IGRAPH_RECIPROCITY_RATIO) {
2480         IGRAPH_ERROR("Invalid reciprocity type", IGRAPH_EINVAL);
2481     }
2482 
2483     /* THIS IS AN EXIT HERE !!!!!!!!!!!!!! */
2484     if (!igraph_is_directed(graph)) {
2485         *res = 1.0;
2486         return 0;
2487     }
2488 
2489     IGRAPH_VECTOR_INIT_FINALLY(&inneis, 0);
2490     IGRAPH_VECTOR_INIT_FINALLY(&outneis, 0);
2491 
2492     for (i = 0; i < no_of_nodes; i++) {
2493         long int ip, op;
2494         igraph_neighbors(graph, &inneis, (igraph_integer_t) i, IGRAPH_IN);
2495         igraph_neighbors(graph, &outneis, (igraph_integer_t) i, IGRAPH_OUT);
2496 
2497         ip = op = 0;
2498         while (ip < igraph_vector_size(&inneis) &&
2499                op < igraph_vector_size(&outneis)) {
2500             if (VECTOR(inneis)[ip] < VECTOR(outneis)[op]) {
2501                 nonrec += 1;
2502                 ip++;
2503             } else if (VECTOR(inneis)[ip] > VECTOR(outneis)[op]) {
2504                 nonrec += 1;
2505                 op++;
2506             } else {
2507 
2508                 /* loop edge? */
2509                 if (VECTOR(inneis)[ip] == i) {
2510                     loops += 1;
2511                     if (!ignore_loops) {
2512                         rec += 1;
2513                     }
2514                 } else {
2515                     rec += 1;
2516                 }
2517 
2518                 ip++;
2519                 op++;
2520             }
2521         }
2522         nonrec += (igraph_vector_size(&inneis) - ip) +
2523                   (igraph_vector_size(&outneis) - op);
2524     }
2525 
2526     if (mode == IGRAPH_RECIPROCITY_DEFAULT) {
2527         if (ignore_loops) {
2528             *res = (igraph_real_t) rec / (igraph_ecount(graph) - loops);
2529         } else {
2530             *res = (igraph_real_t) rec / (igraph_ecount(graph));
2531         }
2532     } else if (mode == IGRAPH_RECIPROCITY_RATIO) {
2533         *res = (igraph_real_t) rec / (rec + nonrec);
2534     }
2535 
2536     igraph_vector_destroy(&inneis);
2537     igraph_vector_destroy(&outneis);
2538     IGRAPH_FINALLY_CLEAN(2);
2539     return 0;
2540 }
2541 
2542 /**
2543  * \function igraph_constraint
2544  * \brief Burt's constraint scores.
2545  *
2546  * </para><para>
2547  * This function calculates Burt's constraint scores for the given
2548  * vertices, also known as structural holes.
2549  *
2550  * </para><para>
2551  * Burt's constraint is higher if ego has less, or mutually stronger
2552  * related (i.e. more redundant) contacts. Burt's measure of
2553  * constraint, C[i], of vertex i's ego network V[i], is defined for
2554  * directed and valued graphs,
2555  * <blockquote><para>
2556  * C[i] = sum( sum( (p[i,q] p[q,j])^2, q in V[i], q != i,j ), j in
2557  * V[], j != i)
2558  * </para></blockquote>
2559  * for a graph of order (i.e. number of vertices) N, where proportional
2560  * tie strengths are defined as
2561  * <blockquote><para>
2562  * p[i,j]=(a[i,j]+a[j,i]) / sum(a[i,k]+a[k,i], k in V[i], k != i),
2563  * </para></blockquote>
2564  * a[i,j] are elements of A and
2565  * the latter being the graph adjacency matrix. For isolated vertices,
2566  * constraint is undefined.
2567  *
2568  * </para><para>
2569  * Burt, R.S. (2004). Structural holes and good ideas. American
2570  * Journal of Sociology 110, 349-399.
2571  *
2572  * </para><para>
2573  * The first R version of this function was contributed by Jeroen
2574  * Bruggeman.
2575  * \param graph A graph object.
2576  * \param res Pointer to an initialized vector, the result will be
2577  *        stored here. The vector will be resized to have the
2578  *        appropriate size for holding the result.
2579  * \param vids Vertex selector containing the vertices for which the
2580  *        constraint should be calculated.
2581  * \param weights Vector giving the weights of the edges. If it is
2582  *        \c NULL then each edge is supposed to have the same weight.
2583  * \return Error code.
2584  *
2585  * Time complexity: O(|V|+E|+n*d^2), n is the number of vertices for
2586  * which the constraint is calculated and d is the average degree, |V|
2587  * is the number of vertices, |E| the number of edges in the
2588  * graph. If the weights argument is \c NULL then the time complexity
2589  * is O(|V|+n*d^2).
2590  */
2591 
igraph_constraint(const igraph_t * graph,igraph_vector_t * res,igraph_vs_t vids,const igraph_vector_t * weights)2592 int igraph_constraint(const igraph_t *graph, igraph_vector_t *res,
2593                       igraph_vs_t vids, const igraph_vector_t *weights) {
2594 
2595     long int no_of_nodes = igraph_vcount(graph);
2596     long int no_of_edges = igraph_ecount(graph);
2597     igraph_vit_t vit;
2598     long int nodes_to_calc;
2599     long int a, b, c, i, j, q;
2600     igraph_integer_t edge, from, to, edge2, from2, to2;
2601 
2602     igraph_vector_t contrib;
2603     igraph_vector_t degree;
2604     igraph_vector_t ineis_in, ineis_out, jneis_in, jneis_out;
2605 
2606     if (weights != 0 && igraph_vector_size(weights) != no_of_edges) {
2607         IGRAPH_ERROR("Invalid length of weight vector", IGRAPH_EINVAL);
2608     }
2609 
2610     IGRAPH_VECTOR_INIT_FINALLY(&contrib, no_of_nodes);
2611     IGRAPH_VECTOR_INIT_FINALLY(&degree, no_of_nodes);
2612     IGRAPH_VECTOR_INIT_FINALLY(&ineis_in, 0);
2613     IGRAPH_VECTOR_INIT_FINALLY(&ineis_out, 0);
2614     IGRAPH_VECTOR_INIT_FINALLY(&jneis_in, 0);
2615     IGRAPH_VECTOR_INIT_FINALLY(&jneis_out, 0);
2616 
2617     IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
2618     IGRAPH_FINALLY(igraph_vit_destroy, &vit);
2619     nodes_to_calc = IGRAPH_VIT_SIZE(vit);
2620 
2621     if (weights == 0) {
2622         IGRAPH_CHECK(igraph_degree(graph, &degree, igraph_vss_all(),
2623                                    IGRAPH_ALL, IGRAPH_NO_LOOPS));
2624     } else {
2625         for (a = 0; a < no_of_edges; a++) {
2626             igraph_edge(graph, (igraph_integer_t) a, &from, &to);
2627             if (from != to) {
2628                 VECTOR(degree)[(long int) from] += VECTOR(*weights)[a];
2629                 VECTOR(degree)[(long int) to  ] += VECTOR(*weights)[a];
2630             }
2631         }
2632     }
2633 
2634     IGRAPH_CHECK(igraph_vector_resize(res, nodes_to_calc));
2635     igraph_vector_null(res);
2636 
2637     for (a = 0; a < nodes_to_calc; a++, IGRAPH_VIT_NEXT(vit)) {
2638         i = IGRAPH_VIT_GET(vit);
2639 
2640         /* get neighbors of i */
2641         IGRAPH_CHECK(igraph_incident(graph, &ineis_in, (igraph_integer_t) i,
2642                                      IGRAPH_IN));
2643         IGRAPH_CHECK(igraph_incident(graph, &ineis_out, (igraph_integer_t) i,
2644                                      IGRAPH_OUT));
2645 
2646         /* NaN for isolates */
2647         if (igraph_vector_size(&ineis_in) == 0 &&
2648             igraph_vector_size(&ineis_out) == 0) {
2649             VECTOR(*res)[a] = IGRAPH_NAN;
2650         }
2651 
2652         /* zero their contribution */
2653         for (b = 0; b < igraph_vector_size(&ineis_in); b++) {
2654             edge = (igraph_integer_t) VECTOR(ineis_in)[b];
2655             igraph_edge(graph, edge, &from, &to);
2656             if (to == i) {
2657                 to = from;
2658             }
2659             j = to;
2660             VECTOR(contrib)[j] = 0.0;
2661         }
2662         for (b = 0; b < igraph_vector_size(&ineis_out); b++) {
2663             edge = (igraph_integer_t) VECTOR(ineis_out)[b];
2664             igraph_edge(graph, edge, &from, &to);
2665             if (to == i) {
2666                 to = from;
2667             }
2668             j = to;
2669             VECTOR(contrib)[j] = 0.0;
2670         }
2671 
2672         /* add the direct contributions, in-neighbors and out-neighbors */
2673         for (b = 0; b < igraph_vector_size(&ineis_in); b++) {
2674             edge = (igraph_integer_t) VECTOR(ineis_in)[b];
2675             igraph_edge(graph, edge, &from, &to);
2676             if (to == i) {
2677                 to = from;
2678             }
2679             j = to;
2680             if (i != j) {     /* excluding loops */
2681                 if (weights) {
2682                     VECTOR(contrib)[j] +=
2683                         VECTOR(*weights)[(long int)edge] / VECTOR(degree)[i];
2684                 } else {
2685                     VECTOR(contrib)[j] += 1.0 / VECTOR(degree)[i];
2686                 }
2687             }
2688         }
2689         if (igraph_is_directed(graph)) {
2690             for (b = 0; b < igraph_vector_size(&ineis_out); b++) {
2691                 edge = (igraph_integer_t) VECTOR(ineis_out)[b];
2692                 igraph_edge(graph, edge, &from, &to);
2693                 if (to == i) {
2694                     to = from;
2695                 }
2696                 j = to;
2697                 if (i != j) {
2698                     if (weights) {
2699                         VECTOR(contrib)[j] +=
2700                             VECTOR(*weights)[(long int)edge] / VECTOR(degree)[i];
2701                     } else {
2702                         VECTOR(contrib)[j] += 1.0 / VECTOR(degree)[i];
2703                     }
2704                 }
2705             }
2706         }
2707 
2708         /* add the indirect contributions, in-in, in-out, out-in, out-out */
2709         for (b = 0; b < igraph_vector_size(&ineis_in); b++) {
2710             edge = (igraph_integer_t) VECTOR(ineis_in)[b];
2711             igraph_edge(graph, edge, &from, &to);
2712             if (to == i) {
2713                 to = from;
2714             }
2715             j = to;
2716             if (i == j) {
2717                 continue;
2718             }
2719             IGRAPH_CHECK(igraph_incident(graph, &jneis_in, (igraph_integer_t) j,
2720                                          IGRAPH_IN));
2721             IGRAPH_CHECK(igraph_incident(graph, &jneis_out, (igraph_integer_t) j,
2722                                          IGRAPH_OUT));
2723             for (c = 0; c < igraph_vector_size(&jneis_in); c++) {
2724                 edge2 = (igraph_integer_t) VECTOR(jneis_in)[c];
2725                 igraph_edge(graph, edge2, &from2, &to2);
2726                 if (to2 == j) {
2727                     to2 = from2;
2728                 }
2729                 q = to2;
2730                 if (j != q) {
2731                     if (weights) {
2732                         VECTOR(contrib)[q] +=
2733                             VECTOR(*weights)[(long int)edge] *
2734                             VECTOR(*weights)[(long int)edge2] /
2735                             VECTOR(degree)[i] / VECTOR(degree)[j];
2736                     } else {
2737                         VECTOR(contrib)[q] += 1 / VECTOR(degree)[i] / VECTOR(degree)[j];
2738                     }
2739                 }
2740             }
2741             if (igraph_is_directed(graph)) {
2742                 for (c = 0; c < igraph_vector_size(&jneis_out); c++) {
2743                     edge2 = (igraph_integer_t) VECTOR(jneis_out)[c];
2744                     igraph_edge(graph, edge2, &from2, &to2);
2745                     if (to2 == j) {
2746                         to2 = from2;
2747                     }
2748                     q = to2;
2749                     if (j != q) {
2750                         if (weights) {
2751                             VECTOR(contrib)[q] +=
2752                                 VECTOR(*weights)[(long int)edge] *
2753                                 VECTOR(*weights)[(long int)edge2] /
2754                                 VECTOR(degree)[i] / VECTOR(degree)[j];
2755                         } else {
2756                             VECTOR(contrib)[q] += 1 / VECTOR(degree)[i] / VECTOR(degree)[j];
2757                         }
2758                     }
2759                 }
2760             }
2761         }
2762         if (igraph_is_directed(graph)) {
2763             for (b = 0; b < igraph_vector_size(&ineis_out); b++) {
2764                 edge = (igraph_integer_t) VECTOR(ineis_out)[b];
2765                 igraph_edge(graph, edge, &from, &to);
2766                 if (to == i) {
2767                     to = from;
2768                 }
2769                 j = to;
2770                 if (i == j) {
2771                     continue;
2772                 }
2773                 IGRAPH_CHECK(igraph_incident(graph, &jneis_in, (igraph_integer_t) j,
2774                                              IGRAPH_IN));
2775                 IGRAPH_CHECK(igraph_incident(graph, &jneis_out, (igraph_integer_t) j,
2776                                              IGRAPH_OUT));
2777                 for (c = 0; c < igraph_vector_size(&jneis_in); c++) {
2778                     edge2 = (igraph_integer_t) VECTOR(jneis_in)[c];
2779                     igraph_edge(graph, edge2, &from2, &to2);
2780                     if (to2 == j) {
2781                         to2 = from2;
2782                     }
2783                     q = to2;
2784                     if (j != q) {
2785                         if (weights) {
2786                             VECTOR(contrib)[q] +=
2787                                 VECTOR(*weights)[(long int)edge] *
2788                                 VECTOR(*weights)[(long int)edge2] /
2789                                 VECTOR(degree)[i] / VECTOR(degree)[j];
2790                         } else {
2791                             VECTOR(contrib)[q] += 1 / VECTOR(degree)[i] / VECTOR(degree)[j];
2792                         }
2793                     }
2794                 }
2795                 for (c = 0; c < igraph_vector_size(&jneis_out); c++) {
2796                     edge2 = (igraph_integer_t) VECTOR(jneis_out)[c];
2797                     igraph_edge(graph, edge2, &from2, &to2);
2798                     if (to2 == j) {
2799                         to2 = from2;
2800                     }
2801                     q = to2;
2802                     if (j != q) {
2803                         if (weights) {
2804                             VECTOR(contrib)[q] +=
2805                                 VECTOR(*weights)[(long int)edge] *
2806                                 VECTOR(*weights)[(long int)edge2] /
2807                                 VECTOR(degree)[i] / VECTOR(degree)[j];
2808                         } else {
2809                             VECTOR(contrib)[q] += 1 / VECTOR(degree)[i] / VECTOR(degree)[j];
2810                         }
2811                     }
2812                 }
2813             }
2814         }
2815 
2816         /* squared sum of the contributions */
2817         for (b = 0; b < igraph_vector_size(&ineis_in); b++) {
2818             edge = (igraph_integer_t) VECTOR(ineis_in)[b];
2819             igraph_edge(graph, edge, &from, &to);
2820             if (to == i) {
2821                 to = from;
2822             }
2823             j = to;
2824             if (i == j) {
2825                 continue;
2826             }
2827             VECTOR(*res)[a] += VECTOR(contrib)[j] * VECTOR(contrib)[j];
2828             VECTOR(contrib)[j] = 0.0;
2829         }
2830         if (igraph_is_directed(graph)) {
2831             for (b = 0; b < igraph_vector_size(&ineis_out); b++) {
2832                 edge = (igraph_integer_t) VECTOR(ineis_out)[b];
2833                 igraph_edge(graph, edge, &from, &to);
2834                 if (to == i) {
2835                     to = from;
2836                 }
2837                 j = to;
2838                 if (i == j) {
2839                     continue;
2840                 }
2841                 VECTOR(*res)[a] += VECTOR(contrib)[j] * VECTOR(contrib)[j];
2842                 VECTOR(contrib)[j] = 0.0;
2843             }
2844         }
2845     }
2846 
2847     igraph_vit_destroy(&vit);
2848     igraph_vector_destroy(&jneis_out);
2849     igraph_vector_destroy(&jneis_in);
2850     igraph_vector_destroy(&ineis_out);
2851     igraph_vector_destroy(&ineis_in);
2852     igraph_vector_destroy(&degree);
2853     igraph_vector_destroy(&contrib);
2854     IGRAPH_FINALLY_CLEAN(7);
2855 
2856     return 0;
2857 }
2858 
2859 /**
2860  * \function igraph_maxdegree
2861  * \brief Calculate the maximum degree in a graph (or set of vertices).
2862  *
2863  * </para><para>
2864  * The largest in-, out- or total degree of the specified vertices is
2865  * calculated.
2866  * \param graph The input graph.
2867  * \param res Pointer to an integer (\c igraph_integer_t), the result
2868  *        will be stored here.
2869  * \param vids Vector giving the vertex IDs for which the maximum degree will
2870  *        be calculated.
2871  * \param mode Defines the type of the degree.
2872  *        \c IGRAPH_OUT, out-degree,
2873  *        \c IGRAPH_IN, in-degree,
2874  *        \c IGRAPH_ALL, total degree (sum of the
2875  *        in- and out-degree).
2876  *        This parameter is ignored for undirected graphs.
2877  * \param loops Boolean, gives whether the self-loops should be
2878  *        counted.
2879  * \return Error code:
2880  *         \c IGRAPH_EINVVID: invalid vertex id.
2881  *         \c IGRAPH_EINVMODE: invalid mode argument.
2882  *
2883  * Time complexity: O(v) if
2884  * loops is
2885  * TRUE, and
2886  * O(v*d)
2887  * otherwise. v is the number
2888  * vertices for which the degree will be calculated, and
2889  * d is their (average) degree.
2890  */
2891 
igraph_maxdegree(const igraph_t * graph,igraph_integer_t * res,igraph_vs_t vids,igraph_neimode_t mode,igraph_bool_t loops)2892 int igraph_maxdegree(const igraph_t *graph, igraph_integer_t *res,
2893                      igraph_vs_t vids, igraph_neimode_t mode,
2894                      igraph_bool_t loops) {
2895 
2896     igraph_vector_t tmp;
2897 
2898     IGRAPH_VECTOR_INIT_FINALLY(&tmp, 0);
2899 
2900     igraph_degree(graph, &tmp, vids, mode, loops);
2901     *res = (igraph_integer_t) igraph_vector_max(&tmp);
2902 
2903     igraph_vector_destroy(&tmp);
2904     IGRAPH_FINALLY_CLEAN(1);
2905     return 0;
2906 }
2907 
2908 /**
2909  * \function igraph_density
2910  * Calculate the density of a graph.
2911  *
2912  * </para><para>The density of a graph is simply the ratio number of
2913  * edges and the number of possible edges. Note that density is
2914  * ill-defined for graphs with multiple and/or loop edges, so consider
2915  * calling \ref igraph_simplify() on the graph if you know that it
2916  * contains multiple or loop edges.
2917  * \param graph The input graph object.
2918  * \param res Pointer to a real number, the result will be stored
2919  *   here.
2920  * \param loops Logical constant, whether to include loops in the
2921  *   calculation. If this constant is TRUE then
2922  *   loop edges are thought to be possible in the graph (this does not
2923  *   necessarily mean that the graph really contains any loops). If
2924  *   this is FALSE then the result is only correct if the graph does not
2925  *   contain loops.
2926  * \return Error code.
2927  *
2928  * Time complexity: O(1).
2929  */
2930 
igraph_density(const igraph_t * graph,igraph_real_t * res,igraph_bool_t loops)2931 int igraph_density(const igraph_t *graph, igraph_real_t *res,
2932                    igraph_bool_t loops) {
2933 
2934     igraph_integer_t no_of_nodes = igraph_vcount(graph);
2935     igraph_real_t no_of_edges = igraph_ecount(graph);
2936     igraph_bool_t directed = igraph_is_directed(graph);
2937 
2938     if (no_of_nodes == 0) {
2939         *res = IGRAPH_NAN;
2940         return 0;
2941     }
2942 
2943     if (!loops) {
2944         if (no_of_nodes == 1) {
2945             *res = IGRAPH_NAN;
2946         } else if (directed) {
2947             *res = no_of_edges / no_of_nodes / (no_of_nodes - 1);
2948         } else {
2949             *res = no_of_edges / no_of_nodes * 2.0 / (no_of_nodes - 1);
2950         }
2951     } else {
2952         if (directed) {
2953             *res = no_of_edges / no_of_nodes / no_of_nodes;
2954         } else {
2955             *res = no_of_edges / no_of_nodes * 2.0 / (no_of_nodes + 1);
2956         }
2957     }
2958 
2959     return 0;
2960 }
2961 
2962 /**
2963  * \function igraph_neighborhood_size
2964  * \brief Calculates the size of the neighborhood of a given vertex.
2965  *
2966  * The neighborhood of a given order of a vertex includes all vertices
2967  * which are closer to the vertex than the order. I.e., order 0 is
2968  * always the vertex itself, order 1 is the vertex plus its immediate
2969  * neighbors, order 2 is order 1 plus the immediate neighbors of the
2970  * vertices in order 1, etc.
2971  *
2972  * </para><para> This function calculates the size of the neighborhood
2973  * of the given order for the given vertices.
2974  * \param graph The input graph.
2975  * \param res Pointer to an initialized vector, the result will be
2976  *    stored here. It will be resized as needed.
2977  * \param vids The vertices for which the calculation is performed.
2978  * \param order Integer giving the order of the neighborhood.
2979  * \param mode Specifies how to use the direction of the edges if a
2980  *   directed graph is analyzed. For \c IGRAPH_OUT only the outgoing
2981  *   edges are followed, so all vertices reachable from the source
2982  *   vertex in at most \c order steps are counted. For \c IGRAPH_IN
2983  *   all vertices from which the source vertex is reachable in at most
2984  *   \c order steps are counted. \c IGRAPH_ALL ignores the direction
2985  *   of the edges. This argument is ignored for undirected graphs.
2986  * \param mindist The minimum distance to include a vertex in the counting.
2987  *   If this is one, then the starting vertex is not counted. If this is
2988  *   two, then its neighbors are not counted, either, etc.
2989  * \return Error code.
2990  *
2991  * \sa \ref igraph_neighborhood() for calculating the actual neighborhood,
2992  * \ref igraph_neighborhood_graphs() for creating separate graphs from
2993  * the neighborhoods.
2994  *
2995  * Time complexity: O(n*d*o), where n is the number vertices for which
2996  * the calculation is performed, d is the average degree, o is the order.
2997  */
2998 
igraph_neighborhood_size(const igraph_t * graph,igraph_vector_t * res,igraph_vs_t vids,igraph_integer_t order,igraph_neimode_t mode,igraph_integer_t mindist)2999 int igraph_neighborhood_size(const igraph_t *graph, igraph_vector_t *res,
3000                              igraph_vs_t vids, igraph_integer_t order,
3001                              igraph_neimode_t mode,
3002                              igraph_integer_t mindist) {
3003 
3004     long int no_of_nodes = igraph_vcount(graph);
3005     igraph_dqueue_t q;
3006     igraph_vit_t vit;
3007     long int i, j;
3008     long int *added;
3009     igraph_vector_t neis;
3010 
3011     if (order < 0) {
3012         IGRAPH_ERROR("Negative order in neighborhood size", IGRAPH_EINVAL);
3013     }
3014 
3015     if (mindist < 0 || mindist > order) {
3016         IGRAPH_ERROR("Minimum distance should be between zero and order",
3017                      IGRAPH_EINVAL);
3018     }
3019 
3020     added = igraph_Calloc(no_of_nodes, long int);
3021     if (added == 0) {
3022         IGRAPH_ERROR("Cannot calculate neighborhood size", IGRAPH_ENOMEM);
3023     }
3024     IGRAPH_FINALLY(igraph_free, added);
3025     IGRAPH_DQUEUE_INIT_FINALLY(&q, 100);
3026     IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
3027     IGRAPH_FINALLY(igraph_vit_destroy, &vit);
3028     IGRAPH_VECTOR_INIT_FINALLY(&neis, 0);
3029     IGRAPH_CHECK(igraph_vector_resize(res, IGRAPH_VIT_SIZE(vit)));
3030 
3031     for (i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) {
3032         long int node = IGRAPH_VIT_GET(vit);
3033         long int size = mindist == 0 ? 1 : 0;
3034         added[node] = i + 1;
3035         igraph_dqueue_clear(&q);
3036         if (order > 0) {
3037             igraph_dqueue_push(&q, node);
3038             igraph_dqueue_push(&q, 0);
3039         }
3040 
3041         while (!igraph_dqueue_empty(&q)) {
3042             long int actnode = (long int) igraph_dqueue_pop(&q);
3043             long int actdist = (long int) igraph_dqueue_pop(&q);
3044             long int n;
3045             igraph_neighbors(graph, &neis, (igraph_integer_t) actnode, mode);
3046             n = igraph_vector_size(&neis);
3047 
3048             if (actdist < order - 1) {
3049                 /* we add them to the q */
3050                 for (j = 0; j < n; j++) {
3051                     long int nei = (long int) VECTOR(neis)[j];
3052                     if (added[nei] != i + 1) {
3053                         added[nei] = i + 1;
3054                         IGRAPH_CHECK(igraph_dqueue_push(&q, nei));
3055                         IGRAPH_CHECK(igraph_dqueue_push(&q, actdist + 1));
3056                         if (actdist + 1 >= mindist) {
3057                             size++;
3058                         }
3059                     }
3060                 }
3061             } else {
3062                 /* we just count them, but don't add them */
3063                 for (j = 0; j < n; j++) {
3064                     long int nei = (long int) VECTOR(neis)[j];
3065                     if (added[nei] != i + 1) {
3066                         added[nei] = i + 1;
3067                         if (actdist + 1 >= mindist) {
3068                             size++;
3069                         }
3070                     }
3071                 }
3072             }
3073 
3074         } /* while q not empty */
3075 
3076         VECTOR(*res)[i] = size;
3077     } /* for VIT, i */
3078 
3079     igraph_vector_destroy(&neis);
3080     igraph_vit_destroy(&vit);
3081     igraph_dqueue_destroy(&q);
3082     igraph_Free(added);
3083     IGRAPH_FINALLY_CLEAN(4);
3084 
3085     return 0;
3086 }
3087 
3088 /**
3089  * \function igraph_neighborhood
3090  * Calculate the neighborhood of vertices.
3091  *
3092  * The neighborhood of a given order of a vertex includes all vertices
3093  * which are closer to the vertex than the order. I.e., order 0 is
3094  * always the vertex itself, order 1 is the vertex plus its immediate
3095  * neighbors, order 2 is order 1 plus the immediate neighbors of the
3096  * vertices in order 1, etc.
3097  *
3098  * </para><para> This function calculates the vertices within the
3099  * neighborhood of the specified vertices.
3100  * \param graph The input graph.
3101  * \param res An initialized pointer vector. Note that the objects
3102  *    (pointers) in the vector will \em not be freed, but the pointer
3103  *    vector will be resized as needed. The result of the calculation
3104  *    will be stored here in \ref igraph_vector_t objects.
3105  * \param vids The vertices for which the calculation is performed.
3106  * \param order Integer giving the order of the neighborhood.
3107  * \param mode Specifies how to use the direction of the edges if a
3108  *   directed graph is analyzed. For \c IGRAPH_OUT only the outgoing
3109  *   edges are followed, so all vertices reachable from the source
3110  *   vertex in at most \p order steps are included. For \c IGRAPH_IN
3111  *   all vertices from which the source vertex is reachable in at most
3112  *   \p order steps are included. \c IGRAPH_ALL ignores the direction
3113  *   of the edges. This argument is ignored for undirected graphs.
3114  * \param mindist The minimum distance to include a vertex in the counting.
3115  *   If this is one, then the starting vertex is not counted. If this is
3116  *   two, then its neighbors are not counted, either, etc.
3117  * \return Error code.
3118  *
3119  * \sa \ref igraph_neighborhood_size() to calculate the size of the
3120  * neighborhood, \ref igraph_neighborhood_graphs() for creating
3121  * graphs from the neighborhoods.
3122  *
3123  * Time complexity: O(n*d*o), n is the number of vertices for which
3124  * the calculation is performed, d is the average degree, o is the
3125  * order.
3126  */
3127 
igraph_neighborhood(const igraph_t * graph,igraph_vector_ptr_t * res,igraph_vs_t vids,igraph_integer_t order,igraph_neimode_t mode,igraph_integer_t mindist)3128 int igraph_neighborhood(const igraph_t *graph, igraph_vector_ptr_t *res,
3129                         igraph_vs_t vids, igraph_integer_t order,
3130                         igraph_neimode_t mode, igraph_integer_t mindist) {
3131 
3132     long int no_of_nodes = igraph_vcount(graph);
3133     igraph_dqueue_t q;
3134     igraph_vit_t vit;
3135     long int i, j;
3136     long int *added;
3137     igraph_vector_t neis;
3138     igraph_vector_t tmp;
3139     igraph_vector_t *newv;
3140 
3141     if (order < 0) {
3142         IGRAPH_ERROR("Negative order in neighborhood size", IGRAPH_EINVAL);
3143     }
3144 
3145     if (mindist < 0 || mindist > order) {
3146         IGRAPH_ERROR("Minimum distance should be between zero and order",
3147                      IGRAPH_EINVAL);
3148     }
3149 
3150     added = igraph_Calloc(no_of_nodes, long int);
3151     if (added == 0) {
3152         IGRAPH_ERROR("Cannot calculate neighborhood size", IGRAPH_ENOMEM);
3153     }
3154     IGRAPH_FINALLY(igraph_free, added);
3155     IGRAPH_DQUEUE_INIT_FINALLY(&q, 100);
3156     IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
3157     IGRAPH_FINALLY(igraph_vit_destroy, &vit);
3158     IGRAPH_VECTOR_INIT_FINALLY(&neis, 0);
3159     IGRAPH_VECTOR_INIT_FINALLY(&tmp, 0);
3160     IGRAPH_CHECK(igraph_vector_ptr_resize(res, IGRAPH_VIT_SIZE(vit)));
3161 
3162     for (i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) {
3163         long int node = IGRAPH_VIT_GET(vit);
3164         added[node] = i + 1;
3165         igraph_vector_clear(&tmp);
3166         if (mindist == 0) {
3167             IGRAPH_CHECK(igraph_vector_push_back(&tmp, node));
3168         }
3169         if (order > 0) {
3170             igraph_dqueue_push(&q, node);
3171             igraph_dqueue_push(&q, 0);
3172         }
3173 
3174         while (!igraph_dqueue_empty(&q)) {
3175             long int actnode = (long int) igraph_dqueue_pop(&q);
3176             long int actdist = (long int) igraph_dqueue_pop(&q);
3177             long int n;
3178             igraph_neighbors(graph, &neis, (igraph_integer_t) actnode, mode);
3179             n = igraph_vector_size(&neis);
3180 
3181             if (actdist < order - 1) {
3182                 /* we add them to the q */
3183                 for (j = 0; j < n; j++) {
3184                     long int nei = (long int) VECTOR(neis)[j];
3185                     if (added[nei] != i + 1) {
3186                         added[nei] = i + 1;
3187                         IGRAPH_CHECK(igraph_dqueue_push(&q, nei));
3188                         IGRAPH_CHECK(igraph_dqueue_push(&q, actdist + 1));
3189                         if (actdist + 1 >= mindist) {
3190                             IGRAPH_CHECK(igraph_vector_push_back(&tmp, nei));
3191                         }
3192                     }
3193                 }
3194             } else {
3195                 /* we just count them but don't add them to q */
3196                 for (j = 0; j < n; j++) {
3197                     long int nei = (long int) VECTOR(neis)[j];
3198                     if (added[nei] != i + 1) {
3199                         added[nei] = i + 1;
3200                         if (actdist + 1 >= mindist) {
3201                             IGRAPH_CHECK(igraph_vector_push_back(&tmp, nei));
3202                         }
3203                     }
3204                 }
3205             }
3206 
3207         } /* while q not empty */
3208 
3209         newv = igraph_Calloc(1, igraph_vector_t);
3210         if (newv == 0) {
3211             IGRAPH_ERROR("Cannot calculate neighborhood", IGRAPH_ENOMEM);
3212         }
3213         IGRAPH_FINALLY(igraph_free, newv);
3214         IGRAPH_CHECK(igraph_vector_copy(newv, &tmp));
3215         VECTOR(*res)[i] = newv;
3216         IGRAPH_FINALLY_CLEAN(1);
3217     }
3218 
3219     igraph_vector_destroy(&tmp);
3220     igraph_vector_destroy(&neis);
3221     igraph_vit_destroy(&vit);
3222     igraph_dqueue_destroy(&q);
3223     igraph_Free(added);
3224     IGRAPH_FINALLY_CLEAN(5);
3225 
3226     return 0;
3227 }
3228 
3229 /**
3230  * \function igraph_neighborhood_graphs
3231  * Create graphs from the neighborhood(s) of some vertex/vertices.
3232  *
3233  * The neighborhood of a given order of a vertex includes all vertices
3234  * which are closer to the vertex than the order. Ie. order 0 is
3235  * always the vertex itself, order 1 is the vertex plus its immediate
3236  * neighbors, order 2 is order 1 plus the immediate neighbors of the
3237  * vertices in order 1, etc.
3238  *
3239  * </para><para> This function finds every vertex in the neighborhood
3240  * of a given parameter vertex and creates a graph from these
3241  * vertices.
3242  *
3243  * </para><para> The first version of this function was written by
3244  * Vincent Matossian, thanks Vincent.
3245  * \param graph The input graph.
3246  * \param res Pointer to a pointer vector, the result will be stored
3247  *   here, ie. \p res will contain pointers to \c igraph_t
3248  *   objects. It will be resized if needed but note that the
3249  *   objects in the pointer vector will not be freed.
3250  * \param vids The vertices for which the calculation is performed.
3251  * \param order Integer giving the order of the neighborhood.
3252  * \param mode Specifies how to use the direction of the edges if a
3253  *   directed graph is analyzed. For \c IGRAPH_OUT only the outgoing
3254  *   edges are followed, so all vertices reachable from the source
3255  *   vertex in at most \p order steps are counted. For \c IGRAPH_IN
3256  *   all vertices from which the source vertex is reachable in at most
3257  *   \p order steps are counted. \c IGRAPH_ALL ignores the direction
3258  *   of the edges. This argument is ignored for undirected graphs.
3259  * \param mindist The minimum distance to include a vertex in the counting.
3260  *   If this is one, then the starting vertex is not counted. If this is
3261  *   two, then its neighbors are not counted, either, etc.
3262  * \return Error code.
3263  *
3264  * \sa \ref igraph_neighborhood_size() for calculating the neighborhood
3265  * sizes only, \ref igraph_neighborhood() for calculating the
3266  * neighborhoods (but not creating graphs).
3267  *
3268  * Time complexity: O(n*(|V|+|E|)), where n is the number vertices for
3269  * which the calculation is performed, |V| and |E| are the number of
3270  * vertices and edges in the original input graph.
3271  */
3272 
igraph_neighborhood_graphs(const igraph_t * graph,igraph_vector_ptr_t * res,igraph_vs_t vids,igraph_integer_t order,igraph_neimode_t mode,igraph_integer_t mindist)3273 int igraph_neighborhood_graphs(const igraph_t *graph, igraph_vector_ptr_t *res,
3274                                igraph_vs_t vids, igraph_integer_t order,
3275                                igraph_neimode_t mode,
3276                                igraph_integer_t mindist) {
3277     long int no_of_nodes = igraph_vcount(graph);
3278     igraph_dqueue_t q;
3279     igraph_vit_t vit;
3280     long int i, j;
3281     long int *added;
3282     igraph_vector_t neis;
3283     igraph_vector_t tmp;
3284     igraph_t *newg;
3285 
3286     if (order < 0) {
3287         IGRAPH_ERROR("Negative order in neighborhood size", IGRAPH_EINVAL);
3288     }
3289 
3290     if (mindist < 0 || mindist > order) {
3291         IGRAPH_ERROR("Minimum distance should be between zero and order",
3292                      IGRAPH_EINVAL);
3293     }
3294 
3295     added = igraph_Calloc(no_of_nodes, long int);
3296     if (added == 0) {
3297         IGRAPH_ERROR("Cannot calculate neighborhood size", IGRAPH_ENOMEM);
3298     }
3299     IGRAPH_FINALLY(igraph_free, added);
3300     IGRAPH_DQUEUE_INIT_FINALLY(&q, 100);
3301     IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
3302     IGRAPH_FINALLY(igraph_vit_destroy, &vit);
3303     IGRAPH_VECTOR_INIT_FINALLY(&neis, 0);
3304     IGRAPH_VECTOR_INIT_FINALLY(&tmp, 0);
3305     IGRAPH_CHECK(igraph_vector_ptr_resize(res, IGRAPH_VIT_SIZE(vit)));
3306 
3307     for (i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) {
3308         long int node = IGRAPH_VIT_GET(vit);
3309         added[node] = i + 1;
3310         igraph_vector_clear(&tmp);
3311         if (mindist == 0) {
3312             IGRAPH_CHECK(igraph_vector_push_back(&tmp, node));
3313         }
3314         if (order > 0) {
3315             igraph_dqueue_push(&q, node);
3316             igraph_dqueue_push(&q, 0);
3317         }
3318 
3319         while (!igraph_dqueue_empty(&q)) {
3320             long int actnode = (long int) igraph_dqueue_pop(&q);
3321             long int actdist = (long int) igraph_dqueue_pop(&q);
3322             long int n;
3323             igraph_neighbors(graph, &neis, (igraph_integer_t) actnode, mode);
3324             n = igraph_vector_size(&neis);
3325 
3326             if (actdist < order - 1) {
3327                 /* we add them to the q */
3328                 for (j = 0; j < n; j++) {
3329                     long int nei = (long int) VECTOR(neis)[j];
3330                     if (added[nei] != i + 1) {
3331                         added[nei] = i + 1;
3332                         IGRAPH_CHECK(igraph_dqueue_push(&q, nei));
3333                         IGRAPH_CHECK(igraph_dqueue_push(&q, actdist + 1));
3334                         if (actdist + 1 >= mindist) {
3335                             IGRAPH_CHECK(igraph_vector_push_back(&tmp, nei));
3336                         }
3337                     }
3338                 }
3339             } else {
3340                 /* we just count them but don't add them to q */
3341                 for (j = 0; j < n; j++) {
3342                     long int nei = (long int) VECTOR(neis)[j];
3343                     if (added[nei] != i + 1) {
3344                         added[nei] = i + 1;
3345                         if (actdist + 1 >= mindist) {
3346                             IGRAPH_CHECK(igraph_vector_push_back(&tmp, nei));
3347                         }
3348                     }
3349                 }
3350             }
3351 
3352         } /* while q not empty */
3353 
3354         newg = igraph_Calloc(1, igraph_t);
3355         if (newg == 0) {
3356             IGRAPH_ERROR("Cannot create neighborhood graph", IGRAPH_ENOMEM);
3357         }
3358         IGRAPH_FINALLY(igraph_free, newg);
3359         if (igraph_vector_size(&tmp) < no_of_nodes) {
3360             IGRAPH_CHECK(igraph_induced_subgraph(graph, newg,
3361                                                  igraph_vss_vector(&tmp),
3362                                                  IGRAPH_SUBGRAPH_AUTO));
3363         } else {
3364             IGRAPH_CHECK(igraph_copy(newg, graph));
3365         }
3366         VECTOR(*res)[i] = newg;
3367         IGRAPH_FINALLY_CLEAN(1);
3368     }
3369 
3370     igraph_vector_destroy(&tmp);
3371     igraph_vector_destroy(&neis);
3372     igraph_vit_destroy(&vit);
3373     igraph_dqueue_destroy(&q);
3374     igraph_Free(added);
3375     IGRAPH_FINALLY_CLEAN(5);
3376 
3377     return 0;
3378 }
3379 
3380 /**
3381  * \function igraph_topological_sorting
3382  * \brief Calculate a possible topological sorting of the graph.
3383  *
3384  * </para><para>
3385  * A topological sorting of a directed acyclic graph is a linear ordering
3386  * of its nodes where each node comes before all nodes to which it has
3387  * edges. Every DAG has at least one topological sort, and may have many.
3388  * This function returns a possible topological sort among them. If the
3389  * graph is not acyclic (it has at least one cycle), a partial topological
3390  * sort is returned and a warning is issued.
3391  *
3392  * \param graph The input graph.
3393  * \param res Pointer to a vector, the result will be stored here.
3394  *   It will be resized if needed.
3395  * \param mode Specifies how to use the direction of the edges.
3396  *   For \c IGRAPH_OUT, the sorting order ensures that each node comes
3397  *   before all nodes to which it has edges, so nodes with no incoming
3398  *   edges go first. For \c IGRAPH_IN, it is quite the opposite: each
3399  *   node comes before all nodes from which it receives edges. Nodes
3400  *   with no outgoing edges go first.
3401  * \return Error code.
3402  *
3403  * Time complexity: O(|V|+|E|), where |V| and |E| are the number of
3404  * vertices and edges in the original input graph.
3405  *
3406  * \sa \ref igraph_is_dag() if you are only interested in whether a given
3407  *     graph is a DAG or not, or \ref igraph_feedback_arc_set() to find a
3408  *     set of edges whose removal makes the graph a DAG.
3409  *
3410  * \example examples/simple/igraph_topological_sorting.c
3411  */
igraph_topological_sorting(const igraph_t * graph,igraph_vector_t * res,igraph_neimode_t mode)3412 int igraph_topological_sorting(const igraph_t* graph, igraph_vector_t *res,
3413                                igraph_neimode_t mode) {
3414     long int no_of_nodes = igraph_vcount(graph);
3415     igraph_vector_t degrees, neis;
3416     igraph_dqueue_t sources;
3417     igraph_neimode_t deg_mode;
3418     long int node, i, j;
3419 
3420     if (mode == IGRAPH_ALL || !igraph_is_directed(graph)) {
3421         IGRAPH_ERROR("topological sorting does not make sense for undirected graphs", IGRAPH_EINVAL);
3422     } else if (mode == IGRAPH_OUT) {
3423         deg_mode = IGRAPH_IN;
3424     } else if (mode == IGRAPH_IN) {
3425         deg_mode = IGRAPH_OUT;
3426     } else {
3427         IGRAPH_ERROR("invalid mode", IGRAPH_EINVAL);
3428     }
3429 
3430     IGRAPH_VECTOR_INIT_FINALLY(&degrees, no_of_nodes);
3431     IGRAPH_VECTOR_INIT_FINALLY(&neis, 0);
3432     IGRAPH_CHECK(igraph_dqueue_init(&sources, 0));
3433     IGRAPH_FINALLY(igraph_dqueue_destroy, &sources);
3434     IGRAPH_CHECK(igraph_degree(graph, &degrees, igraph_vss_all(), deg_mode, 0));
3435 
3436     igraph_vector_clear(res);
3437 
3438     /* Do we have nodes with no incoming vertices? */
3439     for (i = 0; i < no_of_nodes; i++) {
3440         if (VECTOR(degrees)[i] == 0) {
3441             IGRAPH_CHECK(igraph_dqueue_push(&sources, i));
3442         }
3443     }
3444 
3445     /* Take all nodes with no incoming vertices and remove them */
3446     while (!igraph_dqueue_empty(&sources)) {
3447         igraph_real_t tmp = igraph_dqueue_pop(&sources); node = (long) tmp;
3448         /* Add the node to the result vector */
3449         igraph_vector_push_back(res, node);
3450         /* Exclude the node from further source searches */
3451         VECTOR(degrees)[node] = -1;
3452         /* Get the neighbors and decrease their degrees by one */
3453         IGRAPH_CHECK(igraph_neighbors(graph, &neis, (igraph_integer_t) node, mode));
3454         j = igraph_vector_size(&neis);
3455         for (i = 0; i < j; i++) {
3456             VECTOR(degrees)[(long)VECTOR(neis)[i]]--;
3457             if (VECTOR(degrees)[(long)VECTOR(neis)[i]] == 0) {
3458                 IGRAPH_CHECK(igraph_dqueue_push(&sources, VECTOR(neis)[i]));
3459             }
3460         }
3461     }
3462 
3463     if (igraph_vector_size(res) < no_of_nodes) {
3464         IGRAPH_WARNING("graph contains a cycle, partial result is returned");
3465     }
3466 
3467     igraph_vector_destroy(&degrees);
3468     igraph_vector_destroy(&neis);
3469     igraph_dqueue_destroy(&sources);
3470     IGRAPH_FINALLY_CLEAN(3);
3471 
3472     return 0;
3473 }
3474 
3475 /**
3476  * \function igraph_is_dag
3477  * Checks whether a graph is a directed acyclic graph (DAG) or not.
3478  *
3479  * </para><para>
3480  * A directed acyclic graph (DAG) is a directed graph with no cycles.
3481  *
3482  * \param graph The input graph.
3483  * \param res Pointer to a boolean constant, the result
3484  *     is stored here.
3485  * \return Error code.
3486  *
3487  * Time complexity: O(|V|+|E|), where |V| and |E| are the number of
3488  * vertices and edges in the original input graph.
3489  *
3490  * \sa \ref igraph_topological_sorting() to get a possible topological
3491  *     sorting of a DAG.
3492  */
igraph_is_dag(const igraph_t * graph,igraph_bool_t * res)3493 int igraph_is_dag(const igraph_t* graph, igraph_bool_t *res) {
3494     long int no_of_nodes = igraph_vcount(graph);
3495     igraph_vector_t degrees, neis;
3496     igraph_dqueue_t sources;
3497     long int node, i, j, nei, vertices_left;
3498 
3499     if (!igraph_is_directed(graph)) {
3500         *res = 0;
3501         return IGRAPH_SUCCESS;
3502     }
3503 
3504     IGRAPH_VECTOR_INIT_FINALLY(&degrees, no_of_nodes);
3505     IGRAPH_VECTOR_INIT_FINALLY(&neis, 0);
3506     IGRAPH_CHECK(igraph_dqueue_init(&sources, 0));
3507     IGRAPH_FINALLY(igraph_dqueue_destroy, &sources);
3508     IGRAPH_CHECK(igraph_degree(graph, &degrees, igraph_vss_all(), IGRAPH_OUT, 1));
3509 
3510     vertices_left = no_of_nodes;
3511 
3512     /* Do we have nodes with no incoming edges? */
3513     for (i = 0; i < no_of_nodes; i++) {
3514         if (VECTOR(degrees)[i] == 0) {
3515             IGRAPH_CHECK(igraph_dqueue_push(&sources, i));
3516         }
3517     }
3518 
3519     /* Take all nodes with no incoming edges and remove them */
3520     while (!igraph_dqueue_empty(&sources)) {
3521         igraph_real_t tmp = igraph_dqueue_pop(&sources); node = (long) tmp;
3522         /* Exclude the node from further source searches */
3523         VECTOR(degrees)[node] = -1;
3524         vertices_left--;
3525         /* Get the neighbors and decrease their degrees by one */
3526         IGRAPH_CHECK(igraph_neighbors(graph, &neis, (igraph_integer_t) node,
3527                                       IGRAPH_IN));
3528         j = igraph_vector_size(&neis);
3529         for (i = 0; i < j; i++) {
3530             nei = (long)VECTOR(neis)[i];
3531             if (nei == node) {
3532                 continue;
3533             }
3534             VECTOR(degrees)[nei]--;
3535             if (VECTOR(degrees)[nei] == 0) {
3536                 IGRAPH_CHECK(igraph_dqueue_push(&sources, nei));
3537             }
3538         }
3539     }
3540 
3541     *res = (vertices_left == 0);
3542     if (vertices_left < 0) {
3543         IGRAPH_WARNING("vertices_left < 0 in igraph_is_dag, possible bug");
3544     }
3545 
3546     igraph_vector_destroy(&degrees);
3547     igraph_vector_destroy(&neis);
3548     igraph_dqueue_destroy(&sources);
3549     IGRAPH_FINALLY_CLEAN(3);
3550 
3551     return IGRAPH_SUCCESS;
3552 }
3553 
3554 /**
3555  * \function igraph_is_simple
3556  * \brief Decides whether the input graph is a simple graph.
3557  *
3558  * </para><para>
3559  * A graph is a simple graph if it does not contain loop edges and
3560  * multiple edges.
3561  *
3562  * \param graph The input graph.
3563  * \param res Pointer to a boolean constant, the result
3564  *     is stored here.
3565  * \return Error code.
3566  *
3567  * \sa \ref igraph_is_loop() and \ref igraph_is_multiple() to
3568  * find the loops and multiple edges, \ref igraph_simplify() to
3569  * get rid of them, or \ref igraph_has_multiple() to decide whether
3570  * there is at least one multiple edge.
3571  *
3572  * Time complexity: O(|V|+|E|).
3573  */
3574 
igraph_is_simple(const igraph_t * graph,igraph_bool_t * res)3575 int igraph_is_simple(const igraph_t *graph, igraph_bool_t *res) {
3576     long int vc = igraph_vcount(graph);
3577     long int ec = igraph_ecount(graph);
3578 
3579     if (vc == 0 || ec == 0) {
3580         *res = 1;
3581     } else {
3582         igraph_vector_t neis;
3583         long int i, j, n;
3584         igraph_bool_t found = 0;
3585         IGRAPH_VECTOR_INIT_FINALLY(&neis, 0);
3586         for (i = 0; i < vc; i++) {
3587             IGRAPH_CHECK(igraph_neighbors(graph, &neis, (igraph_integer_t) i, IGRAPH_OUT));
3588             n = igraph_vector_size(&neis);
3589             for (j = 0; j < n; j++) {
3590                 if (VECTOR(neis)[j] == i) {
3591                     found = 1; break;
3592                 }
3593                 if (j > 0 && VECTOR(neis)[j - 1] == VECTOR(neis)[j]) {
3594                     found = 1; break;
3595                 }
3596             }
3597         }
3598         *res = !found;
3599         igraph_vector_destroy(&neis);
3600         IGRAPH_FINALLY_CLEAN(1);
3601     }
3602 
3603     return 0;
3604 }
3605 
3606 /**
3607  * \function igraph_has_loop
3608  * \brief Returns whether the graph has at least one loop edge.
3609  *
3610  * </para><para>
3611  * A loop edge is an edge from a vertex to itself.
3612  * \param graph The input graph.
3613  * \param res Pointer to an initialized boolean vector for storing the result.
3614  *
3615  * \sa \ref igraph_simplify() to get rid of loop edges.
3616  *
3617  * Time complexity: O(e), the number of edges to check.
3618  *
3619  * \example examples/simple/igraph_has_loop.c
3620  */
3621 
igraph_has_loop(const igraph_t * graph,igraph_bool_t * res)3622 int igraph_has_loop(const igraph_t *graph, igraph_bool_t *res) {
3623     long int i, m = igraph_ecount(graph);
3624 
3625     *res = 0;
3626 
3627     for (i = 0; i < m; i++) {
3628         if (IGRAPH_FROM(graph, i) == IGRAPH_TO(graph, i)) {
3629             *res = 1;
3630             break;
3631         }
3632     }
3633 
3634     return 0;
3635 }
3636 
3637 /**
3638  * \function igraph_is_loop
3639  * \brief Find the loop edges in a graph.
3640  *
3641  * </para><para>
3642  * A loop edge is an edge from a vertex to itself.
3643  * \param graph The input graph.
3644  * \param res Pointer to an initialized boolean vector for storing the result,
3645  *         it will be resized as needed.
3646  * \param es The edges to check, for all edges supply \ref igraph_ess_all() here.
3647  * \return Error code.
3648  *
3649  * \sa \ref igraph_simplify() to get rid of loop edges.
3650  *
3651  * Time complexity: O(e), the number of edges to check.
3652  *
3653  * \example examples/simple/igraph_is_loop.c
3654  */
3655 
igraph_is_loop(const igraph_t * graph,igraph_vector_bool_t * res,igraph_es_t es)3656 int igraph_is_loop(const igraph_t *graph, igraph_vector_bool_t *res,
3657                    igraph_es_t es) {
3658     igraph_eit_t eit;
3659     long int i;
3660     IGRAPH_CHECK(igraph_eit_create(graph, es, &eit));
3661     IGRAPH_FINALLY(igraph_eit_destroy, &eit);
3662 
3663     IGRAPH_CHECK(igraph_vector_bool_resize(res, IGRAPH_EIT_SIZE(eit)));
3664 
3665     for (i = 0; !IGRAPH_EIT_END(eit); i++, IGRAPH_EIT_NEXT(eit)) {
3666         long int e = IGRAPH_EIT_GET(eit);
3667         VECTOR(*res)[i] = (IGRAPH_FROM(graph, e) == IGRAPH_TO(graph, e)) ? 1 : 0;
3668     }
3669 
3670     igraph_eit_destroy(&eit);
3671     IGRAPH_FINALLY_CLEAN(1);
3672     return 0;
3673 }
3674 
3675 /**
3676  * \function igraph_has_multiple
3677  * \brief Check whether the graph has at least one multiple edge.
3678  *
3679  * </para><para>
3680  * An edge is a multiple edge if there is another
3681  * edge with the same head and tail vertices in the graph.
3682  *
3683  * \param graph The input graph.
3684  * \param res Pointer to a boolean variable, the result will be stored here.
3685  * \return Error code.
3686  *
3687  * \sa \ref igraph_count_multiple(), \ref igraph_is_multiple() and \ref igraph_simplify().
3688  *
3689  * Time complexity: O(e*d), e is the number of edges to check and d is the
3690  * average degree (out-degree in directed graphs) of the vertices at the
3691  * tail of the edges.
3692  *
3693  * \example examples/simple/igraph_has_multiple.c
3694  */
3695 
igraph_has_multiple(const igraph_t * graph,igraph_bool_t * res)3696 int igraph_has_multiple(const igraph_t *graph, igraph_bool_t *res) {
3697     long int vc = igraph_vcount(graph);
3698     long int ec = igraph_ecount(graph);
3699     igraph_bool_t directed = igraph_is_directed(graph);
3700 
3701     if (vc == 0 || ec == 0) {
3702         *res = 0;
3703     } else {
3704         igraph_vector_t neis;
3705         long int i, j, n;
3706         igraph_bool_t found = 0;
3707         IGRAPH_VECTOR_INIT_FINALLY(&neis, 0);
3708         for (i = 0; i < vc && !found; i++) {
3709             IGRAPH_CHECK(igraph_neighbors(graph, &neis, (igraph_integer_t) i,
3710                                           IGRAPH_OUT));
3711             n = igraph_vector_size(&neis);
3712             for (j = 1; j < n; j++) {
3713                 if (VECTOR(neis)[j - 1] == VECTOR(neis)[j]) {
3714                     /* If the graph is undirected, loop edges appear twice in the neighbor
3715                      * list, so check the next item as well */
3716                     if (directed) {
3717                         /* Directed, so this is a real multiple edge */
3718                         found = 1; break;
3719                     } else if (VECTOR(neis)[j - 1] != i) {
3720                         /* Undirected, but not a loop edge */
3721                         found = 1; break;
3722                     } else if (j < n - 1 && VECTOR(neis)[j] == VECTOR(neis)[j + 1]) {
3723                         /* Undirected, loop edge, multiple times */
3724                         found = 1; break;
3725                     }
3726                 }
3727             }
3728         }
3729         *res = found;
3730         igraph_vector_destroy(&neis);
3731         IGRAPH_FINALLY_CLEAN(1);
3732     }
3733 
3734     return 0;
3735 }
3736 
3737 /**
3738  * \function igraph_is_multiple
3739  * \brief Find the multiple edges in a graph.
3740  *
3741  * </para><para>
3742  * An edge is a multiple edge if there is another
3743  * edge with the same head and tail vertices in the graph.
3744  *
3745  * </para><para>
3746  * Note that this function returns true only for the second or more
3747  * appearances of the multiple edges.
3748  * \param graph The input graph.
3749  * \param res Pointer to a boolean vector, the result will be stored
3750  *        here. It will be resized as needed.
3751  * \param es The edges to check. Supply \ref igraph_ess_all() if you want
3752  *        to check all edges.
3753  * \return Error code.
3754  *
3755  * \sa \ref igraph_count_multiple(), \ref igraph_has_multiple() and \ref igraph_simplify().
3756  *
3757  * Time complexity: O(e*d), e is the number of edges to check and d is the
3758  * average degree (out-degree in directed graphs) of the vertices at the
3759  * tail of the edges.
3760  *
3761  * \example examples/simple/igraph_is_multiple.c
3762  */
3763 
igraph_is_multiple(const igraph_t * graph,igraph_vector_bool_t * res,igraph_es_t es)3764 int igraph_is_multiple(const igraph_t *graph, igraph_vector_bool_t *res,
3765                        igraph_es_t es) {
3766     igraph_eit_t eit;
3767     long int i;
3768     igraph_lazy_inclist_t inclist;
3769 
3770     IGRAPH_CHECK(igraph_eit_create(graph, es, &eit));
3771     IGRAPH_FINALLY(igraph_eit_destroy, &eit);
3772     IGRAPH_CHECK(igraph_lazy_inclist_init(graph, &inclist, IGRAPH_OUT));
3773     IGRAPH_FINALLY(igraph_lazy_inclist_destroy, &inclist);
3774 
3775     IGRAPH_CHECK(igraph_vector_bool_resize(res, IGRAPH_EIT_SIZE(eit)));
3776 
3777     for (i = 0; !IGRAPH_EIT_END(eit); i++, IGRAPH_EIT_NEXT(eit)) {
3778         long int e = IGRAPH_EIT_GET(eit);
3779         long int from = IGRAPH_FROM(graph, e);
3780         long int to = IGRAPH_TO(graph, e);
3781         igraph_vector_t *neis = igraph_lazy_inclist_get(&inclist,
3782                                 (igraph_integer_t) from);
3783         long int j, n = igraph_vector_size(neis);
3784         VECTOR(*res)[i] = 0;
3785         for (j = 0; j < n; j++) {
3786             long int e2 = (long int) VECTOR(*neis)[j];
3787             long int to2 = IGRAPH_OTHER(graph, e2, from);
3788             if (to2 == to && e2 < e) {
3789                 VECTOR(*res)[i] = 1;
3790             }
3791         }
3792     }
3793 
3794     igraph_lazy_inclist_destroy(&inclist);
3795     igraph_eit_destroy(&eit);
3796     IGRAPH_FINALLY_CLEAN(2);
3797     return 0;
3798 }
3799 
3800 
3801 /**
3802  * \function igraph_count_multiple
3803  * \brief Count the number of appearances of the edges in a graph.
3804  *
3805  * </para><para>
3806  * If the graph has no multiple edges then the result vector will be
3807  * filled with ones.
3808  * (An edge is a multiple edge if there is another
3809  * edge with the same head and tail vertices in the graph.)
3810  *
3811  * </para><para>
3812  * \param graph The input graph.
3813  * \param res Pointer to a vector, the result will be stored
3814  *        here. It will be resized as needed.
3815  * \param es The edges to check. Supply \ref igraph_ess_all() if you want
3816  *        to check all edges.
3817  * \return Error code.
3818  *
3819  * \sa \ref igraph_is_multiple() and \ref igraph_simplify().
3820  *
3821  * Time complexity: O(E d), E is the number of edges to check and d is the
3822  * average degree (out-degree in directed graphs) of the vertices at the
3823  * tail of the edges.
3824  */
3825 
igraph_count_multiple(const igraph_t * graph,igraph_vector_t * res,igraph_es_t es)3826 int igraph_count_multiple(const igraph_t *graph, igraph_vector_t *res, igraph_es_t es) {
3827     igraph_eit_t eit;
3828     long int i;
3829     igraph_bool_t directed = igraph_is_directed(graph);
3830     igraph_lazy_inclist_t inclist;
3831 
3832     IGRAPH_CHECK(igraph_eit_create(graph, es, &eit));
3833     IGRAPH_FINALLY(igraph_eit_destroy, &eit);
3834     IGRAPH_CHECK(igraph_lazy_inclist_init(graph, &inclist, IGRAPH_OUT));
3835     IGRAPH_FINALLY(igraph_lazy_inclist_destroy, &inclist);
3836 
3837     IGRAPH_CHECK(igraph_vector_resize(res, IGRAPH_EIT_SIZE(eit)));
3838 
3839     for (i = 0; !IGRAPH_EIT_END(eit); i++, IGRAPH_EIT_NEXT(eit)) {
3840         long int e = IGRAPH_EIT_GET(eit);
3841         long int from = IGRAPH_FROM(graph, e);
3842         long int to = IGRAPH_TO(graph, e);
3843         igraph_vector_t *neis = igraph_lazy_inclist_get(&inclist,
3844                                 (igraph_integer_t) from);
3845         long int j, n = igraph_vector_size(neis);
3846         VECTOR(*res)[i] = 0;
3847         for (j = 0; j < n; j++) {
3848             long int e2 = (long int) VECTOR(*neis)[j];
3849             long int to2 = IGRAPH_OTHER(graph, e2, from);
3850             if (to2 == to) {
3851                 VECTOR(*res)[i] += 1;
3852             }
3853         }
3854         /* for loop edges, divide the result by two */
3855         if (!directed && to == from) {
3856             VECTOR(*res)[i] /= 2;
3857         }
3858     }
3859 
3860     igraph_lazy_inclist_destroy(&inclist);
3861     igraph_eit_destroy(&eit);
3862     IGRAPH_FINALLY_CLEAN(2);
3863 
3864     return IGRAPH_SUCCESS;
3865 }
3866 
3867 
3868 /**
3869  * \function igraph_girth
3870  * \brief The girth of a graph is the length of the shortest circle in it.
3871  *
3872  * </para><para>
3873  * The current implementation works for undirected graphs only,
3874  * directed graphs are treated as undirected graphs. Loop edges and
3875  * multiple edges are ignored.
3876  * </para><para>
3877  * If the graph is a forest (ie. acyclic), then zero is returned.
3878  * </para><para>
3879  * This implementation is based on Alon Itai and Michael Rodeh:
3880  * Finding a minimum circuit in a graph
3881  * \emb Proceedings of the ninth annual ACM symposium on Theory of
3882  * computing \eme, 1-10, 1977. The first implementation of this
3883  * function was done by Keith Briggs, thanks Keith.
3884  * \param graph The input graph.
3885  * \param girth Pointer to an integer, if not \c NULL then the result
3886  *     will be stored here.
3887  * \param circle Pointer to an initialized vector, the vertex ids in
3888  *     the shortest circle will be stored here. If \c NULL then it is
3889  *     ignored.
3890  * \return Error code.
3891  *
3892  * Time complexity: O((|V|+|E|)^2), |V| is the number of vertices, |E|
3893  * is the number of edges in the general case. If the graph has no
3894  * circles at all then the function needs O(|V|+|E|) time to realize
3895  * this and then it stops.
3896  *
3897  * \example examples/simple/igraph_girth.c
3898  */
3899 
igraph_girth(const igraph_t * graph,igraph_integer_t * girth,igraph_vector_t * circle)3900 int igraph_girth(const igraph_t *graph, igraph_integer_t *girth,
3901                  igraph_vector_t *circle) {
3902 
3903     long int no_of_nodes = igraph_vcount(graph);
3904     igraph_dqueue_t q;
3905     igraph_lazy_adjlist_t adjlist;
3906     long int mincirc = LONG_MAX, minvertex = 0;
3907     long int node;
3908     igraph_bool_t triangle = 0;
3909     igraph_vector_t *neis;
3910     igraph_vector_long_t level;
3911     long int stoplevel = no_of_nodes + 1;
3912     igraph_bool_t anycircle = 0;
3913     long int t1 = 0, t2 = 0;
3914 
3915     IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &adjlist, IGRAPH_ALL,
3916                                           IGRAPH_SIMPLIFY));
3917     IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &adjlist);
3918     IGRAPH_DQUEUE_INIT_FINALLY(&q, 100);
3919     IGRAPH_CHECK(igraph_vector_long_init(&level, no_of_nodes));
3920     IGRAPH_FINALLY(igraph_vector_long_destroy, &level);
3921 
3922     for (node = 0; !triangle && node < no_of_nodes; node++) {
3923 
3924         /* Are there circles in this graph at all? */
3925         if (node == 1 && anycircle == 0) {
3926             igraph_bool_t conn;
3927             IGRAPH_CHECK(igraph_is_connected(graph, &conn, IGRAPH_WEAK));
3928             if (conn) {
3929                 /* No, there are none */
3930                 break;
3931             }
3932         }
3933 
3934         anycircle = 0;
3935         igraph_dqueue_clear(&q);
3936         igraph_vector_long_null(&level);
3937         IGRAPH_CHECK(igraph_dqueue_push(&q, node));
3938         VECTOR(level)[node] = 1;
3939 
3940         IGRAPH_ALLOW_INTERRUPTION();
3941 
3942         while (!igraph_dqueue_empty(&q)) {
3943             long int actnode = (long int) igraph_dqueue_pop(&q);
3944             long int actlevel = VECTOR(level)[actnode];
3945             long int i, n;
3946 
3947             if (actlevel >= stoplevel) {
3948                 break;
3949             }
3950 
3951             neis = igraph_lazy_adjlist_get(&adjlist, (igraph_integer_t) actnode);
3952             n = igraph_vector_size(neis);
3953             for (i = 0; i < n; i++) {
3954                 long int nei = (long int) VECTOR(*neis)[i];
3955                 long int neilevel = VECTOR(level)[nei];
3956                 if (neilevel != 0) {
3957                     if (neilevel == actlevel - 1) {
3958                         continue;
3959                     } else {
3960                         /* found circle */
3961                         stoplevel = neilevel;
3962                         anycircle = 1;
3963                         if (actlevel < mincirc) {
3964                             /* Is it a minimum circle? */
3965                             mincirc = actlevel + neilevel - 1;
3966                             minvertex = node;
3967                             t1 = actnode; t2 = nei;
3968                             if (neilevel == 2) {
3969                                 /* Is it a triangle? */
3970                                 triangle = 1;
3971                             }
3972                         }
3973                         if (neilevel == actlevel) {
3974                             break;
3975                         }
3976                     }
3977                 } else {
3978                     igraph_dqueue_push(&q, nei);
3979                     VECTOR(level)[nei] = actlevel + 1;
3980                 }
3981             }
3982 
3983         } /* while q !empty */
3984     } /* node */
3985 
3986     if (girth) {
3987         if (mincirc == LONG_MAX) {
3988             *girth = mincirc = 0;
3989         } else {
3990             *girth = (igraph_integer_t) mincirc;
3991         }
3992     }
3993 
3994     /* Store the actual circle, if needed */
3995     if (circle) {
3996         IGRAPH_CHECK(igraph_vector_resize(circle, mincirc));
3997         if (mincirc != 0) {
3998             long int i, n, idx = 0;
3999             igraph_dqueue_clear(&q);
4000             igraph_vector_long_null(&level); /* used for father pointers */
4001 #define FATHER(x) (VECTOR(level)[(x)])
4002             IGRAPH_CHECK(igraph_dqueue_push(&q, minvertex));
4003             FATHER(minvertex) = minvertex;
4004             while (FATHER(t1) == 0 || FATHER(t2) == 0) {
4005                 long int actnode = (long int) igraph_dqueue_pop(&q);
4006                 neis = igraph_lazy_adjlist_get(&adjlist, (igraph_integer_t) actnode);
4007                 n = igraph_vector_size(neis);
4008                 for (i = 0; i < n; i++) {
4009                     long int nei = (long int) VECTOR(*neis)[i];
4010                     if (FATHER(nei) == 0) {
4011                         FATHER(nei) = actnode + 1;
4012                         igraph_dqueue_push(&q, nei);
4013                     }
4014                 }
4015             }  /* while q !empty */
4016             /* Ok, now use FATHER to create the path */
4017             while (t1 != minvertex) {
4018                 VECTOR(*circle)[idx++] = t1;
4019                 t1 = FATHER(t1) - 1;
4020             }
4021             VECTOR(*circle)[idx] = minvertex;
4022             idx = mincirc - 1;
4023             while (t2 != minvertex) {
4024                 VECTOR(*circle)[idx--] = t2;
4025                 t2 = FATHER(t2) - 1;
4026             }
4027         } /* anycircle */
4028     } /* circle */
4029 #undef FATHER
4030 
4031     igraph_vector_long_destroy(&level);
4032     igraph_dqueue_destroy(&q);
4033     igraph_lazy_adjlist_destroy(&adjlist);
4034     IGRAPH_FINALLY_CLEAN(3);
4035 
4036     return 0;
4037 }
4038 
4039 int igraph_i_linegraph_undirected(const igraph_t *graph, igraph_t *linegraph);
4040 
4041 int igraph_i_linegraph_directed(const igraph_t *graph, igraph_t *linegraph);
4042 
4043 /* Note to self: tried using adjacency lists instead of igraph_incident queries,
4044  * with minimal performance improvements on a graph with 70K vertices and 360K
4045  * edges. (1.09s instead of 1.10s). I think it's not worth the fuss. */
igraph_i_linegraph_undirected(const igraph_t * graph,igraph_t * linegraph)4046 int igraph_i_linegraph_undirected(const igraph_t *graph, igraph_t *linegraph) {
4047     long int no_of_edges = igraph_ecount(graph);
4048     long int i, j, n;
4049     igraph_vector_t adjedges, adjedges2;
4050     igraph_vector_t edges;
4051     long int prev = -1;
4052 
4053     IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
4054     IGRAPH_VECTOR_INIT_FINALLY(&adjedges, 0);
4055     IGRAPH_VECTOR_INIT_FINALLY(&adjedges2, 0);
4056 
4057     for (i = 0; i < no_of_edges; i++) {
4058         long int from = IGRAPH_FROM(graph, i);
4059         long int to = IGRAPH_TO(graph, i);
4060 
4061         IGRAPH_ALLOW_INTERRUPTION();
4062 
4063         if (from != prev) {
4064             IGRAPH_CHECK(igraph_incident(graph, &adjedges, (igraph_integer_t) from,
4065                                          IGRAPH_ALL));
4066         }
4067         n = igraph_vector_size(&adjedges);
4068         for (j = 0; j < n; j++) {
4069             long int e = (long int) VECTOR(adjedges)[j];
4070             if (e < i) {
4071                 IGRAPH_CHECK(igraph_vector_push_back(&edges, i));
4072                 IGRAPH_CHECK(igraph_vector_push_back(&edges, e));
4073             }
4074         }
4075 
4076         IGRAPH_CHECK(igraph_incident(graph, &adjedges2, (igraph_integer_t) to,
4077                                      IGRAPH_ALL));
4078         n = igraph_vector_size(&adjedges2);
4079         for (j = 0; j < n; j++) {
4080             long int e = (long int) VECTOR(adjedges2)[j];
4081             if (e < i) {
4082                 IGRAPH_CHECK(igraph_vector_push_back(&edges, i));
4083                 IGRAPH_CHECK(igraph_vector_push_back(&edges, e));
4084             }
4085         }
4086 
4087         prev = from;
4088     }
4089 
4090     igraph_vector_destroy(&adjedges);
4091     igraph_vector_destroy(&adjedges2);
4092     IGRAPH_FINALLY_CLEAN(2);
4093 
4094     igraph_create(linegraph, &edges, (igraph_integer_t) no_of_edges,
4095                   igraph_is_directed(graph));
4096     igraph_vector_destroy(&edges);
4097     IGRAPH_FINALLY_CLEAN(1);
4098 
4099     return 0;
4100 }
4101 
igraph_i_linegraph_directed(const igraph_t * graph,igraph_t * linegraph)4102 int igraph_i_linegraph_directed(const igraph_t *graph, igraph_t *linegraph) {
4103     long int no_of_edges = igraph_ecount(graph);
4104     long int i, j, n;
4105     igraph_vector_t adjedges;
4106     igraph_vector_t edges;
4107     long int prev = -1;
4108 
4109     IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
4110     IGRAPH_VECTOR_INIT_FINALLY(&adjedges, 0);
4111 
4112     for (i = 0; i < no_of_edges; i++) {
4113         long int from = IGRAPH_FROM(graph, i);
4114 
4115         IGRAPH_ALLOW_INTERRUPTION();
4116 
4117         if (from != prev) {
4118             IGRAPH_CHECK(igraph_incident(graph, &adjedges, (igraph_integer_t) from,
4119                                          IGRAPH_IN));
4120         }
4121         n = igraph_vector_size(&adjedges);
4122         for (j = 0; j < n; j++) {
4123             long int e = (long int) VECTOR(adjedges)[j];
4124             IGRAPH_CHECK(igraph_vector_push_back(&edges, e));
4125             IGRAPH_CHECK(igraph_vector_push_back(&edges, i));
4126         }
4127 
4128         prev = from;
4129     }
4130 
4131     igraph_vector_destroy(&adjedges);
4132     IGRAPH_FINALLY_CLEAN(1);
4133     igraph_create(linegraph, &edges, (igraph_integer_t) no_of_edges, igraph_is_directed(graph));
4134     igraph_vector_destroy(&edges);
4135     IGRAPH_FINALLY_CLEAN(1);
4136 
4137     return 0;
4138 }
4139 
4140 /**
4141  * \function igraph_linegraph
4142  * \brief Create the line graph of a graph.
4143  *
4144  * The line graph L(G) of a G undirected graph is defined as follows.
4145  * L(G) has one vertex for each edge in G and two vertices in L(G) are connected
4146  * by an edge if their corresponding edges share an end point.
4147  *
4148  * </para><para>
4149  * The line graph L(G) of a G directed graph is slightly different,
4150  * L(G) has one vertex for each edge in G and two vertices in L(G) are connected
4151  * by a directed edge if the target of the first vertex's corresponding edge
4152  * is the same as the source of the second vertex's corresponding edge.
4153  *
4154  * </para><para>
4155  * Edge \em i  in the original graph will correspond to vertex \em i
4156  * in the line graph.
4157  *
4158  * </para><para>
4159  * The first version of this function was contributed by Vincent Matossian,
4160  * thanks.
4161  * \param graph The input graph, may be directed or undirected.
4162  * \param linegraph Pointer to an uninitialized graph object, the
4163  *        result is stored here.
4164  * \return Error code.
4165  *
4166  * Time complexity: O(|V|+|E|), the number of edges plus the number of vertices.
4167  */
4168 
igraph_linegraph(const igraph_t * graph,igraph_t * linegraph)4169 int igraph_linegraph(const igraph_t *graph, igraph_t *linegraph) {
4170 
4171     if (igraph_is_directed(graph)) {
4172         return igraph_i_linegraph_directed(graph, linegraph);
4173     } else {
4174         return igraph_i_linegraph_undirected(graph, linegraph);
4175     }
4176 }
4177 
4178 /**
4179  * \function igraph_add_edge
4180  * \brief Adds a single edge to a graph.
4181  *
4182  * </para><para>
4183  * For directed graphs the edge points from \p from to \p to.
4184  *
4185  * </para><para>
4186  * Note that if you want to add many edges to a big graph, then it is
4187  * inefficient to add them one by one, it is better to collect them into
4188  * a vector and add all of them via a single \ref igraph_add_edges() call.
4189  * \param igraph The graph.
4190  * \param from The id of the first vertex of the edge.
4191  * \param to The id of the second vertex of the edge.
4192  * \return Error code.
4193  *
4194  * \sa \ref igraph_add_edges() to add many edges, \ref
4195  * igraph_delete_edges() to remove edges and \ref
4196  * igraph_add_vertices() to add vertices.
4197  *
4198  * Time complexity: O(|V|+|E|), the number of edges plus the number of
4199  * vertices.
4200  */
4201 
igraph_add_edge(igraph_t * graph,igraph_integer_t from,igraph_integer_t to)4202 int igraph_add_edge(igraph_t *graph, igraph_integer_t from, igraph_integer_t to) {
4203 
4204     igraph_vector_t edges;
4205     int ret;
4206 
4207     IGRAPH_VECTOR_INIT_FINALLY(&edges, 2);
4208 
4209     VECTOR(edges)[0] = from;
4210     VECTOR(edges)[1] = to;
4211     IGRAPH_CHECK(ret = igraph_add_edges(graph, &edges, 0));
4212 
4213     igraph_vector_destroy(&edges);
4214     IGRAPH_FINALLY_CLEAN(1);
4215     return ret;
4216 }
4217 
4218 /*
4219  * \example examples/simple/graph_convergence_degree.c
4220  */
4221 
igraph_convergence_degree(const igraph_t * graph,igraph_vector_t * result,igraph_vector_t * ins,igraph_vector_t * outs)4222 int igraph_convergence_degree(const igraph_t *graph, igraph_vector_t *result,
4223                               igraph_vector_t *ins, igraph_vector_t *outs) {
4224     long int no_of_nodes = igraph_vcount(graph);
4225     long int no_of_edges = igraph_ecount(graph);
4226     long int i, j, k, n;
4227     long int *geodist;
4228     igraph_vector_int_t *eids;
4229     igraph_vector_t *ins_p, *outs_p, ins_v, outs_v;
4230     igraph_dqueue_t q;
4231     igraph_inclist_t inclist;
4232     igraph_bool_t directed = igraph_is_directed(graph);
4233 
4234     if (result != 0) {
4235         IGRAPH_CHECK(igraph_vector_resize(result, no_of_edges));
4236     }
4237     IGRAPH_CHECK(igraph_dqueue_init(&q, 100));
4238     IGRAPH_FINALLY(igraph_dqueue_destroy, &q);
4239 
4240     if (ins == 0) {
4241         ins_p = &ins_v;
4242         IGRAPH_VECTOR_INIT_FINALLY(ins_p, no_of_edges);
4243     } else {
4244         ins_p = ins;
4245         IGRAPH_CHECK(igraph_vector_resize(ins_p, no_of_edges));
4246         igraph_vector_null(ins_p);
4247     }
4248 
4249     if (outs == 0) {
4250         outs_p = &outs_v;
4251         IGRAPH_VECTOR_INIT_FINALLY(outs_p, no_of_edges);
4252     } else {
4253         outs_p = outs;
4254         IGRAPH_CHECK(igraph_vector_resize(outs_p, no_of_edges));
4255         igraph_vector_null(outs_p);
4256     }
4257 
4258     geodist = igraph_Calloc(no_of_nodes, long int);
4259     if (geodist == 0) {
4260         IGRAPH_ERROR("Cannot calculate convergence degrees", IGRAPH_ENOMEM);
4261     }
4262     IGRAPH_FINALLY(igraph_free, geodist);
4263 
4264     /* Collect shortest paths originating from/to every node to correctly
4265      * determine input field sizes */
4266     for (k = 0; k < (directed ? 2 : 1); k++) {
4267         igraph_neimode_t neimode = (k == 0) ? IGRAPH_OUT : IGRAPH_IN;
4268         igraph_real_t *vec;
4269         IGRAPH_CHECK(igraph_inclist_init(graph, &inclist, neimode));
4270         IGRAPH_FINALLY(igraph_inclist_destroy, &inclist);
4271         vec = (k == 0) ? VECTOR(*ins_p) : VECTOR(*outs_p);
4272         for (i = 0; i < no_of_nodes; i++) {
4273             igraph_dqueue_clear(&q);
4274             memset(geodist, 0, sizeof(long int) * (size_t) no_of_nodes);
4275             geodist[i] = 1;
4276             IGRAPH_CHECK(igraph_dqueue_push(&q, i));
4277             IGRAPH_CHECK(igraph_dqueue_push(&q, 0.0));
4278             while (!igraph_dqueue_empty(&q)) {
4279                 long int actnode = (long int) igraph_dqueue_pop(&q);
4280                 long int actdist = (long int) igraph_dqueue_pop(&q);
4281                 IGRAPH_ALLOW_INTERRUPTION();
4282                 eids = igraph_inclist_get(&inclist, actnode);
4283                 n = igraph_vector_int_size(eids);
4284                 for (j = 0; j < n; j++) {
4285                     long int neighbor = IGRAPH_OTHER(graph, VECTOR(*eids)[j], actnode);
4286                     if (geodist[neighbor] != 0) {
4287                         /* we've already seen this node, another shortest path? */
4288                         if (geodist[neighbor] - 1 == actdist + 1) {
4289                             /* Since this edge is in the BFS tree rooted at i, we must
4290                              * increase either the size of the infield or the outfield */
4291                             if (!directed) {
4292                                 if (actnode < neighbor) {
4293                                     VECTOR(*ins_p)[(long int)VECTOR(*eids)[j]] += 1;
4294                                 } else {
4295                                     VECTOR(*outs_p)[(long int)VECTOR(*eids)[j]] += 1;
4296                                 }
4297                             } else {
4298                                 vec[(long int)VECTOR(*eids)[j]] += 1;
4299                             }
4300                         } else if (geodist[neighbor] - 1 < actdist + 1) {
4301                             continue;
4302                         }
4303                     } else {
4304                         /* we haven't seen this node yet */
4305                         IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor));
4306                         IGRAPH_CHECK(igraph_dqueue_push(&q, actdist + 1));
4307                         /* Since this edge is in the BFS tree rooted at i, we must
4308                          * increase either the size of the infield or the outfield */
4309                         if (!directed) {
4310                             if (actnode < neighbor) {
4311                                 VECTOR(*ins_p)[(long int)VECTOR(*eids)[j]] += 1;
4312                             } else {
4313                                 VECTOR(*outs_p)[(long int)VECTOR(*eids)[j]] += 1;
4314                             }
4315                         } else {
4316                             vec[(long int)VECTOR(*eids)[j]] += 1;
4317                         }
4318                         geodist[neighbor] = actdist + 2;
4319                     }
4320                 }
4321             }
4322         }
4323 
4324         igraph_inclist_destroy(&inclist);
4325         IGRAPH_FINALLY_CLEAN(1);
4326     }
4327 
4328     if (result != 0) {
4329         for (i = 0; i < no_of_edges; i++)
4330             VECTOR(*result)[i] = (VECTOR(*ins_p)[i] - VECTOR(*outs_p)[i]) /
4331                                  (VECTOR(*ins_p)[i] + VECTOR(*outs_p)[i]);
4332         if (!directed) {
4333             for (i = 0; i < no_of_edges; i++)
4334                 if (VECTOR(*result)[i] < 0) {
4335                     VECTOR(*result)[i] = -VECTOR(*result)[i];
4336                 }
4337         }
4338     }
4339 
4340     if (ins == 0) {
4341         igraph_vector_destroy(ins_p);
4342         IGRAPH_FINALLY_CLEAN(1);
4343     }
4344     if (outs == 0) {
4345         igraph_vector_destroy(outs_p);
4346         IGRAPH_FINALLY_CLEAN(1);
4347     }
4348 
4349     igraph_free(geodist);
4350     igraph_dqueue_destroy(&q);
4351     IGRAPH_FINALLY_CLEAN(2);
4352 
4353     return 0;
4354 }
4355 
4356 /**
4357  * \function igraph_shortest_paths_dijkstra
4358  * Weighted shortest paths from some sources.
4359  *
4360  * This function is Dijkstra's algorithm to find the weighted
4361  * shortest paths to all vertices from a single source. (It is run
4362  * independently for the given sources.) It uses a binary heap for
4363  * efficient implementation.
4364  *
4365  * \param graph The input graph, can be directed.
4366  * \param res The result, a matrix. A pointer to an initialized matrix
4367  *    should be passed here. The matrix will be resized as needed.
4368  *    Each row contains the distances from a single source, to the
4369  *    vertices given in the \c to argument.
4370  *    Unreachable vertices has distance
4371  *    \c IGRAPH_INFINITY.
4372  * \param from The source vertices.
4373  * \param to The target vertices. It is not allowed to include a
4374  *    vertex twice or more.
4375  * \param weights The edge weights. They must be all non-negative for
4376  *    Dijkstra's algorithm to work. An error code is returned if there
4377  *    is a negative edge weight in the weight vector. If this is a null
4378  *    pointer, then the
4379  *    unweighted version, \ref igraph_shortest_paths() is called.
4380  * \param mode For directed graphs; whether to follow paths along edge
4381  *    directions (\c IGRAPH_OUT), or the opposite (\c IGRAPH_IN), or
4382  *    ignore edge directions completely (\c IGRAPH_ALL). It is ignored
4383  *    for undirected graphs.
4384  * \return Error code.
4385  *
4386  * Time complexity: O(s*|E|log|E|+|V|), where |V| is the number of
4387  * vertices, |E| the number of edges and s the number of sources.
4388  *
4389  * \sa \ref igraph_shortest_paths() for a (slightly) faster unweighted
4390  * version or \ref igraph_shortest_paths_bellman_ford() for a weighted
4391  * variant that works in the presence of negative edge weights (but no
4392  * negative loops).
4393  *
4394  * \example examples/simple/dijkstra.c
4395  */
4396 
igraph_shortest_paths_dijkstra(const igraph_t * graph,igraph_matrix_t * res,const igraph_vs_t from,const igraph_vs_t to,const igraph_vector_t * weights,igraph_neimode_t mode)4397 int igraph_shortest_paths_dijkstra(const igraph_t *graph,
4398                                    igraph_matrix_t *res,
4399                                    const igraph_vs_t from,
4400                                    const igraph_vs_t to,
4401                                    const igraph_vector_t *weights,
4402                                    igraph_neimode_t mode) {
4403 
4404     /* Implementation details. This is the basic Dijkstra algorithm,
4405        with a binary heap. The heap is indexed, i.e. it stores not only
4406        the distances, but also which vertex they belong to.
4407 
4408        From now on we use a 2-way heap, so the distances can be queried
4409        directly from the heap.
4410 
4411        Dirty tricks:
4412        - the opposite of the distance is stored in the heap, as it is a
4413          maximum heap and we need a minimum heap.
4414        - we don't use IGRAPH_INFINITY in the res matrix during the
4415          computation, as IGRAPH_FINITE() might involve a function call
4416          and we want to spare that. -1 will denote infinity instead.
4417     */
4418 
4419     long int no_of_nodes = igraph_vcount(graph);
4420     long int no_of_edges = igraph_ecount(graph);
4421     igraph_2wheap_t Q;
4422     igraph_vit_t fromvit, tovit;
4423     long int no_of_from, no_of_to;
4424     igraph_lazy_inclist_t inclist;
4425     long int i, j;
4426     igraph_real_t my_infinity = IGRAPH_INFINITY;
4427     igraph_bool_t all_to;
4428     igraph_vector_t indexv;
4429 
4430     if (!weights) {
4431         return igraph_shortest_paths(graph, res, from, to, mode);
4432     }
4433 
4434     if (igraph_vector_size(weights) != no_of_edges) {
4435         IGRAPH_ERROR("Weight vector length does not match", IGRAPH_EINVAL);
4436     }
4437     if (igraph_vector_min(weights) < 0) {
4438         IGRAPH_ERROR("Weight vector must be non-negative", IGRAPH_EINVAL);
4439     }
4440 
4441     IGRAPH_CHECK(igraph_vit_create(graph, from, &fromvit));
4442     IGRAPH_FINALLY(igraph_vit_destroy, &fromvit);
4443     no_of_from = IGRAPH_VIT_SIZE(fromvit);
4444 
4445     IGRAPH_CHECK(igraph_2wheap_init(&Q, no_of_nodes));
4446     IGRAPH_FINALLY(igraph_2wheap_destroy, &Q);
4447     IGRAPH_CHECK(igraph_lazy_inclist_init(graph, &inclist, mode));
4448     IGRAPH_FINALLY(igraph_lazy_inclist_destroy, &inclist);
4449 
4450     if ( (all_to = igraph_vs_is_all(&to)) ) {
4451         no_of_to = no_of_nodes;
4452     } else {
4453         IGRAPH_VECTOR_INIT_FINALLY(&indexv, no_of_nodes);
4454         IGRAPH_CHECK(igraph_vit_create(graph, to, &tovit));
4455         IGRAPH_FINALLY(igraph_vit_destroy, &tovit);
4456         no_of_to = IGRAPH_VIT_SIZE(tovit);
4457         for (i = 0; !IGRAPH_VIT_END(tovit); IGRAPH_VIT_NEXT(tovit)) {
4458             long int v = IGRAPH_VIT_GET(tovit);
4459             if (VECTOR(indexv)[v]) {
4460                 IGRAPH_ERROR("Duplicate vertices in `to', this is not allowed",
4461                              IGRAPH_EINVAL);
4462             }
4463             VECTOR(indexv)[v] = ++i;
4464         }
4465     }
4466 
4467     IGRAPH_CHECK(igraph_matrix_resize(res, no_of_from, no_of_to));
4468     igraph_matrix_fill(res, my_infinity);
4469 
4470     for (IGRAPH_VIT_RESET(fromvit), i = 0;
4471          !IGRAPH_VIT_END(fromvit);
4472          IGRAPH_VIT_NEXT(fromvit), i++) {
4473 
4474         long int reached = 0;
4475         long int source = IGRAPH_VIT_GET(fromvit);
4476         igraph_2wheap_clear(&Q);
4477         igraph_2wheap_push_with_index(&Q, source, -1.0);
4478 
4479         while (!igraph_2wheap_empty(&Q)) {
4480             long int minnei = igraph_2wheap_max_index(&Q);
4481             igraph_real_t mindist = -igraph_2wheap_deactivate_max(&Q);
4482             igraph_vector_t *neis;
4483             long int nlen;
4484 
4485             if (all_to) {
4486                 MATRIX(*res, i, minnei) = mindist - 1.0;
4487             } else {
4488                 if (VECTOR(indexv)[minnei]) {
4489                     MATRIX(*res, i, (long int)(VECTOR(indexv)[minnei] - 1)) = mindist - 1.0;
4490                     reached++;
4491                     if (reached == no_of_to) {
4492                         igraph_2wheap_clear(&Q);
4493                         break;
4494                     }
4495                 }
4496             }
4497 
4498             /* Now check all neighbors of 'minnei' for a shorter path */
4499             neis = igraph_lazy_inclist_get(&inclist, (igraph_integer_t) minnei);
4500             nlen = igraph_vector_size(neis);
4501             for (j = 0; j < nlen; j++) {
4502                 long int edge = (long int) VECTOR(*neis)[j];
4503                 long int tto = IGRAPH_OTHER(graph, edge, minnei);
4504                 igraph_real_t altdist = mindist + VECTOR(*weights)[edge];
4505                 igraph_bool_t active = igraph_2wheap_has_active(&Q, tto);
4506                 igraph_bool_t has = igraph_2wheap_has_elem(&Q, tto);
4507                 igraph_real_t curdist = active ? -igraph_2wheap_get(&Q, tto) : 0.0;
4508                 if (!has) {
4509                     /* This is the first non-infinite distance */
4510                     IGRAPH_CHECK(igraph_2wheap_push_with_index(&Q, tto, -altdist));
4511                 } else if (altdist < curdist) {
4512                     /* This is a shorter path */
4513                     IGRAPH_CHECK(igraph_2wheap_modify(&Q, tto, -altdist));
4514                 }
4515             }
4516 
4517         } /* !igraph_2wheap_empty(&Q) */
4518 
4519     } /* !IGRAPH_VIT_END(fromvit) */
4520 
4521     if (!all_to) {
4522         igraph_vit_destroy(&tovit);
4523         igraph_vector_destroy(&indexv);
4524         IGRAPH_FINALLY_CLEAN(2);
4525     }
4526 
4527     igraph_lazy_inclist_destroy(&inclist);
4528     igraph_2wheap_destroy(&Q);
4529     igraph_vit_destroy(&fromvit);
4530     IGRAPH_FINALLY_CLEAN(3);
4531 
4532     return 0;
4533 }
4534 
4535 /**
4536  * \ingroup structural
4537  * \function igraph_get_shortest_paths_dijkstra
4538  * \brief Calculates the weighted shortest paths from/to one vertex.
4539  *
4540  * </para><para>
4541  * If there is more than one path with the smallest weight between two vertices, this
4542  * function gives only one of them.
4543  * \param graph The graph object.
4544  * \param vertices The result, the ids of the vertices along the paths.
4545  *        This is a pointer vector, each element points to a vector
4546  *        object. These should be initialized before passing them to
4547  *        the function, which will properly clear and/or resize them
4548  *        and fill the ids of the vertices along the geodesics from/to
4549  *        the vertices. Supply a null pointer here if you don't need
4550  *        these vectors. Normally, either this argument, or the \c
4551  *        edges should be non-null, but no error or warning is given
4552  *        if they are both null pointers.
4553  * \param edges The result, the ids of the edges along the paths.
4554  *        This is a pointer vector, each element points to a vector
4555  *        object. These should be initialized before passing them to
4556  *        the function, which will properly clear and/or resize them
4557  *        and fill the ids of the vertices along the geodesics from/to
4558  *        the vertices. Supply a null pointer here if you don't need
4559  *        these vectors. Normally, either this argument, or the \c
4560  *        vertices should be non-null, but no error or warning is given
4561  *        if they are both null pointers.
4562  * \param from The id of the vertex from/to which the geodesics are
4563  *        calculated.
4564  * \param to Vertex sequence with the ids of the vertices to/from which the
4565  *        shortest paths will be calculated. A vertex might be given multiple
4566  *        times.
4567  * \param weights a vector holding the edge weights. All weights must be
4568  *        positive.
4569  * \param mode The type of shortest paths to be use for the
4570  *        calculation in directed graphs. Possible values:
4571  *        \clist
4572  *        \cli IGRAPH_OUT
4573  *          the outgoing paths are calculated.
4574  *        \cli IGRAPH_IN
4575  *          the incoming paths are calculated.
4576  *        \cli IGRAPH_ALL
4577  *          the directed graph is considered as an
4578  *          undirected one for the computation.
4579  *        \endclist
4580  * \param predecessors A pointer to an initialized igraph vector or null.
4581  *        If not null, a vector containing the predecessor of each vertex in
4582  *        the single source shortest path tree is returned here. The
4583  *        predecessor of vertex i in the tree is the vertex from which vertex i
4584  *        was reached. The predecessor of the start vertex (in the \c from
4585  *        argument) is itself by definition. If the predecessor is -1, it means
4586  *        that the given vertex was not reached from the source during the
4587  *        search. Note that the search terminates if all the vertices in
4588  *        \c to are reached.
4589  * \param inbound_edges A pointer to an initialized igraph vector or null.
4590  *        If not null, a vector containing the inbound edge of each vertex in
4591  *        the single source shortest path tree is returned here. The
4592  *        inbound edge of vertex i in the tree is the edge via which vertex i
4593  *        was reached. The start vertex and vertices that were not reached
4594  *        during the search will have -1 in the corresponding entry of the
4595  *        vector. Note that the search terminates if all the vertices in
4596  *        \c to are reached.
4597  * \return Error code:
4598  *        \clist
4599  *        \cli IGRAPH_ENOMEM
4600  *           not enough memory for temporary data.
4601  *        \cli IGRAPH_EINVVID
4602  *           \p from is invalid vertex id, or the length of \p to is
4603  *           not the same as the length of \p res.
4604  *        \cli IGRAPH_EINVMODE
4605  *           invalid mode argument.
4606  *        \endclist
4607  *
4608  * Time complexity: O(|E|log|E|+|V|), where |V| is the number of
4609  * vertices and |E| is the number of edges
4610  *
4611  * \sa \ref igraph_shortest_paths_dijkstra() if you only need the path length but
4612  * not the paths themselves, \ref igraph_get_shortest_paths() if all edge
4613  * weights are equal.
4614  *
4615  * \example examples/simple/igraph_get_shortest_paths_dijkstra.c
4616  */
igraph_get_shortest_paths_dijkstra(const igraph_t * graph,igraph_vector_ptr_t * vertices,igraph_vector_ptr_t * edges,igraph_integer_t from,igraph_vs_t to,const igraph_vector_t * weights,igraph_neimode_t mode,igraph_vector_long_t * predecessors,igraph_vector_long_t * inbound_edges)4617 int igraph_get_shortest_paths_dijkstra(const igraph_t *graph,
4618                                        igraph_vector_ptr_t *vertices,
4619                                        igraph_vector_ptr_t *edges,
4620                                        igraph_integer_t from,
4621                                        igraph_vs_t to,
4622                                        const igraph_vector_t *weights,
4623                                        igraph_neimode_t mode,
4624                                        igraph_vector_long_t *predecessors,
4625                                        igraph_vector_long_t *inbound_edges) {
4626     /* Implementation details. This is the basic Dijkstra algorithm,
4627        with a binary heap. The heap is indexed, i.e. it stores not only
4628        the distances, but also which vertex they belong to. The other
4629        mapping, i.e. getting the distance for a vertex is not in the
4630        heap (that would by the double-indexed heap), but in the result
4631        matrix.
4632 
4633        Dirty tricks:
4634        - the opposite of the distance is stored in the heap, as it is a
4635          maximum heap and we need a minimum heap.
4636        - we don't use IGRAPH_INFINITY in the distance vector during the
4637          computation, as IGRAPH_FINITE() might involve a function call
4638          and we want to spare that. So we store distance+1.0 instead of
4639          distance, and zero denotes infinity.
4640        - `parents' assigns the inbound edge IDs of all vertices in the
4641          shortest path tree to the vertices. In this implementation, the
4642          edge ID + 1 is stored, zero means unreachable vertices.
4643     */
4644 
4645     long int no_of_nodes = igraph_vcount(graph);
4646     long int no_of_edges = igraph_ecount(graph);
4647     igraph_vit_t vit;
4648     igraph_2wheap_t Q;
4649     igraph_lazy_inclist_t inclist;
4650     igraph_vector_t dists;
4651     long int *parents;
4652     igraph_bool_t *is_target;
4653     long int i, to_reach;
4654 
4655     if (!weights) {
4656         return igraph_get_shortest_paths(graph, vertices, edges, from, to, mode,
4657                                          predecessors, inbound_edges);
4658     }
4659 
4660     if (igraph_vector_size(weights) != no_of_edges) {
4661         IGRAPH_ERROR("Weight vector length does not match", IGRAPH_EINVAL);
4662     }
4663     if (igraph_vector_min(weights) < 0) {
4664         IGRAPH_ERROR("Weight vector must be non-negative", IGRAPH_EINVAL);
4665     }
4666 
4667     IGRAPH_CHECK(igraph_vit_create(graph, to, &vit));
4668     IGRAPH_FINALLY(igraph_vit_destroy, &vit);
4669 
4670     if (vertices && IGRAPH_VIT_SIZE(vit) != igraph_vector_ptr_size(vertices)) {
4671         IGRAPH_ERROR("Size of `vertices' and `to' should match", IGRAPH_EINVAL);
4672     }
4673     if (edges && IGRAPH_VIT_SIZE(vit) != igraph_vector_ptr_size(edges)) {
4674         IGRAPH_ERROR("Size of `edges' and `to' should match", IGRAPH_EINVAL);
4675     }
4676 
4677     IGRAPH_CHECK(igraph_2wheap_init(&Q, no_of_nodes));
4678     IGRAPH_FINALLY(igraph_2wheap_destroy, &Q);
4679     IGRAPH_CHECK(igraph_lazy_inclist_init(graph, &inclist, mode));
4680     IGRAPH_FINALLY(igraph_lazy_inclist_destroy, &inclist);
4681 
4682     IGRAPH_VECTOR_INIT_FINALLY(&dists, no_of_nodes);
4683     igraph_vector_fill(&dists, -1.0);
4684 
4685     parents = igraph_Calloc(no_of_nodes, long int);
4686     if (parents == 0) {
4687         IGRAPH_ERROR("Can't calculate shortest paths", IGRAPH_ENOMEM);
4688     }
4689     IGRAPH_FINALLY(igraph_free, parents);
4690     is_target = igraph_Calloc(no_of_nodes, igraph_bool_t);
4691     if (is_target == 0) {
4692         IGRAPH_ERROR("Can't calculate shortest paths", IGRAPH_ENOMEM);
4693     }
4694     IGRAPH_FINALLY(igraph_free, is_target);
4695 
4696     /* Mark the vertices we need to reach */
4697     to_reach = IGRAPH_VIT_SIZE(vit);
4698     for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) {
4699         if (!is_target[ (long int) IGRAPH_VIT_GET(vit) ]) {
4700             is_target[ (long int) IGRAPH_VIT_GET(vit) ] = 1;
4701         } else {
4702             to_reach--;       /* this node was given multiple times */
4703         }
4704     }
4705 
4706     VECTOR(dists)[(long int)from] = 0.0;  /* zero distance */
4707     parents[(long int)from] = 0;
4708     igraph_2wheap_push_with_index(&Q, from, 0);
4709 
4710     while (!igraph_2wheap_empty(&Q) && to_reach > 0) {
4711         long int nlen, minnei = igraph_2wheap_max_index(&Q);
4712         igraph_real_t mindist = -igraph_2wheap_delete_max(&Q);
4713         igraph_vector_t *neis;
4714 
4715         IGRAPH_ALLOW_INTERRUPTION();
4716 
4717         if (is_target[minnei]) {
4718             is_target[minnei] = 0;
4719             to_reach--;
4720         }
4721 
4722         /* Now check all neighbors of 'minnei' for a shorter path */
4723         neis = igraph_lazy_inclist_get(&inclist, (igraph_integer_t) minnei);
4724         nlen = igraph_vector_size(neis);
4725         for (i = 0; i < nlen; i++) {
4726             long int edge = (long int) VECTOR(*neis)[i];
4727             long int tto = IGRAPH_OTHER(graph, edge, minnei);
4728             igraph_real_t altdist = mindist + VECTOR(*weights)[edge];
4729             igraph_real_t curdist = VECTOR(dists)[tto];
4730             if (curdist < 0) {
4731                 /* This is the first finite distance */
4732                 VECTOR(dists)[tto] = altdist;
4733                 parents[tto] = edge + 1;
4734                 IGRAPH_CHECK(igraph_2wheap_push_with_index(&Q, tto, -altdist));
4735             } else if (altdist < curdist) {
4736                 /* This is a shorter path */
4737                 VECTOR(dists)[tto] = altdist;
4738                 parents[tto] = edge + 1;
4739                 IGRAPH_CHECK(igraph_2wheap_modify(&Q, tto, -altdist));
4740             }
4741         }
4742     } /* !igraph_2wheap_empty(&Q) */
4743 
4744     if (to_reach > 0) {
4745         IGRAPH_WARNING("Couldn't reach some vertices");
4746     }
4747 
4748     /* Create `predecessors' if needed */
4749     if (predecessors) {
4750         IGRAPH_CHECK(igraph_vector_long_resize(predecessors, no_of_nodes));
4751 
4752         for (i = 0; i < no_of_nodes; i++) {
4753             if (i == from) {
4754                 /* i is the start vertex */
4755                 VECTOR(*predecessors)[i] = i;
4756             } else if (parents[i] <= 0) {
4757                 /* i was not reached */
4758                 VECTOR(*predecessors)[i] = -1;
4759             } else {
4760                 /* i was reached via the edge with ID = parents[i] - 1 */
4761                 VECTOR(*predecessors)[i] = IGRAPH_OTHER(graph, parents[i] - 1, i);
4762             }
4763         }
4764     }
4765 
4766     /* Create `inbound_edges' if needed */
4767     if (inbound_edges) {
4768         IGRAPH_CHECK(igraph_vector_long_resize(inbound_edges, no_of_nodes));
4769 
4770         for (i = 0; i < no_of_nodes; i++) {
4771             if (parents[i] <= 0) {
4772                 /* i was not reached */
4773                 VECTOR(*inbound_edges)[i] = -1;
4774             } else {
4775                 /* i was reached via the edge with ID = parents[i] - 1 */
4776                 VECTOR(*inbound_edges)[i] = parents[i] - 1;
4777             }
4778         }
4779     }
4780 
4781     /* Reconstruct the shortest paths based on vertex and/or edge IDs */
4782     if (vertices || edges) {
4783         for (IGRAPH_VIT_RESET(vit), i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) {
4784             long int node = IGRAPH_VIT_GET(vit);
4785             long int size, act, edge;
4786             igraph_vector_t *vvec = 0, *evec = 0;
4787             if (vertices) {
4788                 vvec = VECTOR(*vertices)[i];
4789                 igraph_vector_clear(vvec);
4790             }
4791             if (edges) {
4792                 evec = VECTOR(*edges)[i];
4793                 igraph_vector_clear(evec);
4794             }
4795 
4796             IGRAPH_ALLOW_INTERRUPTION();
4797 
4798             size = 0;
4799             act = node;
4800             while (parents[act]) {
4801                 size++;
4802                 edge = parents[act] - 1;
4803                 act = IGRAPH_OTHER(graph, edge, act);
4804             }
4805             if (vvec) {
4806                 IGRAPH_CHECK(igraph_vector_resize(vvec, size + 1));
4807                 VECTOR(*vvec)[size] = node;
4808             }
4809             if (evec) {
4810                 IGRAPH_CHECK(igraph_vector_resize(evec, size));
4811             }
4812             act = node;
4813             while (parents[act]) {
4814                 edge = parents[act] - 1;
4815                 act = IGRAPH_OTHER(graph, edge, act);
4816                 size--;
4817                 if (vvec) {
4818                     VECTOR(*vvec)[size] = act;
4819                 }
4820                 if (evec) {
4821                     VECTOR(*evec)[size] = edge;
4822                 }
4823             }
4824         }
4825     }
4826 
4827     igraph_lazy_inclist_destroy(&inclist);
4828     igraph_2wheap_destroy(&Q);
4829     igraph_vector_destroy(&dists);
4830     igraph_Free(is_target);
4831     igraph_Free(parents);
4832     igraph_vit_destroy(&vit);
4833     IGRAPH_FINALLY_CLEAN(6);
4834 
4835     return 0;
4836 }
4837 
4838 /**
4839  * \function igraph_get_shortest_path_dijkstra
4840  * Weighted shortest path from one vertex to another one.
4841  *
4842  * Calculates a single (positively) weighted shortest path from
4843  * a single vertex to another one, using Dijkstra's algorithm.
4844  *
4845  * </para><para>This function is a special case (and a wrapper) to
4846  * \ref igraph_get_shortest_paths_dijkstra().
4847  *
4848  * \param graph The input graph, it can be directed or undirected.
4849  * \param vertices Pointer to an initialized vector or a null
4850  *        pointer. If not a null pointer, then the vertex ids along
4851  *        the path are stored here, including the source and target
4852  *        vertices.
4853  * \param edges Pointer to an uninitialized vector or a null
4854  *        pointer. If not a null pointer, then the edge ids along the
4855  *        path are stored here.
4856  * \param from The id of the source vertex.
4857  * \param to The id of the target vertex.
4858  * \param weights Vector of edge weights, in the order of edge
4859  *        ids. They must be non-negative, otherwise the algorithm does
4860  *        not work.
4861  * \param mode A constant specifying how edge directions are
4862  *        considered in directed graphs. \c IGRAPH_OUT follows edge
4863  *        directions, \c IGRAPH_IN follows the opposite directions,
4864  *        and \c IGRAPH_ALL ignores edge directions. This argument is
4865  *        ignored for undirected graphs.
4866  * \return Error code.
4867  *
4868  * Time complexity: O(|E|log|E|+|V|), |V| is the number of vertices,
4869  * |E| is the number of edges in the graph.
4870  *
4871  * \sa \ref igraph_get_shortest_paths_dijkstra() for the version with
4872  * more target vertices.
4873  */
4874 
igraph_get_shortest_path_dijkstra(const igraph_t * graph,igraph_vector_t * vertices,igraph_vector_t * edges,igraph_integer_t from,igraph_integer_t to,const igraph_vector_t * weights,igraph_neimode_t mode)4875 int igraph_get_shortest_path_dijkstra(const igraph_t *graph,
4876                                       igraph_vector_t *vertices,
4877                                       igraph_vector_t *edges,
4878                                       igraph_integer_t from,
4879                                       igraph_integer_t to,
4880                                       const igraph_vector_t *weights,
4881                                       igraph_neimode_t mode) {
4882 
4883     igraph_vector_ptr_t vertices2, *vp = &vertices2;
4884     igraph_vector_ptr_t edges2, *ep = &edges2;
4885 
4886     if (vertices) {
4887         IGRAPH_CHECK(igraph_vector_ptr_init(&vertices2, 1));
4888         IGRAPH_FINALLY(igraph_vector_ptr_destroy, &vertices2);
4889         VECTOR(vertices2)[0] = vertices;
4890     } else {
4891         vp = 0;
4892     }
4893     if (edges) {
4894         IGRAPH_CHECK(igraph_vector_ptr_init(&edges2, 1));
4895         IGRAPH_FINALLY(igraph_vector_ptr_destroy, &edges2);
4896         VECTOR(edges2)[0] = edges;
4897     } else {
4898         ep = 0;
4899     }
4900 
4901     IGRAPH_CHECK(igraph_get_shortest_paths_dijkstra(graph, vp, ep,
4902                  from, igraph_vss_1(to),
4903                  weights, mode, 0, 0));
4904 
4905     if (edges) {
4906         igraph_vector_ptr_destroy(&edges2);
4907         IGRAPH_FINALLY_CLEAN(1);
4908     }
4909     if (vertices) {
4910         igraph_vector_ptr_destroy(&vertices2);
4911         IGRAPH_FINALLY_CLEAN(1);
4912     }
4913 
4914     return 0;
4915 }
4916 
4917 int igraph_i_vector_tail_cmp(const void* path1, const void* path2);
4918 
4919 /* Compares two paths based on their last elements. Required by
4920  * igraph_get_all_shortest_paths_dijkstra to put the final result
4921  * in order. Assumes that both paths are pointers to igraph_vector_t
4922  * objects and that they are not empty
4923  */
igraph_i_vector_tail_cmp(const void * path1,const void * path2)4924 int igraph_i_vector_tail_cmp(const void* path1, const void* path2) {
4925     return (int) (igraph_vector_tail(*(const igraph_vector_t**)path1) -
4926                   igraph_vector_tail(*(const igraph_vector_t**)path2));
4927 }
4928 
4929 /**
4930  * \ingroup structural
4931  * \function igraph_get_all_shortest_paths_dijkstra
4932  * \brief Finds all shortest paths (geodesics) from a vertex to all other vertices.
4933  *
4934  * \param graph The graph object.
4935  * \param res Pointer to an initialized pointer vector, the result
4936  *   will be stored here in igraph_vector_t objects. Each vector
4937  *   object contains the vertices along a shortest path from \p from
4938  *   to another vertex. The vectors are ordered according to their
4939  *   target vertex: first the shortest paths to vertex 0, then to
4940  *   vertex 1, etc. No data is included for unreachable vertices.
4941  * \param nrgeo Pointer to an initialized igraph_vector_t object or
4942  *   NULL. If not NULL the number of shortest paths from \p from are
4943  *   stored here for every vertex in the graph. Note that the values
4944  *   will be accurate only for those vertices that are in the target
4945  *   vertex sequence (see \p to), since the search terminates as soon
4946  *   as all the target vertices have been found.
4947  * \param from The id of the vertex from/to which the geodesics are
4948  *        calculated.
4949  * \param to Vertex sequence with the ids of the vertices to/from which the
4950  *        shortest paths will be calculated. A vertex might be given multiple
4951  *        times.
4952  * \param weights a vector holding the edge weights. All weights must be
4953  *        non-negative.
4954  * \param mode The type of shortest paths to be use for the
4955  *        calculation in directed graphs. Possible values:
4956  *        \clist
4957  *        \cli IGRAPH_OUT
4958  *          the outgoing paths are calculated.
4959  *        \cli IGRAPH_IN
4960  *          the incoming paths are calculated.
4961  *        \cli IGRAPH_ALL
4962  *          the directed graph is considered as an
4963  *          undirected one for the computation.
4964  *        \endclist
4965  * \return Error code:
4966  *        \clist
4967  *        \cli IGRAPH_ENOMEM
4968  *           not enough memory for temporary data.
4969  *        \cli IGRAPH_EINVVID
4970  *           \p from is invalid vertex id, or the length of \p to is
4971  *           not the same as the length of \p res.
4972  *        \cli IGRAPH_EINVMODE
4973  *           invalid mode argument.
4974  *        \endclist
4975  *
4976  * Time complexity: O(|E|log|E|+|V|), where |V| is the number of
4977  * vertices and |E| is the number of edges
4978  *
4979  * \sa \ref igraph_shortest_paths_dijkstra() if you only need the path
4980  * length but not the paths themselves, \ref igraph_get_all_shortest_paths()
4981  * if all edge weights are equal.
4982  *
4983  * \example examples/simple/igraph_get_all_shortest_paths_dijkstra.c
4984  */
igraph_get_all_shortest_paths_dijkstra(const igraph_t * graph,igraph_vector_ptr_t * res,igraph_vector_t * nrgeo,igraph_integer_t from,igraph_vs_t to,const igraph_vector_t * weights,igraph_neimode_t mode)4985 int igraph_get_all_shortest_paths_dijkstra(const igraph_t *graph,
4986         igraph_vector_ptr_t *res,
4987         igraph_vector_t *nrgeo,
4988         igraph_integer_t from, igraph_vs_t to,
4989         const igraph_vector_t *weights,
4990         igraph_neimode_t mode) {
4991     /* Implementation details: see igraph_get_shortest_paths_dijkstra,
4992        it's basically the same.
4993     */
4994 
4995     long int no_of_nodes = igraph_vcount(graph);
4996     long int no_of_edges = igraph_ecount(graph);
4997     igraph_vit_t vit;
4998     igraph_2wheap_t Q;
4999     igraph_lazy_inclist_t inclist;
5000     igraph_vector_t dists, order;
5001     igraph_vector_ptr_t parents;
5002     unsigned char *is_target;
5003     long int i, n, to_reach;
5004 
5005     if (!weights) {
5006         return igraph_get_all_shortest_paths(graph, res, nrgeo, from, to, mode);
5007     }
5008 
5009     if (res == 0 && nrgeo == 0) {
5010         return IGRAPH_SUCCESS;
5011     }
5012 
5013     if (igraph_vector_size(weights) != no_of_edges) {
5014         IGRAPH_ERROR("Weight vector length does not match", IGRAPH_EINVAL);
5015     }
5016     if (igraph_vector_min(weights) < 0) {
5017         IGRAPH_ERROR("Weight vector must be non-negative", IGRAPH_EINVAL);
5018     }
5019 
5020     /* parents stores a vector for each vertex, listing the parent vertices
5021      * of each vertex in the traversal */
5022     IGRAPH_CHECK(igraph_vector_ptr_init(&parents, no_of_nodes));
5023     IGRAPH_FINALLY(igraph_vector_ptr_destroy_all, &parents);
5024     igraph_vector_ptr_set_item_destructor(&parents, (igraph_finally_func_t*)igraph_vector_destroy);
5025     for (i = 0; i < no_of_nodes; i++) {
5026         igraph_vector_t* parent_vec;
5027         parent_vec = igraph_Calloc(1, igraph_vector_t);
5028         if (parent_vec == 0) {
5029             IGRAPH_ERROR("cannot run igraph_get_all_shortest_paths", IGRAPH_ENOMEM);
5030         }
5031         IGRAPH_CHECK(igraph_vector_init(parent_vec, 0));
5032         VECTOR(parents)[i] = parent_vec;
5033     }
5034 
5035     /* distance of each vertex from the root */
5036     IGRAPH_VECTOR_INIT_FINALLY(&dists, no_of_nodes);
5037     igraph_vector_fill(&dists, -1.0);
5038 
5039     /* order lists the order of vertices in which they were found during
5040      * the traversal */
5041     IGRAPH_VECTOR_INIT_FINALLY(&order, 0);
5042 
5043     /* boolean array to mark whether a given vertex is a target or not */
5044     is_target = igraph_Calloc(no_of_nodes, unsigned char);
5045     if (is_target == 0) {
5046         IGRAPH_ERROR("Can't calculate shortest paths", IGRAPH_ENOMEM);
5047     }
5048     IGRAPH_FINALLY(igraph_free, is_target);
5049 
5050     /* two-way heap storing vertices and distances */
5051     IGRAPH_CHECK(igraph_2wheap_init(&Q, no_of_nodes));
5052     IGRAPH_FINALLY(igraph_2wheap_destroy, &Q);
5053 
5054     /* lazy adjacency edge list to query neighbours efficiently */
5055     IGRAPH_CHECK(igraph_lazy_inclist_init(graph, &inclist, mode));
5056     IGRAPH_FINALLY(igraph_lazy_inclist_destroy, &inclist);
5057 
5058     /* Mark the vertices we need to reach */
5059     IGRAPH_CHECK(igraph_vit_create(graph, to, &vit));
5060     IGRAPH_FINALLY(igraph_vit_destroy, &vit);
5061     to_reach = IGRAPH_VIT_SIZE(vit);
5062     for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) {
5063         if (!is_target[ (long int) IGRAPH_VIT_GET(vit) ]) {
5064             is_target[ (long int) IGRAPH_VIT_GET(vit) ] = 1;
5065         } else {
5066             to_reach--;       /* this node was given multiple times */
5067         }
5068     }
5069     igraph_vit_destroy(&vit);
5070     IGRAPH_FINALLY_CLEAN(1);
5071 
5072     VECTOR(dists)[(long int)from] = 0.0;  /* zero distance */
5073     igraph_2wheap_push_with_index(&Q, from, 0);
5074 
5075     while (!igraph_2wheap_empty(&Q) && to_reach > 0) {
5076         long int nlen, minnei = igraph_2wheap_max_index(&Q);
5077         igraph_real_t mindist = -igraph_2wheap_delete_max(&Q);
5078         igraph_vector_t *neis;
5079 
5080         IGRAPH_ALLOW_INTERRUPTION();
5081 
5082         /*
5083         printf("Reached vertex %ld, is_target[%ld] = %d, %ld to go\n",
5084             minnei, minnei, (int)is_target[minnei], to_reach - is_target[minnei]);
5085         */
5086 
5087         if (is_target[minnei]) {
5088             is_target[minnei] = 0;
5089             to_reach--;
5090         }
5091 
5092         /* Mark that we have reached this vertex */
5093         IGRAPH_CHECK(igraph_vector_push_back(&order, minnei));
5094 
5095         /* Now check all neighbors of 'minnei' for a shorter path */
5096         neis = igraph_lazy_inclist_get(&inclist, (igraph_integer_t) minnei);
5097         nlen = igraph_vector_size(neis);
5098         for (i = 0; i < nlen; i++) {
5099             long int edge = (long int) VECTOR(*neis)[i];
5100             long int tto = IGRAPH_OTHER(graph, edge, minnei);
5101             igraph_real_t altdist = mindist + VECTOR(*weights)[edge];
5102             igraph_real_t curdist = VECTOR(dists)[tto];
5103             igraph_vector_t *parent_vec;
5104 
5105             if (curdist < 0) {
5106                 /* This is the first non-infinite distance */
5107                 VECTOR(dists)[tto] = altdist;
5108                 parent_vec = (igraph_vector_t*)VECTOR(parents)[tto];
5109                 IGRAPH_CHECK(igraph_vector_push_back(parent_vec, minnei));
5110                 IGRAPH_CHECK(igraph_2wheap_push_with_index(&Q, tto, -altdist));
5111             } else if (altdist == curdist && VECTOR(*weights)[edge] > 0) {
5112                 /* This is an alternative path with exactly the same length.
5113                      * Note that we consider this case only if the edge via which we
5114                      * reached the node has a nonzero weight; otherwise we could create
5115                      * infinite loops in undirected graphs by traversing zero-weight edges
5116                      * back-and-forth */
5117                 parent_vec = (igraph_vector_t*)VECTOR(parents)[tto];
5118                 IGRAPH_CHECK(igraph_vector_push_back(parent_vec, minnei));
5119             } else if (altdist < curdist) {
5120                 /* This is a shorter path */
5121                 VECTOR(dists)[tto] = altdist;
5122                 parent_vec = (igraph_vector_t*)VECTOR(parents)[tto];
5123                 igraph_vector_clear(parent_vec);
5124                 IGRAPH_CHECK(igraph_vector_push_back(parent_vec, minnei));
5125                 IGRAPH_CHECK(igraph_2wheap_modify(&Q, tto, -altdist));
5126             }
5127         }
5128     } /* !igraph_2wheap_empty(&Q) */
5129 
5130     if (to_reach > 0) {
5131         IGRAPH_WARNING("Couldn't reach some vertices");
5132     }
5133 
5134     /* we don't need these anymore */
5135     igraph_lazy_inclist_destroy(&inclist);
5136     igraph_2wheap_destroy(&Q);
5137     IGRAPH_FINALLY_CLEAN(2);
5138 
5139     /*
5140     printf("Order:\n");
5141     igraph_vector_print(&order);
5142 
5143     printf("Parent vertices:\n");
5144     for (i = 0; i < no_of_nodes; i++) {
5145       if (igraph_vector_size(VECTOR(parents)[i]) > 0) {
5146         printf("[%ld]: ", (long int)i);
5147         igraph_vector_print(VECTOR(parents)[i]);
5148       }
5149     }
5150     */
5151 
5152     if (nrgeo) {
5153         IGRAPH_CHECK(igraph_vector_resize(nrgeo, no_of_nodes));
5154         igraph_vector_null(nrgeo);
5155 
5156         /* Theoretically, we could calculate nrgeo in parallel with the traversal.
5157          * However, that way we would have to check whether nrgeo is null or not
5158          * every time we want to update some element in nrgeo. Since we need the
5159          * order vector anyway for building the final result, we could just as well
5160          * build nrgeo here.
5161          */
5162         VECTOR(*nrgeo)[(long int)from] = 1;
5163         n = igraph_vector_size(&order);
5164         for (i = 1; i < n; i++) {
5165             long int node, j, k;
5166             igraph_vector_t *parent_vec;
5167 
5168             node = (long int)VECTOR(order)[i];
5169             /* now, take the parent vertices */
5170             parent_vec = (igraph_vector_t*)VECTOR(parents)[node];
5171             k = igraph_vector_size(parent_vec);
5172             for (j = 0; j < k; j++) {
5173                 VECTOR(*nrgeo)[node] += VECTOR(*nrgeo)[(long int)VECTOR(*parent_vec)[j]];
5174             }
5175         }
5176     }
5177 
5178     if (res) {
5179         igraph_vector_t *path, *paths_index, *parent_vec;
5180         igraph_stack_t stack;
5181         long int j, node;
5182 
5183         /* a shortest path from the starting vertex to vertex i can be
5184          * obtained by calculating the shortest paths from the "parents"
5185          * of vertex i in the traversal. Knowing which of the vertices
5186          * are "targets" (see is_target), we can collect for which other
5187          * vertices do we need to calculate the shortest paths. We reuse
5188          * is_target for that; is_target = 0 means that we don't need the
5189          * vertex, is_target = 1 means that the vertex is a target (hence
5190          * we need it), is_target = 2 means that the vertex is not a target
5191          * but it stands between a shortest path between the root and one
5192          * of the targets
5193          */
5194         if (igraph_vs_is_all(&to)) {
5195             memset(is_target, 1, sizeof(unsigned char) * (size_t) no_of_nodes);
5196         } else {
5197             memset(is_target, 0, sizeof(unsigned char) * (size_t) no_of_nodes);
5198 
5199             IGRAPH_CHECK(igraph_stack_init(&stack, 0));
5200             IGRAPH_FINALLY(igraph_stack_destroy, &stack);
5201 
5202             /* Add the target vertices to the queue */
5203             IGRAPH_CHECK(igraph_vit_create(graph, to, &vit));
5204             IGRAPH_FINALLY(igraph_vit_destroy, &vit);
5205             for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) {
5206                 i = (long int) IGRAPH_VIT_GET(vit);
5207                 if (!is_target[i]) {
5208                     is_target[i] = 1;
5209                     IGRAPH_CHECK(igraph_stack_push(&stack, i));
5210                 }
5211             }
5212             igraph_vit_destroy(&vit);
5213             IGRAPH_FINALLY_CLEAN(1);
5214 
5215             while (!igraph_stack_empty(&stack)) {
5216                 /* For each parent of node i, get its parents */
5217                 igraph_real_t el = igraph_stack_pop(&stack);
5218                 parent_vec = (igraph_vector_t*)VECTOR(parents)[(long int) el];
5219                 i = igraph_vector_size(parent_vec);
5220 
5221                 for (j = 0; j < i; j++) {
5222                     /* For each parent, check if it's already in the stack.
5223                      * If not, push it and mark it in is_target */
5224                     n = (long int) VECTOR(*parent_vec)[j];
5225                     if (!is_target[n]) {
5226                         is_target[n] = 2;
5227                         IGRAPH_CHECK(igraph_stack_push(&stack, n));
5228                     }
5229                 }
5230             }
5231             igraph_stack_destroy(&stack);
5232             IGRAPH_FINALLY_CLEAN(1);
5233         }
5234 
5235         /* now, reconstruct the shortest paths from the parent list in the
5236          * order we've found the nodes during the traversal.
5237          * dists is being re-used as a vector where element i tells the
5238          * index in res where the shortest paths leading to vertex i
5239          * start, plus one (so that zero means that there are no paths
5240          * for a given vertex).
5241          */
5242         paths_index = &dists;
5243         n = igraph_vector_size(&order);
5244         igraph_vector_null(paths_index);
5245 
5246         /* clear the paths vector */
5247         igraph_vector_ptr_clear(res);
5248         igraph_vector_ptr_set_item_destructor(res,
5249                                               (igraph_finally_func_t*)igraph_vector_destroy);
5250 
5251         /* by definition, the shortest path leading to the starting vertex
5252          * consists of the vertex itself only */
5253         path = igraph_Calloc(1, igraph_vector_t);
5254         if (path == 0)
5255             IGRAPH_ERROR("cannot run igraph_get_all_shortest_paths_dijkstra",
5256                          IGRAPH_ENOMEM);
5257         IGRAPH_FINALLY(igraph_free, path);
5258         IGRAPH_CHECK(igraph_vector_init(path, 1));
5259         IGRAPH_CHECK(igraph_vector_ptr_push_back(res, path));
5260         IGRAPH_FINALLY_CLEAN(1);  /* ownership of path passed to res */
5261         VECTOR(*path)[0] = from;
5262         VECTOR(*paths_index)[(long int)from] = 1;
5263 
5264         for (i = 1; i < n; i++) {
5265             long int m, path_count;
5266             igraph_vector_t *parent_path;
5267 
5268             node = (long int) VECTOR(order)[i];
5269 
5270             /* if we don't need the shortest paths for this node (because
5271              * it is not standing in a shortest path between the source
5272              * node and any of the target nodes), skip it */
5273             if (!is_target[node]) {
5274                 continue;
5275             }
5276 
5277             IGRAPH_ALLOW_INTERRUPTION();
5278 
5279             /* we are calculating the shortest paths of node now. */
5280             /* first, we update the paths_index */
5281             path_count = igraph_vector_ptr_size(res);
5282             VECTOR(*paths_index)[node] = path_count + 1;
5283             /* res_end = (igraph_vector_t*)&(VECTOR(*res)[path_count]); */
5284 
5285             /* now, take the parent vertices */
5286             parent_vec = (igraph_vector_t*)VECTOR(parents)[node];
5287             m = igraph_vector_size(parent_vec);
5288 
5289             /*
5290             printf("Calculating shortest paths to vertex %ld\n", node);
5291             printf("Parents are: ");
5292             igraph_vector_print(parent_vec);
5293             */
5294 
5295             for (j = 0; j < m; j++) {
5296                 /* for each parent, copy the shortest paths leading to that parent
5297                  * and add the current vertex in the end */
5298                 long int parent_node = (long int) VECTOR(*parent_vec)[j];
5299                 long int parent_path_idx = (long int) VECTOR(*paths_index)[parent_node] - 1;
5300                 /*
5301                 printf("  Considering parent: %ld\n", parent_node);
5302                 printf("  Paths to parent start at index %ld in res\n", parent_path_idx);
5303                 */
5304                 assert(parent_path_idx >= 0);
5305                 for (; parent_path_idx < path_count; parent_path_idx++) {
5306                     parent_path = (igraph_vector_t*)VECTOR(*res)[parent_path_idx];
5307                     if (igraph_vector_tail(parent_path) != parent_node) {
5308                         break;
5309                     }
5310 
5311                     path = igraph_Calloc(1, igraph_vector_t);
5312                     if (path == 0)
5313                         IGRAPH_ERROR("cannot run igraph_get_all_shortest_paths_dijkstra",
5314                                      IGRAPH_ENOMEM);
5315                     IGRAPH_FINALLY(igraph_free, path);
5316                     IGRAPH_CHECK(igraph_vector_copy(path, parent_path));
5317                     IGRAPH_CHECK(igraph_vector_ptr_push_back(res, path));
5318                     IGRAPH_FINALLY_CLEAN(1);  /* ownership of path passed to res */
5319                     IGRAPH_CHECK(igraph_vector_push_back(path, node));
5320                 }
5321             }
5322         }
5323 
5324         /* remove the destructor from the path vector */
5325         igraph_vector_ptr_set_item_destructor(res, 0);
5326 
5327         /* free those paths from the result vector which we won't need */
5328         n = igraph_vector_ptr_size(res);
5329         j = 0;
5330         for (i = 0; i < n; i++) {
5331             igraph_real_t tmp;
5332             path = (igraph_vector_t*)VECTOR(*res)[i];
5333             tmp = igraph_vector_tail(path);
5334             if (is_target[(long int)tmp] == 1) {
5335                 /* we need this path, keep it */
5336                 VECTOR(*res)[j] = path;
5337                 j++;
5338             } else {
5339                 /* we don't need this path, free it */
5340                 igraph_vector_destroy(path); free(path);
5341             }
5342         }
5343         IGRAPH_CHECK(igraph_vector_ptr_resize(res, j));
5344 
5345         /* sort the paths by the target vertices */
5346         igraph_vector_ptr_sort(res, igraph_i_vector_tail_cmp);
5347     }
5348 
5349     /* free the allocated memory */
5350     igraph_vector_destroy(&order);
5351     igraph_Free(is_target);
5352     igraph_vector_destroy(&dists);
5353     igraph_vector_ptr_destroy_all(&parents);
5354     IGRAPH_FINALLY_CLEAN(4);
5355 
5356     return 0;
5357 }
5358 
5359 /**
5360  * \function igraph_shortest_paths_bellman_ford
5361  * Weighted shortest paths from some sources allowing negative weights.
5362  *
5363  * This function is the Bellman-Ford algorithm to find the weighted
5364  * shortest paths to all vertices from a single source. (It is run
5365  * independently for the given sources.). If there are no negative
5366  * weights, you are better off with \ref igraph_shortest_paths_dijkstra() .
5367  *
5368  * \param graph The input graph, can be directed.
5369  * \param res The result, a matrix. A pointer to an initialized matrix
5370  *    should be passed here, the matrix will be resized if needed.
5371  *    Each row contains the distances from a single source, to all
5372  *    vertices in the graph, in the order of vertex ids. For unreachable
5373  *    vertices the matrix contains \c IGRAPH_INFINITY.
5374  * \param from The source vertices.
5375  * \param weights The edge weights. There mustn't be any closed loop in
5376  *    the graph that has a negative total weight (since this would allow
5377  *    us to decrease the weight of any path containing at least a single
5378  *    vertex of this loop infinitely). If this is a null pointer, then the
5379  *    unweighted version, \ref igraph_shortest_paths() is called.
5380  * \param mode For directed graphs; whether to follow paths along edge
5381  *    directions (\c IGRAPH_OUT), or the opposite (\c IGRAPH_IN), or
5382  *    ignore edge directions completely (\c IGRAPH_ALL). It is ignored
5383  *    for undirected graphs.
5384  * \return Error code.
5385  *
5386  * Time complexity: O(s*|E|*|V|), where |V| is the number of
5387  * vertices, |E| the number of edges and s the number of sources.
5388  *
5389  * \sa \ref igraph_shortest_paths() for a faster unweighted version
5390  * or \ref igraph_shortest_paths_dijkstra() if you do not have negative
5391  * edge weights.
5392  *
5393  * \example examples/simple/bellman_ford.c
5394  */
5395 
igraph_shortest_paths_bellman_ford(const igraph_t * graph,igraph_matrix_t * res,const igraph_vs_t from,const igraph_vs_t to,const igraph_vector_t * weights,igraph_neimode_t mode)5396 int igraph_shortest_paths_bellman_ford(const igraph_t *graph,
5397                                        igraph_matrix_t *res,
5398                                        const igraph_vs_t from,
5399                                        const igraph_vs_t to,
5400                                        const igraph_vector_t *weights,
5401                                        igraph_neimode_t mode) {
5402     long int no_of_nodes = igraph_vcount(graph);
5403     long int no_of_edges = igraph_ecount(graph);
5404     igraph_lazy_inclist_t inclist;
5405     long int i, j, k;
5406     long int no_of_from, no_of_to;
5407     igraph_dqueue_t Q;
5408     igraph_vector_t clean_vertices;
5409     igraph_vector_t num_queued;
5410     igraph_vit_t fromvit, tovit;
5411     igraph_real_t my_infinity = IGRAPH_INFINITY;
5412     igraph_bool_t all_to;
5413     igraph_vector_t dist;
5414 
5415     /*
5416        - speedup: a vertex is marked clean if its distance from the source
5417          did not change during the last phase. Neighbors of a clean vertex
5418          are not relaxed again, since it would mean no change in the
5419          shortest path values. Dirty vertices are queued. Negative loops can
5420          be detected by checking whether a vertex has been queued at least
5421          n times.
5422     */
5423     if (!weights) {
5424         return igraph_shortest_paths(graph, res, from, to, mode);
5425     }
5426 
5427     if (igraph_vector_size(weights) != no_of_edges) {
5428         IGRAPH_ERROR("Weight vector length does not match", IGRAPH_EINVAL);
5429     }
5430 
5431     IGRAPH_CHECK(igraph_vit_create(graph, from, &fromvit));
5432     IGRAPH_FINALLY(igraph_vit_destroy, &fromvit);
5433     no_of_from = IGRAPH_VIT_SIZE(fromvit);
5434 
5435     IGRAPH_DQUEUE_INIT_FINALLY(&Q, no_of_nodes);
5436     IGRAPH_VECTOR_INIT_FINALLY(&clean_vertices, no_of_nodes);
5437     IGRAPH_VECTOR_INIT_FINALLY(&num_queued, no_of_nodes);
5438     IGRAPH_CHECK(igraph_lazy_inclist_init(graph, &inclist, mode));
5439     IGRAPH_FINALLY(igraph_lazy_inclist_destroy, &inclist);
5440 
5441     if ( (all_to = igraph_vs_is_all(&to)) ) {
5442         no_of_to = no_of_nodes;
5443     } else {
5444         IGRAPH_CHECK(igraph_vit_create(graph, to, &tovit));
5445         IGRAPH_FINALLY(igraph_vit_destroy, &tovit);
5446         no_of_to = IGRAPH_VIT_SIZE(tovit);
5447     }
5448 
5449     IGRAPH_VECTOR_INIT_FINALLY(&dist, no_of_nodes);
5450     IGRAPH_CHECK(igraph_matrix_resize(res, no_of_from, no_of_to));
5451 
5452     for (IGRAPH_VIT_RESET(fromvit), i = 0;
5453          !IGRAPH_VIT_END(fromvit);
5454          IGRAPH_VIT_NEXT(fromvit), i++) {
5455         long int source = IGRAPH_VIT_GET(fromvit);
5456 
5457         igraph_vector_fill(&dist, my_infinity);
5458         VECTOR(dist)[source] = 0;
5459         igraph_vector_null(&clean_vertices);
5460         igraph_vector_null(&num_queued);
5461 
5462         /* Fill the queue with vertices to be checked */
5463         for (j = 0; j < no_of_nodes; j++) {
5464             IGRAPH_CHECK(igraph_dqueue_push(&Q, j));
5465         }
5466 
5467         while (!igraph_dqueue_empty(&Q)) {
5468             igraph_vector_t *neis;
5469             long int nlen;
5470 
5471             j = (long int) igraph_dqueue_pop(&Q);
5472             VECTOR(clean_vertices)[j] = 1;
5473             VECTOR(num_queued)[j] += 1;
5474             if (VECTOR(num_queued)[j] > no_of_nodes) {
5475                 IGRAPH_ERROR("cannot run Bellman-Ford algorithm", IGRAPH_ENEGLOOP);
5476             }
5477 
5478             /* If we cannot get to j in finite time yet, there is no need to relax
5479              * its edges */
5480             if (!IGRAPH_FINITE(VECTOR(dist)[j])) {
5481                 continue;
5482             }
5483 
5484             neis = igraph_lazy_inclist_get(&inclist, (igraph_integer_t) j);
5485             nlen = igraph_vector_size(neis);
5486 
5487             for (k = 0; k < nlen; k++) {
5488                 long int nei = (long int) VECTOR(*neis)[k];
5489                 long int target = IGRAPH_OTHER(graph, nei, j);
5490                 if (VECTOR(dist)[target] > VECTOR(dist)[j] + VECTOR(*weights)[nei]) {
5491                     /* relax the edge */
5492                     VECTOR(dist)[target] = VECTOR(dist)[j] + VECTOR(*weights)[nei];
5493                     if (VECTOR(clean_vertices)[target]) {
5494                         VECTOR(clean_vertices)[target] = 0;
5495                         IGRAPH_CHECK(igraph_dqueue_push(&Q, target));
5496                     }
5497                 }
5498             }
5499         }
5500 
5501         /* Copy it to the result */
5502         if (all_to) {
5503             igraph_matrix_set_row(res, &dist, i);
5504         } else {
5505             for (IGRAPH_VIT_RESET(tovit), j = 0; !IGRAPH_VIT_END(tovit);
5506                  IGRAPH_VIT_NEXT(tovit), j++) {
5507                 long int v = IGRAPH_VIT_GET(tovit);
5508                 MATRIX(*res, i, j) = VECTOR(dist)[v];
5509             }
5510         }
5511     }
5512 
5513     igraph_vector_destroy(&dist);
5514     IGRAPH_FINALLY_CLEAN(1);
5515 
5516     if (!all_to) {
5517         igraph_vit_destroy(&tovit);
5518         IGRAPH_FINALLY_CLEAN(1);
5519     }
5520 
5521     igraph_vit_destroy(&fromvit);
5522     igraph_dqueue_destroy(&Q);
5523     igraph_vector_destroy(&clean_vertices);
5524     igraph_vector_destroy(&num_queued);
5525     igraph_lazy_inclist_destroy(&inclist);
5526     IGRAPH_FINALLY_CLEAN(5);
5527 
5528     return 0;
5529 }
5530 
5531 /**
5532  * \function igraph_shortest_paths_johnson
5533  * Calculate shortest paths from some sources using Johnson's algorithm.
5534  *
5535  * See Wikipedia at http://en.wikipedia.org/wiki/Johnson's_algorithm
5536  * for Johnson's algorithm. This algorithm works even if the graph
5537  * contains negative edge weights, and it is worth using it if we
5538  * calculate the shortest paths from many sources.
5539  *
5540  * </para><para> If no edge weights are supplied, then the unweighted
5541  * version, \ref igraph_shortest_paths() is called.
5542  *
5543  * </para><para> If all the supplied edge weights are non-negative,
5544  * then Dijkstra's algorithm is used by calling
5545  * \ref igraph_shortest_paths_dijkstra().
5546  *
5547  * \param graph The input graph, typically it is directed.
5548  * \param res Pointer to an initialized matrix, the result will be
5549  *   stored here, one line for each source vertex, one column for each
5550  *   target vertex.
5551  * \param from The source vertices.
5552  * \param to The target vertices. It is not allowed to include a
5553  *   vertex twice or more.
5554  * \param weights Optional edge weights. If it is a null-pointer, then
5555  *   the unweighted breadth-first search based \ref
5556  *   igraph_shortest_paths() will be called.
5557  * \return Error code.
5558  *
5559  * Time complexity: O(s|V|log|V|+|V||E|), |V| and |E| are the number
5560  * of vertices and edges, s is the number of source vertices.
5561  *
5562  * \sa \ref igraph_shortest_paths() for a faster unweighted version
5563  * or \ref igraph_shortest_paths_dijkstra() if you do not have negative
5564  * edge weights, \ref igraph_shortest_paths_bellman_ford() if you only
5565  * need to calculate shortest paths from a couple of sources.
5566  */
5567 
igraph_shortest_paths_johnson(const igraph_t * graph,igraph_matrix_t * res,const igraph_vs_t from,const igraph_vs_t to,const igraph_vector_t * weights)5568 int igraph_shortest_paths_johnson(const igraph_t *graph,
5569                                   igraph_matrix_t *res,
5570                                   const igraph_vs_t from,
5571                                   const igraph_vs_t to,
5572                                   const igraph_vector_t *weights) {
5573 
5574     long int no_of_nodes = igraph_vcount(graph);
5575     long int no_of_edges = igraph_ecount(graph);
5576     igraph_t newgraph;
5577     igraph_vector_t edges, newweights;
5578     igraph_matrix_t bfres;
5579     long int i, ptr;
5580     long int nr, nc;
5581     igraph_vit_t fromvit;
5582 
5583     /* If no weights, then we can just run the unweighted version */
5584     if (!weights) {
5585         return igraph_shortest_paths(graph, res, from, to, IGRAPH_OUT);
5586     }
5587 
5588     if (igraph_vector_size(weights) != no_of_edges) {
5589         IGRAPH_ERROR("Weight vector length does not match", IGRAPH_EINVAL);
5590     }
5591 
5592     /* If no negative weights, then we can run Dijkstra's algorithm */
5593     if (igraph_vector_min(weights) >= 0) {
5594         return igraph_shortest_paths_dijkstra(graph, res, from, to,
5595                                               weights, IGRAPH_OUT);
5596     }
5597 
5598     if (!igraph_is_directed(graph)) {
5599         IGRAPH_ERROR("Johnson's shortest path: undirected graph and negative weight",
5600                      IGRAPH_EINVAL);
5601     }
5602 
5603     /* ------------------------------------------------------------ */
5604     /* -------------------- Otherwise proceed --------------------- */
5605 
5606     IGRAPH_MATRIX_INIT_FINALLY(&bfres, 0, 0);
5607     IGRAPH_VECTOR_INIT_FINALLY(&newweights, 0);
5608 
5609     IGRAPH_CHECK(igraph_empty(&newgraph, (igraph_integer_t) no_of_nodes + 1,
5610                               igraph_is_directed(graph)));
5611     IGRAPH_FINALLY(igraph_destroy, &newgraph);
5612 
5613     /* Add a new node to the graph, plus edges from it to all the others. */
5614     IGRAPH_VECTOR_INIT_FINALLY(&edges, no_of_edges * 2 + no_of_nodes * 2);
5615     igraph_get_edgelist(graph, &edges, /*bycol=*/ 0);
5616     igraph_vector_resize(&edges, no_of_edges * 2 + no_of_nodes * 2);
5617     for (i = 0, ptr = no_of_edges * 2; i < no_of_nodes; i++) {
5618         VECTOR(edges)[ptr++] = no_of_nodes;
5619         VECTOR(edges)[ptr++] = i;
5620     }
5621     IGRAPH_CHECK(igraph_add_edges(&newgraph, &edges, 0));
5622     igraph_vector_destroy(&edges);
5623     IGRAPH_FINALLY_CLEAN(1);
5624 
5625     IGRAPH_CHECK(igraph_vector_reserve(&newweights, no_of_edges + no_of_nodes));
5626     igraph_vector_update(&newweights, weights);
5627     igraph_vector_resize(&newweights, no_of_edges + no_of_nodes);
5628     for (i = no_of_edges; i < no_of_edges + no_of_nodes; i++) {
5629         VECTOR(newweights)[i] = 0;
5630     }
5631 
5632     /* Run Bellmann-Ford algorithm on the new graph, starting from the
5633        new vertex.  */
5634 
5635     IGRAPH_CHECK(igraph_shortest_paths_bellman_ford(&newgraph, &bfres,
5636                  igraph_vss_1((igraph_integer_t) no_of_nodes),
5637                  igraph_vss_all(), &newweights, IGRAPH_OUT));
5638 
5639     igraph_destroy(&newgraph);
5640     IGRAPH_FINALLY_CLEAN(1);
5641 
5642     /* Now the edges of the original graph are reweighted, using the
5643        values from the BF algorithm. Instead of w(u,v) we will have
5644        w(u,v) + h(u) - h(v) */
5645 
5646     igraph_vector_resize(&newweights, no_of_edges);
5647     for (i = 0; i < no_of_edges; i++) {
5648         long int ffrom = IGRAPH_FROM(graph, i);
5649         long int tto = IGRAPH_TO(graph, i);
5650         VECTOR(newweights)[i] += MATRIX(bfres, 0, ffrom) - MATRIX(bfres, 0, tto);
5651     }
5652 
5653     /* Run Dijkstra's algorithm on the new weights */
5654     IGRAPH_CHECK(igraph_shortest_paths_dijkstra(graph, res, from,
5655                  to, &newweights,
5656                  IGRAPH_OUT));
5657 
5658     igraph_vector_destroy(&newweights);
5659     IGRAPH_FINALLY_CLEAN(1);
5660 
5661     /* Reweight the shortest paths */
5662     nr = igraph_matrix_nrow(res);
5663     nc = igraph_matrix_ncol(res);
5664 
5665     IGRAPH_CHECK(igraph_vit_create(graph, from, &fromvit));
5666     IGRAPH_FINALLY(igraph_vit_destroy, &fromvit);
5667 
5668     for (i = 0; i < nr; i++, IGRAPH_VIT_NEXT(fromvit)) {
5669         long int v1 = IGRAPH_VIT_GET(fromvit);
5670         if (igraph_vs_is_all(&to)) {
5671             long int v2;
5672             for (v2 = 0; v2 < nc; v2++) {
5673                 igraph_real_t sub = MATRIX(bfres, 0, v1) - MATRIX(bfres, 0, v2);
5674                 MATRIX(*res, i, v2) -= sub;
5675             }
5676         } else {
5677             long int j;
5678             igraph_vit_t tovit;
5679             IGRAPH_CHECK(igraph_vit_create(graph, to, &tovit));
5680             IGRAPH_FINALLY(igraph_vit_destroy, &tovit);
5681             for (j = 0, IGRAPH_VIT_RESET(tovit); j < nc; j++, IGRAPH_VIT_NEXT(tovit)) {
5682                 long int v2 = IGRAPH_VIT_GET(tovit);
5683                 igraph_real_t sub = MATRIX(bfres, 0, v1) - MATRIX(bfres, 0, v2);
5684                 MATRIX(*res, i, v2) -= sub;
5685             }
5686             igraph_vit_destroy(&tovit);
5687             IGRAPH_FINALLY_CLEAN(1);
5688         }
5689     }
5690 
5691     igraph_vit_destroy(&fromvit);
5692     igraph_matrix_destroy(&bfres);
5693     IGRAPH_FINALLY_CLEAN(2);
5694 
5695     return 0;
5696 }
5697 
5698 /**
5699  * \function igraph_unfold_tree
5700  * Unfolding a graph into a tree, by possibly multiplicating its vertices.
5701  *
5702  * A graph is converted into a tree (or forest, if it is unconnected),
5703  * by performing a breadth-first search on it, and replicating
5704  * vertices that were found a second, third, etc. time.
5705  * \param graph The input graph, it can be either directed or
5706  *   undirected.
5707  * \param tree Pointer to an uninitialized graph object, the result is
5708  *   stored here.
5709  * \param mode For directed graphs; whether to follow paths along edge
5710  *    directions (\c IGRAPH_OUT), or the opposite (\c IGRAPH_IN), or
5711  *    ignore edge directions completely (\c IGRAPH_ALL). It is ignored
5712  *    for undirected graphs.
5713  * \param roots A numeric vector giving the root vertex, or vertices
5714  *   (if the graph is not connected), to start from.
5715  * \param vertex_index Pointer to an initialized vector, or a null
5716  *   pointer. If not a null pointer, then a mapping from the vertices
5717  *   in the new graph to the ones in the original is created here.
5718  * \return Error code.
5719  *
5720  * Time complexity: O(n+m), linear in the number vertices and edges.
5721  *
5722  */
5723 
igraph_unfold_tree(const igraph_t * graph,igraph_t * tree,igraph_neimode_t mode,const igraph_vector_t * roots,igraph_vector_t * vertex_index)5724 int igraph_unfold_tree(const igraph_t *graph, igraph_t *tree,
5725                        igraph_neimode_t mode, const igraph_vector_t *roots,
5726                        igraph_vector_t *vertex_index) {
5727 
5728     long int no_of_nodes = igraph_vcount(graph);
5729     long int no_of_edges = igraph_ecount(graph);
5730     long int no_of_roots = igraph_vector_size(roots);
5731     long int tree_vertex_count = no_of_nodes;
5732 
5733     igraph_vector_t edges;
5734     igraph_vector_bool_t seen_vertices;
5735     igraph_vector_bool_t seen_edges;
5736 
5737     igraph_dqueue_t Q;
5738     igraph_vector_t neis;
5739 
5740     long int i, n, r, v_ptr = no_of_nodes;
5741 
5742     /* TODO: handle not-connected graphs, multiple root vertices */
5743 
5744     IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
5745     igraph_vector_reserve(&edges, no_of_edges * 2);
5746     IGRAPH_DQUEUE_INIT_FINALLY(&Q, 100);
5747     IGRAPH_VECTOR_INIT_FINALLY(&neis, 0);
5748     IGRAPH_VECTOR_BOOL_INIT_FINALLY(&seen_vertices, no_of_nodes);
5749     IGRAPH_VECTOR_BOOL_INIT_FINALLY(&seen_edges, no_of_edges);
5750 
5751     if (vertex_index) {
5752         IGRAPH_CHECK(igraph_vector_resize(vertex_index, no_of_nodes));
5753         for (i = 0; i < no_of_nodes; i++) {
5754             VECTOR(*vertex_index)[i] = i;
5755         }
5756     }
5757 
5758     for (r = 0; r < no_of_roots; r++) {
5759 
5760         long int root = (long int) VECTOR(*roots)[r];
5761         VECTOR(seen_vertices)[root] = 1;
5762         igraph_dqueue_push(&Q, root);
5763 
5764         while (!igraph_dqueue_empty(&Q)) {
5765             long int actnode = (long int) igraph_dqueue_pop(&Q);
5766 
5767             IGRAPH_CHECK(igraph_incident(graph, &neis, (igraph_integer_t) actnode, mode));
5768             n = igraph_vector_size(&neis);
5769             for (i = 0; i < n; i++) {
5770 
5771                 long int edge = (long int) VECTOR(neis)[i];
5772                 long int from = IGRAPH_FROM(graph, edge);
5773                 long int to = IGRAPH_TO(graph, edge);
5774                 long int nei = IGRAPH_OTHER(graph, edge, actnode);
5775 
5776                 if (! VECTOR(seen_edges)[edge]) {
5777 
5778                     VECTOR(seen_edges)[edge] = 1;
5779 
5780                     if (! VECTOR(seen_vertices)[nei]) {
5781 
5782                         igraph_vector_push_back(&edges, from);
5783                         igraph_vector_push_back(&edges, to);
5784 
5785                         VECTOR(seen_vertices)[nei] = 1;
5786                         IGRAPH_CHECK(igraph_dqueue_push(&Q, nei));
5787 
5788                     } else {
5789 
5790                         tree_vertex_count++;
5791                         if (vertex_index) {
5792                             IGRAPH_CHECK(igraph_vector_push_back(vertex_index, nei));
5793                         }
5794 
5795                         if (from == nei) {
5796                             igraph_vector_push_back(&edges, v_ptr++);
5797                             igraph_vector_push_back(&edges, to);
5798                         } else {
5799                             igraph_vector_push_back(&edges, from);
5800                             igraph_vector_push_back(&edges, v_ptr++);
5801                         }
5802                     }
5803                 }
5804 
5805             } /* for i<n */
5806 
5807         } /* ! igraph_dqueue_empty(&Q) */
5808 
5809     } /* r < igraph_vector_size(roots) */
5810 
5811     igraph_vector_bool_destroy(&seen_edges);
5812     igraph_vector_bool_destroy(&seen_vertices);
5813     igraph_vector_destroy(&neis);
5814     igraph_dqueue_destroy(&Q);
5815     IGRAPH_FINALLY_CLEAN(4);
5816 
5817     IGRAPH_CHECK(igraph_create(tree, &edges, tree_vertex_count, igraph_is_directed(graph)));
5818     igraph_vector_destroy(&edges);
5819     IGRAPH_FINALLY_CLEAN(1);
5820 
5821     return 0;
5822 }
5823 
5824 /**
5825  * \function igraph_is_mutual
5826  * Check whether the edges of a directed graph are mutual.
5827  *
5828  * An (A,B) edge is mutual if the graph contains the (B,A) edge, too.
5829  * </para>
5830  *
5831  * <para>An undirected graph only has mutual edges, by definition.
5832  * </para>
5833  *
5834  * <para>Edge multiplicity is not considered here, e.g. if there are two
5835  * (A,B) edges and one (B,A) edge, then all three are considered to be
5836  * mutual.
5837  *
5838  * \param graph The input graph.
5839  * \param res Pointer to an initialized vector, the result is stored
5840  *        here.
5841  * \param es The sequence of edges to check. Supply
5842  *        <code>igraph_ess_all()</code> for all edges, see \ref
5843  *        igraph_ess_all().
5844  * \return Error code.
5845  *
5846  * Time complexity: O(n log(d)), n is the number of edges supplied, d
5847  * is the maximum in-degree of the vertices that are targets of the
5848  * supplied edges. An upper limit of the time complexity is O(n log(|E|)),
5849  * |E| is the number of edges in the graph.
5850  */
5851 
igraph_is_mutual(igraph_t * graph,igraph_vector_bool_t * res,igraph_es_t es)5852 int igraph_is_mutual(igraph_t *graph, igraph_vector_bool_t *res, igraph_es_t es) {
5853 
5854     igraph_eit_t eit;
5855     igraph_lazy_adjlist_t adjlist;
5856     long int i;
5857 
5858     /* How many edges do we have? */
5859     IGRAPH_CHECK(igraph_eit_create(graph, es, &eit));
5860     IGRAPH_FINALLY(igraph_eit_destroy, &eit);
5861     IGRAPH_CHECK(igraph_vector_bool_resize(res, IGRAPH_EIT_SIZE(eit)));
5862 
5863     /* An undirected graph has mutual edges by definition,
5864        res is already properly resized */
5865     if (! igraph_is_directed(graph)) {
5866         igraph_vector_bool_fill(res, 1);
5867         igraph_eit_destroy(&eit);
5868         IGRAPH_FINALLY_CLEAN(1);
5869         return 0;
5870     }
5871 
5872     IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &adjlist, IGRAPH_OUT, IGRAPH_DONT_SIMPLIFY));
5873     IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &adjlist);
5874 
5875     for (i = 0; ! IGRAPH_EIT_END(eit); i++, IGRAPH_EIT_NEXT(eit)) {
5876         long int edge = IGRAPH_EIT_GET(eit);
5877         long int from = IGRAPH_FROM(graph, edge);
5878         long int to = IGRAPH_TO(graph, edge);
5879 
5880         /* Check whether there is a to->from edge, search for from in the
5881            out-list of to. We don't search an empty vector, because
5882            vector_binsearch seems to have a bug with this. */
5883         igraph_vector_t *neis = igraph_lazy_adjlist_get(&adjlist,
5884                                 (igraph_integer_t) to);
5885         if (igraph_vector_empty(neis)) {
5886             VECTOR(*res)[i] = 0;
5887         } else {
5888             VECTOR(*res)[i] = igraph_vector_binsearch2(neis, from);
5889         }
5890     }
5891 
5892     igraph_lazy_adjlist_destroy(&adjlist);
5893     igraph_eit_destroy(&eit);
5894     IGRAPH_FINALLY_CLEAN(2);
5895 
5896     return 0;
5897 }
5898 
5899 int igraph_i_avg_nearest_neighbor_degree_weighted(const igraph_t *graph,
5900         igraph_vs_t vids,
5901         igraph_neimode_t mode,
5902         igraph_neimode_t neighbor_degree_mode,
5903         igraph_vector_t *knn,
5904         igraph_vector_t *knnk,
5905         const igraph_vector_t *weights);
5906 
igraph_i_avg_nearest_neighbor_degree_weighted(const igraph_t * graph,igraph_vs_t vids,igraph_neimode_t mode,igraph_neimode_t neighbor_degree_mode,igraph_vector_t * knn,igraph_vector_t * knnk,const igraph_vector_t * weights)5907 int igraph_i_avg_nearest_neighbor_degree_weighted(const igraph_t *graph,
5908         igraph_vs_t vids,
5909         igraph_neimode_t mode,
5910         igraph_neimode_t neighbor_degree_mode,
5911         igraph_vector_t *knn,
5912         igraph_vector_t *knnk,
5913         const igraph_vector_t *weights) {
5914 
5915     long int no_of_nodes = igraph_vcount(graph);
5916     igraph_vector_t neis, edge_neis;
5917     long int i, j, no_vids;
5918     igraph_vit_t vit;
5919     igraph_vector_t my_knn_v, *my_knn = knn;
5920     igraph_vector_t strength, deg;
5921     igraph_integer_t maxdeg;
5922     igraph_vector_t deghist;
5923     igraph_real_t mynan = IGRAPH_NAN;
5924 
5925     if (igraph_vector_size(weights) != igraph_ecount(graph)) {
5926         IGRAPH_ERROR("Invalid weight vector size", IGRAPH_EINVAL);
5927     }
5928 
5929     IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
5930     IGRAPH_FINALLY(igraph_vit_destroy, &vit);
5931     no_vids = IGRAPH_VIT_SIZE(vit);
5932 
5933     if (!knn) {
5934         IGRAPH_VECTOR_INIT_FINALLY(&my_knn_v, no_vids);
5935         my_knn = &my_knn_v;
5936     } else {
5937         IGRAPH_CHECK(igraph_vector_resize(knn, no_vids));
5938     }
5939 
5940     // Get degree of neighbours
5941     IGRAPH_VECTOR_INIT_FINALLY(&deg, no_of_nodes);
5942     IGRAPH_CHECK(igraph_degree(graph, &deg, igraph_vss_all(),
5943                                neighbor_degree_mode, IGRAPH_LOOPS));
5944     IGRAPH_VECTOR_INIT_FINALLY(&strength, no_of_nodes);
5945 
5946     // Get strength of all nodes
5947     IGRAPH_CHECK(igraph_strength(graph, &strength, igraph_vss_all(),
5948                                  mode, IGRAPH_LOOPS, weights));
5949 
5950     // Get maximum degree for initialization
5951     IGRAPH_CHECK(igraph_maxdegree(graph, &maxdeg, igraph_vss_all(),
5952                                   mode, IGRAPH_LOOPS));
5953     IGRAPH_VECTOR_INIT_FINALLY(&neis, (long int)maxdeg);
5954     IGRAPH_VECTOR_INIT_FINALLY(&edge_neis, (long int)maxdeg);
5955     igraph_vector_resize(&neis, 0);
5956     igraph_vector_resize(&edge_neis, 0);
5957 
5958     if (knnk) {
5959         IGRAPH_CHECK(igraph_vector_resize(knnk, (long int)maxdeg));
5960         igraph_vector_null(knnk);
5961         IGRAPH_VECTOR_INIT_FINALLY(&deghist, (long int)maxdeg);
5962     }
5963 
5964     for (i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) {
5965         igraph_real_t sum = 0.0;
5966         long int v = IGRAPH_VIT_GET(vit);
5967         long int nv;
5968         igraph_real_t str = VECTOR(strength)[v];
5969         // Get neighbours and incident edges
5970         IGRAPH_CHECK(igraph_neighbors(graph, &neis, (igraph_integer_t) v, mode));
5971         IGRAPH_CHECK(igraph_incident(graph, &edge_neis, (igraph_integer_t) v, mode));
5972         nv = igraph_vector_size(&neis);
5973         for (j = 0; j < nv; j++) {
5974             long int nei = (long int) VECTOR(neis)[j];
5975             long int e = (long int) VECTOR(edge_neis)[j];
5976             double w = VECTOR(*weights)[e];
5977             sum += w * VECTOR(deg)[nei];
5978         }
5979         if (str != 0.0) {
5980             VECTOR(*my_knn)[i] = sum / str;
5981         } else {
5982             VECTOR(*my_knn)[i] = mynan;
5983         }
5984         if (knnk && nv > 0) {
5985             VECTOR(*knnk)[nv - 1] += VECTOR(*my_knn)[i];
5986             VECTOR(deghist)[nv - 1] += 1;
5987         }
5988     }
5989 
5990     igraph_vector_destroy(&edge_neis);
5991     igraph_vector_destroy(&neis);
5992     IGRAPH_FINALLY_CLEAN(2);
5993 
5994     if (knnk) {
5995         for (i = 0; i < maxdeg; i++) {
5996             igraph_real_t dh = VECTOR(deghist)[i];
5997             if (dh != 0) {
5998                 VECTOR(*knnk)[i] /= dh;
5999             } else {
6000                 VECTOR(*knnk)[i] = mynan;
6001             }
6002         }
6003 
6004         igraph_vector_destroy(&deghist);
6005         IGRAPH_FINALLY_CLEAN(1);
6006     }
6007 
6008     igraph_vector_destroy(&strength);
6009     igraph_vector_destroy(&deg);
6010     IGRAPH_FINALLY_CLEAN(2);
6011 
6012     if (!knn) {
6013         igraph_vector_destroy(&my_knn_v);
6014         IGRAPH_FINALLY_CLEAN(1);
6015     }
6016 
6017     igraph_vit_destroy(&vit);
6018     IGRAPH_FINALLY_CLEAN(1);
6019 
6020     return 0;
6021 }
6022 
6023 /**
6024  * \function igraph_avg_nearest_neighbor_degree
6025  * Average neighbor degree.
6026  *
6027  * Calculates the average degree of the neighbors for each vertex (\p knn), and
6028  * optionally, the same quantity as a function of the vertex degree (\p knnk).
6029  *
6030  * </para><para>
6031  * For isolated vertices \p knn is set to NaN.
6032  * The same is done in \p knnk for vertex degrees that
6033  * don't appear in the graph.
6034  *
6035  * </para><para>
6036  * The weighted version computes a weighted average of the neighbor degrees as
6037  *
6038  * <code>k_nn_u = 1/s_u sum_v w_uv k_v</code>,
6039  *
6040  * where <code>s_u = sum_v w_uv</code> is the sum of the incident edge weights
6041  * of vertex \c u, i.e. its strength.
6042  * The sum runs over the neighbors \c v of vertex \c u
6043  * as indicated by \p mode. <code>w_uv</code> denotes the weighted adjacency matrix
6044  * and <code>k_v</code> is the neighbors' degree, specified by \p neighbor_degree_mode.
6045  *
6046  * </para><para>
6047  * Reference:
6048  * A. Barrat, M. Barthélemy, R. Pastor-Satorras, and A. Vespignani,
6049  * The architecture of complex weighted networks,
6050  * Proc. Natl. Acad. Sci. USA 101, 3747 (2004).
6051  * https://dx.doi.org/10.1073/pnas.0400087101
6052  *
6053  * \param graph The input graph. It may be directed.
6054  * \param vids The vertices for which the calculation is performed.
6055  * \param mode The type of neighbors to consider in directed graphs.
6056  *   \c IGRAPH_OUT considers out-neighbors, \c IGRAPH_IN in-neighbors
6057  *   and \c IGRAPH_ALL ignores edge directions.
6058  * \param neighbor_degree_mode The type of degree to average in directed graphs.
6059  *   \c IGRAPH_OUT averages out-degrees, \c IGRAPH_IN averages in-degrees
6060  *   and \c IGRAPH_ALL ignores edge directions for the degree calculation.
6061  * \param vids The vertices for which the calculation is performed.
6062  * \param knn Pointer to an initialized vector, the result will be
6063  *   stored here. It will be resized as needed. Supply a \c NULL pointer
6064  *   here, if you only want to calculate \c knnk.
6065  * \param knnk Pointer to an initialized vector, the average
6066  *   neighbor degree as a function of the vertex degree is stored
6067  *   here. The first (zeroth) element is for degree one vertices,
6068  *   etc. Supply a \c NULL pointer here if you don't want to calculate
6069  *   this.
6070  * \param weights Optional edge weights. Supply a null pointer here
6071  *   for the non-weighted version.
6072  *
6073  * \return Error code.
6074  *
6075  * Time complexity: O(|V|+|E|), linear in the number of vertices and
6076  * edges.
6077  *
6078  * \example examples/simple/igraph_knn.c
6079  */
6080 
igraph_avg_nearest_neighbor_degree(const igraph_t * graph,igraph_vs_t vids,igraph_neimode_t mode,igraph_neimode_t neighbor_degree_mode,igraph_vector_t * knn,igraph_vector_t * knnk,const igraph_vector_t * weights)6081 int igraph_avg_nearest_neighbor_degree(const igraph_t *graph,
6082                                        igraph_vs_t vids,
6083                                        igraph_neimode_t mode,
6084                                        igraph_neimode_t neighbor_degree_mode,
6085                                        igraph_vector_t *knn,
6086                                        igraph_vector_t *knnk,
6087                                        const igraph_vector_t *weights) {
6088 
6089     long int no_of_nodes = igraph_vcount(graph);
6090     igraph_vector_t neis;
6091     long int i, j, no_vids;
6092     igraph_vit_t vit;
6093     igraph_vector_t my_knn_v, *my_knn = knn;
6094     igraph_vector_t deg;
6095     igraph_integer_t maxdeg;
6096     igraph_vector_t deghist;
6097     igraph_real_t mynan = IGRAPH_NAN;
6098     igraph_bool_t simple;
6099 
6100     IGRAPH_CHECK(igraph_is_simple(graph, &simple));
6101     if (!simple) {
6102         IGRAPH_ERROR("Average nearest neighbor degree works only with "
6103                      "simple graphs", IGRAPH_EINVAL);
6104     }
6105 
6106     if (weights) {
6107         return igraph_i_avg_nearest_neighbor_degree_weighted(graph, vids,
6108                 mode, neighbor_degree_mode, knn, knnk, weights);
6109     }
6110 
6111     IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
6112     IGRAPH_FINALLY(igraph_vit_destroy, &vit);
6113     no_vids = IGRAPH_VIT_SIZE(vit);
6114 
6115     if (!knn) {
6116         IGRAPH_VECTOR_INIT_FINALLY(&my_knn_v, no_vids);
6117         my_knn = &my_knn_v;
6118     } else {
6119         IGRAPH_CHECK(igraph_vector_resize(knn, no_vids));
6120     }
6121 
6122     IGRAPH_VECTOR_INIT_FINALLY(&deg, no_of_nodes);
6123     IGRAPH_CHECK(igraph_degree(graph, &deg, igraph_vss_all(),
6124                                neighbor_degree_mode, IGRAPH_LOOPS));
6125     igraph_maxdegree(graph, &maxdeg, igraph_vss_all(), mode, IGRAPH_LOOPS);
6126     IGRAPH_VECTOR_INIT_FINALLY(&neis, maxdeg);
6127     igraph_vector_resize(&neis, 0);
6128 
6129     if (knnk) {
6130         IGRAPH_CHECK(igraph_vector_resize(knnk, (long int)maxdeg));
6131         igraph_vector_null(knnk);
6132         IGRAPH_VECTOR_INIT_FINALLY(&deghist, (long int)maxdeg);
6133     }
6134 
6135     for (i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) {
6136         igraph_real_t sum = 0.0;
6137         long int v = IGRAPH_VIT_GET(vit);
6138         long int nv;
6139         IGRAPH_CHECK(igraph_neighbors(graph, &neis, (igraph_integer_t) v, mode));
6140         nv = igraph_vector_size(&neis);
6141         for (j = 0; j < nv; j++) {
6142             long int nei = (long int) VECTOR(neis)[j];
6143             sum += VECTOR(deg)[nei];
6144         }
6145         if (nv != 0) {
6146             VECTOR(*my_knn)[i] = sum / nv;
6147         } else {
6148             VECTOR(*my_knn)[i] = mynan;
6149         }
6150         if (knnk && nv > 0) {
6151             VECTOR(*knnk)[nv - 1] += VECTOR(*my_knn)[i];
6152             VECTOR(deghist)[nv - 1] += 1;
6153         }
6154     }
6155 
6156     if (knnk) {
6157         for (i = 0; i < maxdeg; i++) {
6158             long int dh = (long int) VECTOR(deghist)[i];
6159             if (dh != 0) {
6160                 VECTOR(*knnk)[i] /= dh;
6161             } else {
6162                 VECTOR(*knnk)[i] = mynan;
6163             }
6164         }
6165         igraph_vector_destroy(&deghist);
6166         IGRAPH_FINALLY_CLEAN(1);
6167     }
6168 
6169     igraph_vector_destroy(&neis);
6170     igraph_vector_destroy(&deg);
6171     igraph_vit_destroy(&vit);
6172     IGRAPH_FINALLY_CLEAN(3);
6173 
6174     if (!knn) {
6175         igraph_vector_destroy(&my_knn_v);
6176         IGRAPH_FINALLY_CLEAN(1);
6177     }
6178 
6179     return 0;
6180 }
6181 
6182 /**
6183  * \function igraph_strength
6184  * Strength of the vertices, weighted vertex degree in other words.
6185  *
6186  * In a weighted network the strength of a vertex is the sum of the
6187  * weights of all incident edges. In a non-weighted network this is
6188  * exactly the vertex degree.
6189  * \param graph The input graph.
6190  * \param res Pointer to an initialized vector, the result is stored
6191  *   here. It will be resized as needed.
6192  * \param vids The vertices for which the calculation is performed.
6193  * \param mode Gives whether to count only outgoing (\c IGRAPH_OUT),
6194  *   incoming (\c IGRAPH_IN) edges or both (\c IGRAPH_ALL).
6195  * \param loops A logical scalar, whether to count loop edges as well.
6196  * \param weights A vector giving the edge weights. If this is a NULL
6197  *   pointer, then \ref igraph_degree() is called to perform the
6198  *   calculation.
6199  * \return Error code.
6200  *
6201  * Time complexity: O(|V|+|E|), linear in the number vertices and
6202  * edges.
6203  *
6204  * \sa \ref igraph_degree() for the traditional, non-weighted version.
6205  */
6206 
igraph_strength(const igraph_t * graph,igraph_vector_t * res,const igraph_vs_t vids,igraph_neimode_t mode,igraph_bool_t loops,const igraph_vector_t * weights)6207 int igraph_strength(const igraph_t *graph, igraph_vector_t *res,
6208                     const igraph_vs_t vids, igraph_neimode_t mode,
6209                     igraph_bool_t loops, const igraph_vector_t *weights) {
6210 
6211     long int no_of_nodes = igraph_vcount(graph);
6212     igraph_vit_t vit;
6213     long int no_vids;
6214     igraph_vector_t neis;
6215     long int i;
6216 
6217     if (!weights) {
6218         return igraph_degree(graph, res, vids, mode, loops);
6219     }
6220 
6221     if (igraph_vector_size(weights) != igraph_ecount(graph)) {
6222         IGRAPH_ERROR("Invalid weight vector length", IGRAPH_EINVAL);
6223     }
6224 
6225     IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
6226     IGRAPH_FINALLY(igraph_vit_destroy, &vit);
6227     no_vids = IGRAPH_VIT_SIZE(vit);
6228 
6229     IGRAPH_VECTOR_INIT_FINALLY(&neis, 0);
6230     IGRAPH_CHECK(igraph_vector_reserve(&neis, no_of_nodes));
6231     IGRAPH_CHECK(igraph_vector_resize(res, no_vids));
6232     igraph_vector_null(res);
6233 
6234     if (loops) {
6235         for (i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) {
6236             long int vid = IGRAPH_VIT_GET(vit);
6237             long int j, n;
6238             IGRAPH_CHECK(igraph_incident(graph, &neis, (igraph_integer_t) vid, mode));
6239             n = igraph_vector_size(&neis);
6240             for (j = 0; j < n; j++) {
6241                 long int edge = (long int) VECTOR(neis)[j];
6242                 VECTOR(*res)[i] += VECTOR(*weights)[edge];
6243             }
6244         }
6245     } else {
6246         for (i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) {
6247             long int vid = IGRAPH_VIT_GET(vit);
6248             long int j, n;
6249             IGRAPH_CHECK(igraph_incident(graph, &neis, (igraph_integer_t) vid, mode));
6250             n = igraph_vector_size(&neis);
6251             for (j = 0; j < n; j++) {
6252                 long int edge = (long int) VECTOR(neis)[j];
6253                 long int from = IGRAPH_FROM(graph, edge);
6254                 long int to = IGRAPH_TO(graph, edge);
6255                 if (from != to) {
6256                     VECTOR(*res)[i] += VECTOR(*weights)[edge];
6257                 }
6258             }
6259         }
6260     }
6261 
6262     igraph_vit_destroy(&vit);
6263     igraph_vector_destroy(&neis);
6264     IGRAPH_FINALLY_CLEAN(2);
6265 
6266     return 0;
6267 }
6268 
6269 /**
6270  * \function igraph_diameter_dijkstra
6271  * Weighted diameter using Dijkstra's algorithm, non-negative weights only.
6272  *
6273  * The diameter of a graph is its longest geodesic. I.e. the
6274  * (weighted) shortest path is calculated for all pairs of vertices
6275  * and the longest one is the diameter.
6276  * \param graph The input graph, can be directed or undirected.
6277  * \param pres Pointer to a real number, if not \c NULL then it will contain
6278  *        the diameter (the actual distance).
6279  * \param pfrom Pointer to an integer, if not \c NULL it will be set to the
6280  *        source vertex of the diameter path.
6281  * \param pto Pointer to an integer, if not \c NULL it will be set to the
6282  *        target vertex of the diameter path.
6283  * \param path Pointer to an initialized vector. If not \c NULL the actual
6284  *        longest geodesic path will be stored here. The vector will be
6285  *        resized as needed.
6286  * \param directed Boolean, whether to consider directed
6287  *        paths. Ignored for undirected graphs.
6288  * \param unconn What to do if the graph is not connected. If
6289  *        \c TRUE the longest geodesic within a component
6290  *        will be returned, otherwise \c IGRAPH_INFINITY is
6291  *        returned.
6292  * \return Error code.
6293  *
6294  * Time complexity: O(|V||E|*log|E|), |V| is the number of vertices,
6295  * |E| is the number of edges.
6296  */
6297 
igraph_diameter_dijkstra(const igraph_t * graph,const igraph_vector_t * weights,igraph_real_t * pres,igraph_integer_t * pfrom,igraph_integer_t * pto,igraph_vector_t * path,igraph_bool_t directed,igraph_bool_t unconn)6298 int igraph_diameter_dijkstra(const igraph_t *graph,
6299                              const igraph_vector_t *weights,
6300                              igraph_real_t *pres,
6301                              igraph_integer_t *pfrom,
6302                              igraph_integer_t *pto,
6303                              igraph_vector_t *path,
6304                              igraph_bool_t directed,
6305                              igraph_bool_t unconn) {
6306 
6307     /* Implementation details. This is the basic Dijkstra algorithm,
6308        with a binary heap. The heap is indexed, i.e. it stores not only
6309        the distances, but also which vertex they belong to.
6310 
6311        From now on we use a 2-way heap, so the distances can be queried
6312        directly from the heap.
6313 
6314        Dirty tricks:
6315        - the opposite of the distance is stored in the heap, as it is a
6316          maximum heap and we need a minimum heap.
6317        - we don't use IGRAPH_INFINITY during the computation, as IGRAPH_FINITE()
6318          might involve a function call and we want to spare that. -1 will denote
6319          infinity instead.
6320     */
6321 
6322     long int no_of_nodes = igraph_vcount(graph);
6323     long int no_of_edges = igraph_ecount(graph);
6324 
6325     igraph_2wheap_t Q;
6326     igraph_inclist_t inclist;
6327     long int source, j;
6328     igraph_neimode_t dirmode = directed ? IGRAPH_OUT : IGRAPH_ALL;
6329 
6330     long int from = -1, to = -1;
6331     igraph_real_t res = 0;
6332     long int nodes_reached = 0;
6333 
6334     if (!weights) {
6335         igraph_integer_t diameter;
6336         IGRAPH_CHECK(igraph_diameter(graph, &diameter, pfrom, pto, path, directed, unconn));
6337         if (pres) {
6338             *pres = diameter;
6339         }
6340         return IGRAPH_SUCCESS;
6341     }
6342 
6343     if (weights && igraph_vector_size(weights) != no_of_edges) {
6344         IGRAPH_ERROR("Invalid weight vector length", IGRAPH_EINVAL);
6345     }
6346 
6347     if (igraph_vector_min(weights) < 0) {
6348         IGRAPH_ERROR("Weight vector must be non-negative", IGRAPH_EINVAL);
6349     }
6350 
6351     IGRAPH_CHECK(igraph_2wheap_init(&Q, no_of_nodes));
6352     IGRAPH_FINALLY(igraph_2wheap_destroy, &Q);
6353     IGRAPH_CHECK(igraph_inclist_init(graph, &inclist, dirmode));
6354     IGRAPH_FINALLY(igraph_inclist_destroy, &inclist);
6355 
6356     for (source = 0; source < no_of_nodes; source++) {
6357 
6358         IGRAPH_PROGRESS("Weighted diameter: ", source * 100.0 / no_of_nodes, NULL);
6359         IGRAPH_ALLOW_INTERRUPTION();
6360 
6361         igraph_2wheap_clear(&Q);
6362         igraph_2wheap_push_with_index(&Q, source, -1.0);
6363 
6364         nodes_reached = 0.0;
6365 
6366         while (!igraph_2wheap_empty(&Q)) {
6367             long int minnei = igraph_2wheap_max_index(&Q);
6368             igraph_real_t mindist = -igraph_2wheap_deactivate_max(&Q);
6369             igraph_vector_int_t *neis;
6370             long int nlen;
6371 
6372             if (mindist > res) {
6373                 res = mindist; from = source; to = minnei;
6374             }
6375             nodes_reached++;
6376 
6377             /* Now check all neighbors of 'minnei' for a shorter path */
6378             neis = igraph_inclist_get(&inclist, minnei);
6379             nlen = igraph_vector_int_size(neis);
6380             for (j = 0; j < nlen; j++) {
6381                 long int edge = (long int) VECTOR(*neis)[j];
6382                 long int tto = IGRAPH_OTHER(graph, edge, minnei);
6383                 igraph_real_t altdist = mindist + VECTOR(*weights)[edge];
6384                 igraph_bool_t active = igraph_2wheap_has_active(&Q, tto);
6385                 igraph_bool_t has = igraph_2wheap_has_elem(&Q, tto);
6386                 igraph_real_t curdist = active ? -igraph_2wheap_get(&Q, tto) : 0.0;
6387 
6388                 if (!has) {
6389                     /* First finite distance */
6390                     IGRAPH_CHECK(igraph_2wheap_push_with_index(&Q, tto, -altdist));
6391                 } else if (altdist < curdist) {
6392                     /* A shorter path */
6393                     IGRAPH_CHECK(igraph_2wheap_modify(&Q, tto, -altdist));
6394                 }
6395             }
6396 
6397         } /* !igraph_2wheap_empty(&Q) */
6398 
6399         /* not connected, return infinity */
6400         if (nodes_reached != no_of_nodes && !unconn) {
6401             res = IGRAPH_INFINITY;
6402             from = to = -1;
6403             break;
6404         }
6405 
6406     } /* source < no_of_nodes */
6407 
6408     /* Compensate for the +1 that we have added to distances */
6409     res -= 1;
6410 
6411     igraph_inclist_destroy(&inclist);
6412     igraph_2wheap_destroy(&Q);
6413     IGRAPH_FINALLY_CLEAN(2);
6414 
6415     IGRAPH_PROGRESS("Weighted diameter: ", 100.0, NULL);
6416 
6417     if (pres) {
6418         *pres = res;
6419     }
6420     if (pfrom) {
6421         *pfrom = (igraph_integer_t) from;
6422     }
6423     if (pto) {
6424         *pto = (igraph_integer_t) to;
6425     }
6426     if (path) {
6427         if (!igraph_finite(res)) {
6428             igraph_vector_clear(path);
6429         } else {
6430             igraph_vector_ptr_t tmpptr;
6431             igraph_vector_ptr_init(&tmpptr, 1);
6432             IGRAPH_FINALLY(igraph_vector_ptr_destroy, &tmpptr);
6433             VECTOR(tmpptr)[0] = path;
6434             IGRAPH_CHECK(igraph_get_shortest_paths_dijkstra(graph,
6435                          /*vertices=*/ &tmpptr, /*edges=*/ 0,
6436                          (igraph_integer_t) from,
6437                          igraph_vss_1((igraph_integer_t) to),
6438                          weights, dirmode, /*predecessors=*/ 0,
6439                          /*inbound_edges=*/ 0));
6440             igraph_vector_ptr_destroy(&tmpptr);
6441             IGRAPH_FINALLY_CLEAN(1);
6442         }
6443     }
6444 
6445     return 0;
6446 }
6447 
6448 /**
6449  * \function igraph_sort_vertex_ids_by_degree
6450  * \brief Calculate a list of vertex ids sorted by degree of the corresponding vertex.
6451  *
6452  * The list of vertex ids is returned in a vector that is sorted
6453  * in ascending or descending order of vertex degree.
6454  *
6455  * \param graph The input graph.
6456  * \param outvids Pointer to an initialized vector that will be
6457  *        resized and will contain the ordered vertex ids.
6458  * \param vids Input vertex selector of vertex ids to include in
6459  *        calculation.
6460  * \param mode Defines the type of the degree.
6461  *        \c IGRAPH_OUT, out-degree,
6462  *        \c IGRAPH_IN, in-degree,
6463  *        \c IGRAPH_ALL, total degree (sum of the
6464  *        in- and out-degree).
6465  *        This parameter is ignored for undirected graphs.
6466  * \param loops Boolean, gives whether the self-loops should be
6467  *        counted.
6468  * \param order Specifies whether the ordering should be ascending
6469  *        (\c IGRAPH_ASCENDING) or descending (\c IGRAPH_DESCENDING).
6470  * \param only_indices If true, then return a sorted list of indices
6471  *        into a vector corresponding to \c vids, rather than a list
6472  *        of vertex ids. This parameter is ignored if \c vids is set
6473  *        to all vertices via igraph_vs_all() or igraph_vss_all(),
6474  *        because in this case the indices and vertex ids are the
6475  *        same.
6476  * \return Error code:
6477  *         \c IGRAPH_EINVVID: invalid vertex id.
6478  *         \c IGRAPH_EINVMODE: invalid mode argument.
6479  *
6480  */
6481 
igraph_sort_vertex_ids_by_degree(const igraph_t * graph,igraph_vector_t * outvids,igraph_vs_t vids,igraph_neimode_t mode,igraph_bool_t loops,igraph_order_t order,igraph_bool_t only_indices)6482 int igraph_sort_vertex_ids_by_degree(const igraph_t *graph,
6483                                      igraph_vector_t *outvids,
6484                                      igraph_vs_t vids,
6485                                      igraph_neimode_t mode,
6486                                      igraph_bool_t loops,
6487                                      igraph_order_t order,
6488                                      igraph_bool_t only_indices) {
6489     long int i;
6490     igraph_vector_t degrees, vs_vec;
6491     IGRAPH_VECTOR_INIT_FINALLY(&degrees, 0);
6492     IGRAPH_CHECK(igraph_degree(graph, &degrees, vids, mode, loops));
6493     IGRAPH_CHECK((int) igraph_vector_qsort_ind(&degrees, outvids,
6494                  order == IGRAPH_DESCENDING));
6495     if (only_indices || igraph_vs_is_all(&vids) ) {
6496         igraph_vector_destroy(&degrees);
6497         IGRAPH_FINALLY_CLEAN(1);
6498     } else {
6499         IGRAPH_VECTOR_INIT_FINALLY(&vs_vec, 0);
6500         IGRAPH_CHECK(igraph_vs_as_vector(graph, vids, &vs_vec));
6501         for (i = 0; i < igraph_vector_size(outvids); i++) {
6502             VECTOR(*outvids)[i] = VECTOR(vs_vec)[(long int)VECTOR(*outvids)[i]];
6503         }
6504         igraph_vector_destroy(&vs_vec);
6505         igraph_vector_destroy(&degrees);
6506         IGRAPH_FINALLY_CLEAN(2);
6507     }
6508     return 0;
6509 }
6510 
6511 /**
6512  * \function igraph_contract_vertices
6513  * Replace multiple vertices with a single one.
6514  *
6515  * This function creates a new graph, by merging several
6516  * vertices into one. The vertices in the new graph correspond
6517  * to sets of vertices in the input graph.
6518  * \param graph The input graph, it can be directed or
6519  *        undirected.
6520  * \param mapping A vector giving the mapping. For each
6521  *        vertex in the original graph, it should contain
6522  *        its id in the new graph.
6523  * \param vertex_comb What to do with the vertex attributes.
6524  *        See the igraph manual section about attributes for
6525  *        details.
6526  * \return Error code.
6527  *
6528  * Time complexity: O(|V|+|E|), linear in the number
6529  * or vertices plus edges.
6530  */
6531 
igraph_contract_vertices(igraph_t * graph,const igraph_vector_t * mapping,const igraph_attribute_combination_t * vertex_comb)6532 int igraph_contract_vertices(igraph_t *graph,
6533                              const igraph_vector_t *mapping,
6534                              const igraph_attribute_combination_t *vertex_comb) {
6535     igraph_vector_t edges;
6536     long int no_of_nodes = igraph_vcount(graph);
6537     long int no_of_edges = igraph_ecount(graph);
6538     igraph_bool_t vattr = vertex_comb && igraph_has_attribute_table();
6539     igraph_t res;
6540     long int e, last = -1;
6541     long int no_new_vertices;
6542 
6543     if (igraph_vector_size(mapping) != no_of_nodes) {
6544         IGRAPH_ERROR("Invalid mapping vector length",
6545                      IGRAPH_EINVAL);
6546     }
6547 
6548     IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
6549     IGRAPH_CHECK(igraph_vector_reserve(&edges, no_of_edges * 2));
6550 
6551     if (no_of_nodes > 0) {
6552         last = (long int) igraph_vector_max(mapping);
6553     }
6554 
6555     for (e = 0; e < no_of_edges; e++) {
6556         long int from = IGRAPH_FROM(graph, e);
6557         long int to = IGRAPH_TO(graph, e);
6558 
6559         long int nfrom = (long int) VECTOR(*mapping)[from];
6560         long int nto = (long int) VECTOR(*mapping)[to];
6561 
6562         igraph_vector_push_back(&edges, nfrom);
6563         igraph_vector_push_back(&edges, nto);
6564 
6565         if (nfrom > last) {
6566             last = nfrom;
6567         }
6568         if (nto   > last) {
6569             last = nto;
6570         }
6571     }
6572 
6573     no_new_vertices = last + 1;
6574 
6575     IGRAPH_CHECK(igraph_create(&res, &edges, (igraph_integer_t) no_new_vertices,
6576                                igraph_is_directed(graph)));
6577 
6578     igraph_vector_destroy(&edges);
6579     IGRAPH_FINALLY_CLEAN(1);
6580 
6581     IGRAPH_FINALLY(igraph_destroy, &res);
6582 
6583     IGRAPH_I_ATTRIBUTE_DESTROY(&res);
6584     IGRAPH_I_ATTRIBUTE_COPY(&res, graph, /*graph=*/ 1,
6585                             /*vertex=*/ 0, /*edge=*/ 1);
6586 
6587     if (vattr) {
6588         long int i;
6589         igraph_vector_ptr_t merges;
6590         igraph_vector_t sizes;
6591         igraph_vector_t *vecs;
6592 
6593         vecs = igraph_Calloc(no_new_vertices, igraph_vector_t);
6594         if (!vecs) {
6595             IGRAPH_ERROR("Cannot combine attributes while contracting"
6596                          " vertices", IGRAPH_ENOMEM);
6597         }
6598         IGRAPH_FINALLY(igraph_free, vecs);
6599         IGRAPH_CHECK(igraph_vector_ptr_init(&merges, no_new_vertices));
6600         IGRAPH_FINALLY(igraph_i_simplify_free, &merges);
6601         IGRAPH_VECTOR_INIT_FINALLY(&sizes, no_new_vertices);
6602 
6603         for (i = 0; i < no_of_nodes; i++) {
6604             long int to = (long int) VECTOR(*mapping)[i];
6605             VECTOR(sizes)[to] += 1;
6606         }
6607         for (i = 0; i < no_new_vertices; i++) {
6608             igraph_vector_t *v = &vecs[i];
6609             IGRAPH_CHECK(igraph_vector_init(v, (long int) VECTOR(sizes)[i]));
6610             igraph_vector_clear(v);
6611             VECTOR(merges)[i] = v;
6612         }
6613         for (i = 0; i < no_of_nodes; i++) {
6614             long int to = (long int) VECTOR(*mapping)[i];
6615             igraph_vector_t *v = &vecs[to];
6616             igraph_vector_push_back(v, i);
6617         }
6618 
6619         IGRAPH_CHECK(igraph_i_attribute_combine_vertices(graph, &res,
6620                      &merges,
6621                      vertex_comb));
6622 
6623         igraph_vector_destroy(&sizes);
6624         igraph_i_simplify_free(&merges);
6625         igraph_free(vecs);
6626         IGRAPH_FINALLY_CLEAN(3);
6627     }
6628 
6629     IGRAPH_FINALLY_CLEAN(1);
6630     igraph_destroy(graph);
6631     *graph = res;
6632 
6633     return 0;
6634 }
6635 
6636 /* Create the transitive closure of a tree graph.
6637    This is fairly simple, we just collect all ancestors of a vertex
6638    using a depth-first search.
6639  */
6640 
igraph_transitive_closure_dag(const igraph_t * graph,igraph_t * closure)6641 int igraph_transitive_closure_dag(const igraph_t *graph,
6642                                   igraph_t *closure) {
6643 
6644     long int no_of_nodes = igraph_vcount(graph);
6645     igraph_vector_t deg;
6646     igraph_vector_t new_edges;
6647     igraph_vector_t ancestors;
6648     long int root;
6649     igraph_vector_t neighbors;
6650     igraph_stack_t path;
6651     igraph_vector_bool_t done;
6652 
6653     if (!igraph_is_directed(graph)) {
6654         IGRAPH_ERROR("Tree transitive closure of a directed graph",
6655                      IGRAPH_EINVAL);
6656     }
6657 
6658     IGRAPH_VECTOR_INIT_FINALLY(&new_edges, 0);
6659     IGRAPH_VECTOR_INIT_FINALLY(&deg, no_of_nodes);
6660     IGRAPH_VECTOR_INIT_FINALLY(&ancestors, 0);
6661     IGRAPH_VECTOR_INIT_FINALLY(&neighbors, 0);
6662     IGRAPH_CHECK(igraph_stack_init(&path, 0));
6663     IGRAPH_FINALLY(igraph_stack_destroy, &path);
6664     IGRAPH_CHECK(igraph_vector_bool_init(&done, no_of_nodes));
6665     IGRAPH_FINALLY(igraph_vector_bool_destroy, &done);
6666 
6667     IGRAPH_CHECK(igraph_degree(graph, &deg, igraph_vss_all(),
6668                                IGRAPH_OUT, IGRAPH_LOOPS));
6669 
6670 #define STAR (-1)
6671 
6672     for (root = 0; root < no_of_nodes; root++) {
6673         if (VECTOR(deg)[root] != 0) {
6674             continue;
6675         }
6676         IGRAPH_CHECK(igraph_stack_push(&path, root));
6677 
6678         while (!igraph_stack_empty(&path)) {
6679             long int node = (long int) igraph_stack_top(&path);
6680             if (node == STAR) {
6681                 /* Leaving a node */
6682                 long int j, n;
6683                 igraph_stack_pop(&path);
6684                 node = (long int) igraph_stack_pop(&path);
6685                 if (!VECTOR(done)[node]) {
6686                     igraph_vector_pop_back(&ancestors);
6687                     VECTOR(done)[node] = 1;
6688                 }
6689                 n = igraph_vector_size(&ancestors);
6690                 for (j = 0; j < n; j++) {
6691                     IGRAPH_CHECK(igraph_vector_push_back(&new_edges, node));
6692                     IGRAPH_CHECK(igraph_vector_push_back(&new_edges,
6693                                                          VECTOR(ancestors)[j]));
6694                 }
6695             } else {
6696                 /* Getting into a node */
6697                 long int n, j;
6698                 if (!VECTOR(done)[node]) {
6699                     IGRAPH_CHECK(igraph_vector_push_back(&ancestors, node));
6700                 }
6701                 IGRAPH_CHECK(igraph_neighbors(graph, &neighbors,
6702                                               (igraph_integer_t) node, IGRAPH_IN));
6703                 n = igraph_vector_size(&neighbors);
6704                 IGRAPH_CHECK(igraph_stack_push(&path, STAR));
6705                 for (j = 0; j < n; j++) {
6706                     long int nei = (long int) VECTOR(neighbors)[j];
6707                     IGRAPH_CHECK(igraph_stack_push(&path, nei));
6708                 }
6709             }
6710         }
6711     }
6712 
6713 #undef STAR
6714 
6715     igraph_vector_bool_destroy(&done);
6716     igraph_stack_destroy(&path);
6717     igraph_vector_destroy(&neighbors);
6718     igraph_vector_destroy(&ancestors);
6719     igraph_vector_destroy(&deg);
6720     IGRAPH_FINALLY_CLEAN(5);
6721 
6722     IGRAPH_CHECK(igraph_create(closure, &new_edges, (igraph_integer_t)no_of_nodes,
6723                                IGRAPH_DIRECTED));
6724 
6725     igraph_vector_destroy(&new_edges);
6726     IGRAPH_FINALLY_CLEAN(1);
6727 
6728     return 0;
6729 }
6730 
6731 /**
6732  * \function igraph_diversity
6733  * Structural diversity index of the vertices
6734  *
6735  * This measure was defined in Nathan Eagle, Michael Macy and Rob
6736  * Claxton: Network Diversity and Economic Development, Science 328,
6737  * 1029--1031, 2010.
6738  *
6739  * </para><para>
6740  * It is simply the (normalized) Shannon entropy of the
6741  * incident edges' weights. D(i)=H(i)/log(k[i]), and
6742  * H(i) = -sum(p[i,j] log(p[i,j]), j=1..k[i]),
6743  * where p[i,j]=w[i,j]/sum(w[i,l], l=1..k[i]),  k[i] is the (total)
6744  * degree of vertex i, and w[i,j] is the weight of the edge(s) between
6745  * vertex i and j.
6746  * \param graph The input graph, edge directions are ignored.
6747  * \param weights The edge weights, in the order of the edge ids, must
6748  *    have appropriate length.
6749  * \param res An initialized vector, the results are stored here.
6750  * \param vids Vector with the vertex ids for which to calculate the
6751  *    measure.
6752  * \return Error code.
6753  *
6754  * Time complexity: O(|V|+|E|), linear.
6755  *
6756  */
6757 
igraph_diversity(igraph_t * graph,const igraph_vector_t * weights,igraph_vector_t * res,const igraph_vs_t vids)6758 int igraph_diversity(igraph_t *graph, const igraph_vector_t *weights,
6759                      igraph_vector_t *res, const igraph_vs_t vids) {
6760 
6761     int no_of_nodes = igraph_vcount(graph);
6762     int no_of_edges = igraph_ecount(graph);
6763     igraph_vector_t incident;
6764     igraph_vit_t vit;
6765     igraph_real_t s, ent, w;
6766     int i, j, k;
6767 
6768     if (!weights) {
6769         IGRAPH_ERROR("Edge weights must be given", IGRAPH_EINVAL);
6770     }
6771 
6772     if (igraph_vector_size(weights) != no_of_edges) {
6773         IGRAPH_ERROR("Invalid edge weight vector length", IGRAPH_EINVAL);
6774     }
6775 
6776     IGRAPH_VECTOR_INIT_FINALLY(&incident, 10);
6777 
6778     if (igraph_vs_is_all(&vids)) {
6779         IGRAPH_CHECK(igraph_vector_resize(res, no_of_nodes));
6780         for (i = 0; i < no_of_nodes; i++) {
6781             s = ent = 0.0;
6782             IGRAPH_CHECK(igraph_incident(graph, &incident, i, /*mode=*/ IGRAPH_ALL));
6783             for (j = 0, k = (int) igraph_vector_size(&incident); j < k; j++) {
6784                 w = VECTOR(*weights)[(long int)VECTOR(incident)[j]];
6785                 s += w;
6786                 ent += (w * log(w));
6787             }
6788             VECTOR(*res)[i] = (log(s) - ent / s) / log(k);
6789         }
6790     } else {
6791         IGRAPH_CHECK(igraph_vector_resize(res, 0));
6792         IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
6793         IGRAPH_FINALLY(igraph_vit_destroy, &vit);
6794 
6795         for (IGRAPH_VIT_RESET(vit), i = 0;
6796              !IGRAPH_VIT_END(vit);
6797              IGRAPH_VIT_NEXT(vit), i++) {
6798             long int v = IGRAPH_VIT_GET(vit);
6799             s = ent = 0.0;
6800             IGRAPH_CHECK(igraph_incident(graph, &incident, (igraph_integer_t) v,
6801                                          /*mode=*/ IGRAPH_ALL));
6802             for (j = 0, k = (int) igraph_vector_size(&incident); j < k; j++) {
6803                 w = VECTOR(*weights)[(long int)VECTOR(incident)[j]];
6804                 s += w;
6805                 ent += (w * log(w));
6806             }
6807             IGRAPH_CHECK(igraph_vector_push_back(res, (log(s) - ent / s) / log(k)));
6808         }
6809 
6810         igraph_vit_destroy(&vit);
6811         IGRAPH_FINALLY_CLEAN(1);
6812     }
6813 
6814     igraph_vector_destroy(&incident);
6815     IGRAPH_FINALLY_CLEAN(1);
6816 
6817     return 0;
6818 }
6819 
6820 #define SUCCEED {   \
6821         if (res) {        \
6822             *res = 1;       \
6823         }                 \
6824         return IGRAPH_SUCCESS; \
6825     }
6826 
6827 #define FAIL {   \
6828         if (res) {     \
6829             *res = 0;    \
6830         }              \
6831         return IGRAPH_SUCCESS; \
6832     }
6833 
6834 /**
6835  * \function igraph_is_degree_sequence
6836  * Determines whether a degree sequence is valid.
6837  *
6838  * A sequence of n integers is a valid degree sequence if there exists some
6839  * graph where the degree of the i-th vertex is equal to the i-th element of the
6840  * sequence. Note that the graph may contain multiple or loop edges; if you are
6841  * interested in whether the degrees of some \em simple graph may realize the
6842  * given sequence, use \ref igraph_is_graphical_degree_sequence.
6843  *
6844  * </para><para>
6845  * In particular, the function checks whether all the degrees are non-negative.
6846  * For undirected graphs, it also checks whether the sum of degrees is even.
6847  * For directed graphs, the function checks whether the lengths of the two
6848  * degree vectors are equal and whether their sums are also equal. These are
6849  * known sufficient and necessary conditions for a degree sequence to be
6850  * valid.
6851  *
6852  * \param out_degrees  an integer vector specifying the degree sequence for
6853  *     undirected graphs or the out-degree sequence for directed graphs.
6854  * \param in_degrees   an integer vector specifying the in-degrees of the
6855  *     vertices for directed graphs. For undirected graphs, this must be null.
6856  * \param res  pointer to a boolean variable, the result will be stored here
6857  * \return Error code.
6858  *
6859  * Time complexity: O(n), where n is the length of the degree sequence.
6860  */
igraph_is_degree_sequence(const igraph_vector_t * out_degrees,const igraph_vector_t * in_degrees,igraph_bool_t * res)6861 int igraph_is_degree_sequence(const igraph_vector_t *out_degrees,
6862                               const igraph_vector_t *in_degrees, igraph_bool_t *res) {
6863     /* degrees must be non-negative */
6864     if (igraph_vector_any_smaller(out_degrees, 0)) {
6865         FAIL;
6866     }
6867     if (in_degrees && igraph_vector_any_smaller(in_degrees, 0)) {
6868         FAIL;
6869     }
6870 
6871     if (in_degrees == 0) {
6872         /* sum of degrees must be even */
6873         if (((long int)igraph_vector_sum(out_degrees) % 2) != 0) {
6874             FAIL;
6875         }
6876     } else {
6877         /* length of the two degree vectors must be equal */
6878         if (igraph_vector_size(out_degrees) != igraph_vector_size(in_degrees)) {
6879             FAIL;
6880         }
6881         /* sum of in-degrees must be equal to sum of out-degrees */
6882         if (igraph_vector_sum(out_degrees) != igraph_vector_sum(in_degrees)) {
6883             FAIL;
6884         }
6885     }
6886 
6887     SUCCEED;
6888     return 0;
6889 }
6890 
6891 int igraph_i_is_graphical_degree_sequence_undirected(
6892     const igraph_vector_t *degrees, igraph_bool_t *res);
6893 int igraph_i_is_graphical_degree_sequence_directed(
6894     const igraph_vector_t *out_degrees, const igraph_vector_t *in_degrees,
6895     igraph_bool_t *res);
6896 
6897 /**
6898  * \function igraph_is_graphical_degree_sequence
6899  * Determines whether a sequence of integers can be a degree sequence of some
6900  * simple graph.
6901  *
6902  * </para><para>
6903  * References:
6904  *
6905  * </para><para>
6906  * Hakimi SL: On the realizability of a set of integers as degrees of the
6907  * vertices of a simple graph. J SIAM Appl Math 10:496-506, 1962.
6908  *
6909  * </para><para>
6910  * PL Erdos, I Miklos and Z Toroczkai: A simple Havel-Hakimi type algorithm
6911  * to realize graphical degree sequences of directed graphs. The Electronic
6912  * Journal of Combinatorics 17(1):R66, 2010.
6913  *
6914  * </para><para>
6915  * Z Kiraly: Recognizing graphic degree sequences and generating all
6916  * realizations. TR-2011-11, Egervary Research Group, H-1117, Budapest,
6917  * Hungary. ISSN 1587-4451, 2012.
6918  *
6919  * \param out_degrees  an integer vector specifying the degree sequence for
6920  *     undirected graphs or the out-degree sequence for directed graphs.
6921  * \param in_degrees   an integer vector specifying the in-degrees of the
6922  *     vertices for directed graphs. For undirected graphs, this must be null.
6923  * \param res  pointer to a boolean variable, the result will be stored here
6924  * \return Error code.
6925  *
6926  * Time complexity: O(n log n) for undirected graphs, O(n^2) for directed
6927  *                  graphs, where n is the length of the degree sequence.
6928  */
igraph_is_graphical_degree_sequence(const igraph_vector_t * out_degrees,const igraph_vector_t * in_degrees,igraph_bool_t * res)6929 int igraph_is_graphical_degree_sequence(const igraph_vector_t *out_degrees,
6930                                         const igraph_vector_t *in_degrees, igraph_bool_t *res) {
6931     IGRAPH_CHECK(igraph_is_degree_sequence(out_degrees, in_degrees, res));
6932     if (!*res) {
6933         FAIL;
6934     }
6935 
6936     if (igraph_vector_size(out_degrees) == 0) {
6937         SUCCEED;
6938     }
6939 
6940     if (in_degrees == 0) {
6941         return igraph_i_is_graphical_degree_sequence_undirected(out_degrees, res);
6942     } else {
6943         return igraph_i_is_graphical_degree_sequence_directed(out_degrees, in_degrees, res);
6944     }
6945 }
6946 
igraph_i_is_graphical_degree_sequence_undirected(const igraph_vector_t * degrees,igraph_bool_t * res)6947 int igraph_i_is_graphical_degree_sequence_undirected(const igraph_vector_t *degrees, igraph_bool_t *res) {
6948     igraph_vector_t work;
6949     long int w, b, s, c, n, k;
6950 
6951     n = igraph_vector_size(degrees);
6952 
6953     /* zero-length sequences are considered graphical */
6954     if (n == 0) {
6955         *res = 1;
6956         return IGRAPH_SUCCESS;
6957     }
6958 
6959     IGRAPH_CHECK(igraph_vector_copy(&work, degrees));
6960     IGRAPH_FINALLY(igraph_vector_destroy, &work);
6961 
6962     igraph_vector_reverse_sort(&work);
6963 
6964     /* This algorithm is outlined in TR-2011-11 of the Egervary Research Group,
6965      * ISSN 1587-4451. The main loop of the algorithm is O(n) but it is dominated
6966      * by an O(n log n) quicksort; this could in theory be brought down to
6967      * O(n) with binsort but it's probably not worth the fuss.
6968      *
6969      * Variables names are mostly according to the technical report, apart from
6970      * the degrees themselves. w and k are zero-based here; in the technical
6971      * report they are 1-based */
6972     *res = 1;
6973     w = n - 1; b = 0; s = 0; c = 0;
6974     for (k = 0; k < n; k++) {
6975         b += VECTOR(work)[k];
6976         c += w;
6977         while (w > k && VECTOR(work)[w] <= k + 1) {
6978             s += VECTOR(work)[w];
6979             c -= (k + 1);
6980             w--;
6981         }
6982         if (b > c + s) {
6983             *res = 0;
6984             break;
6985         }
6986         if (w == k) {
6987             break;
6988         }
6989     }
6990 
6991     igraph_vector_destroy(&work);
6992     IGRAPH_FINALLY_CLEAN(1);
6993 
6994     return IGRAPH_SUCCESS;
6995 }
6996 
6997 typedef struct {
6998     const igraph_vector_t* first;
6999     const igraph_vector_t* second;
7000 } igraph_i_qsort_dual_vector_cmp_data_t;
7001 
igraph_i_qsort_dual_vector_cmp_desc(void * data,const void * p1,const void * p2)7002 int igraph_i_qsort_dual_vector_cmp_desc(void* data, const void *p1, const void *p2) {
7003     igraph_i_qsort_dual_vector_cmp_data_t* sort_data =
7004         (igraph_i_qsort_dual_vector_cmp_data_t*)data;
7005     long int index1 = *((long int*)p1);
7006     long int index2 = *((long int*)p2);
7007     if (VECTOR(*sort_data->first)[index1] < VECTOR(*sort_data->first)[index2]) {
7008         return 1;
7009     }
7010     if (VECTOR(*sort_data->first)[index1] > VECTOR(*sort_data->first)[index2]) {
7011         return -1;
7012     }
7013     if (VECTOR(*sort_data->second)[index1] < VECTOR(*sort_data->second)[index2]) {
7014         return 1;
7015     }
7016     if (VECTOR(*sort_data->second)[index1] > VECTOR(*sort_data->second)[index2]) {
7017         return -1;
7018     }
7019     return 0;
7020 }
7021 
igraph_i_is_graphical_degree_sequence_directed(const igraph_vector_t * out_degrees,const igraph_vector_t * in_degrees,igraph_bool_t * res)7022 int igraph_i_is_graphical_degree_sequence_directed(
7023     const igraph_vector_t *out_degrees, const igraph_vector_t *in_degrees,
7024     igraph_bool_t *res) {
7025     igraph_vector_long_t index_array;
7026     long int i, j, vcount, lhs, rhs;
7027     igraph_i_qsort_dual_vector_cmp_data_t sort_data;
7028 
7029     /* Create an index vector that sorts the vertices by decreasing in-degree */
7030     vcount = igraph_vector_size(out_degrees);
7031     IGRAPH_CHECK(igraph_vector_long_init_seq(&index_array, 0, vcount - 1));
7032     IGRAPH_FINALLY(igraph_vector_long_destroy, &index_array);
7033 
7034     /* Set up the auxiliary struct for sorting */
7035     sort_data.first  = in_degrees;
7036     sort_data.second = out_degrees;
7037 
7038     /* Sort the index vector */
7039     igraph_qsort_r(VECTOR(index_array), vcount, sizeof(long int), &sort_data,
7040                    igraph_i_qsort_dual_vector_cmp_desc);
7041 
7042     /* Be optimistic, then check whether the Fulkerson–Chen–Anstee condition
7043      * holds for every k. In particular, for every k in [0; n), it must be true
7044      * that:
7045      *
7046      * \sum_{i=0}^k indegree[i] <=
7047      *     \sum_{i=0}^k min(outdegree[i], k) +
7048      *     \sum_{i=k+1}^{n-1} min(outdegree[i], k + 1)
7049      */
7050 
7051 #define INDEGREE(x) (VECTOR(*in_degrees)[VECTOR(index_array)[x]])
7052 #define OUTDEGREE(x) (VECTOR(*out_degrees)[VECTOR(index_array)[x]])
7053 
7054     *res = 1;
7055     lhs = 0;
7056     for (i = 0; i < vcount; i++) {
7057         lhs += INDEGREE(i);
7058 
7059         /* It is enough to check for indexes where the in-degree is about to
7060          * decrease in the next step; see "Stronger condition" in the Wikipedia
7061          * entry for the Fulkerson-Chen-Anstee condition */
7062         if (i != vcount - 1 && INDEGREE(i) == INDEGREE(i + 1)) {
7063             continue;
7064         }
7065 
7066         rhs = 0;
7067         for (j = 0; j <= i; j++) {
7068             rhs += OUTDEGREE(j) < i ? OUTDEGREE(j) : i;
7069         }
7070         for (j = i + 1; j < vcount; j++) {
7071             rhs += OUTDEGREE(j) < (i + 1) ? OUTDEGREE(j) : (i + 1);
7072         }
7073 
7074         if (lhs > rhs) {
7075             *res = 0;
7076             break;
7077         }
7078     }
7079 
7080 #undef INDEGREE
7081 #undef OUTDEGREE
7082 
7083     igraph_vector_long_destroy(&index_array);
7084     IGRAPH_FINALLY_CLEAN(1);
7085 
7086     return IGRAPH_SUCCESS;
7087 }
7088 
7089 #undef SUCCEED
7090 #undef FAIL
7091 
7092 
7093 /* igraph_is_tree -- check if a graph is a tree */
7094 
7095 /* count the number of vertices reachable from the root */
igraph_i_is_tree_visitor(igraph_integer_t root,const igraph_adjlist_t * al,igraph_integer_t * visited_count)7096 static int igraph_i_is_tree_visitor(igraph_integer_t root, const igraph_adjlist_t *al, igraph_integer_t *visited_count) {
7097     igraph_stack_int_t stack;
7098     igraph_vector_bool_t visited;
7099     long i;
7100 
7101     IGRAPH_CHECK(igraph_vector_bool_init(&visited, igraph_adjlist_size(al)));
7102     IGRAPH_FINALLY(igraph_vector_bool_destroy, &visited);
7103 
7104     IGRAPH_CHECK(igraph_stack_int_init(&stack, 0));
7105     IGRAPH_FINALLY(igraph_stack_int_destroy, &stack);
7106 
7107     *visited_count = 0;
7108 
7109     /* push the root into the stack */
7110     IGRAPH_CHECK(igraph_stack_int_push(&stack, root));
7111 
7112     while (! igraph_stack_int_empty(&stack)) {
7113         igraph_integer_t u;
7114         igraph_vector_int_t *neighbors;
7115         long ncount;
7116 
7117         /* take a vertex from the stack, mark it as visited */
7118         u = igraph_stack_int_pop(&stack);
7119         if (IGRAPH_LIKELY(! VECTOR(visited)[u])) {
7120             VECTOR(visited)[u] = 1;
7121             *visited_count += 1;
7122         }
7123 
7124         /* register all its yet-unvisited neighbours for future processing */
7125         neighbors = igraph_adjlist_get(al, u);
7126         ncount = igraph_vector_int_size(neighbors);
7127         for (i = 0; i < ncount; ++i) {
7128             igraph_integer_t v = VECTOR(*neighbors)[i];
7129             if (! VECTOR(visited)[v]) {
7130                 IGRAPH_CHECK(igraph_stack_int_push(&stack, v));
7131             }
7132         }
7133     }
7134 
7135     igraph_stack_int_destroy(&stack);
7136     igraph_vector_bool_destroy(&visited);
7137     IGRAPH_FINALLY_CLEAN(2);
7138 
7139     return IGRAPH_SUCCESS;
7140 }
7141 
7142 
7143 /**
7144  * \ingroup structural
7145  * \function igraph_is_tree
7146  * \brief Decides whether the graph is a tree.
7147  *
7148  * An undirected graph is a tree if it is connected and has no cycles.
7149  * </para><para>
7150  *
7151  * In the directed case, a possible additional requirement is that all
7152  * edges are oriented away from a root (out-tree or arborescence) or all edges
7153  * are oriented towards a root (in-tree or anti-arborescence).
7154  * This test can be controlled using the \p mode parameter.
7155  * </para><para>
7156  *
7157  * By convention, the null graph (i.e. the graph with no vertices) is considered not to be a tree.
7158  *
7159  * \param graph The graph object to analyze.
7160  * \param res Pointer to a logical variable, the result will be stored
7161  *        here.
7162  * \param root If not \c NULL, the root node will be stored here. When \p mode
7163  *        is \c IGRAPH_ALL or the graph is undirected, any vertex can be the root
7164  *        and \p root is set to 0 (the first vertex). When \p mode is \c IGRAPH_OUT
7165  *        or \c IGRAPH_IN, the root is set to the vertex with zero in- or out-degree,
7166  *        respectively.
7167  * \param mode For a directed graph this specifies whether to test for an
7168  *        out-tree, an in-tree or ignore edge directions. The respective
7169  *        possible values are:
7170  *        \c IGRAPH_OUT, \c IGRAPH_IN, \c IGRAPH_ALL. This argument is
7171  *        ignored for undirected graphs.
7172  * \return Error code:
7173  *        \c IGRAPH_EINVAL: invalid mode argument.
7174  *
7175  * Time complexity: At most O(|V|+|E|), the
7176  * number of vertices plus the number of edges in the graph.
7177  *
7178  * \sa igraph_is_weakly_connected()
7179  *
7180  * \example examples/simple/igraph_tree.c
7181  */
7182 
igraph_is_tree(const igraph_t * graph,igraph_bool_t * res,igraph_integer_t * root,igraph_neimode_t mode)7183 int igraph_is_tree(const igraph_t *graph, igraph_bool_t *res, igraph_integer_t *root, igraph_neimode_t mode) {
7184     igraph_adjlist_t al;
7185     igraph_integer_t iroot = 0;
7186     igraph_integer_t visited_count;
7187     igraph_integer_t vcount, ecount;
7188 
7189     vcount = igraph_vcount(graph);
7190     ecount = igraph_ecount(graph);
7191 
7192     /* A tree must have precisely vcount-1 edges. */
7193     /* By convention, the zero-vertex graph will not be considered a tree. */
7194     if (ecount != vcount - 1) {
7195         *res = 0;
7196         return IGRAPH_SUCCESS;
7197     }
7198 
7199     /* The single-vertex graph is a tree, provided it has no edges (checked in the previous if (..)) */
7200     if (vcount == 1) {
7201         *res = 1;
7202         if (root) {
7203             *root = 0;
7204         }
7205         return IGRAPH_SUCCESS;
7206     }
7207 
7208     /* For higher vertex counts we cannot short-circuit due to the possibility
7209      * of loops or multi-edges even when the edge count is correct. */
7210 
7211     /* Ignore mode for undirected graphs. */
7212     if (! igraph_is_directed(graph)) {
7213         mode = IGRAPH_ALL;
7214     }
7215 
7216     IGRAPH_CHECK(igraph_adjlist_init(graph, &al, mode));
7217     IGRAPH_FINALLY(igraph_adjlist_destroy, &al);
7218 
7219     /* The main algorithm:
7220      * We find a root and check that all other vertices are reachable from it.
7221      * We have already checked the number of edges, so with the additional
7222      * reachability condition we can verify if the graph is a tree.
7223      *
7224      * For directed graphs, the root is the node with no incoming/outgoing
7225      * connections, depending on 'mode'. For undirected, it is arbitrary, so
7226      * we choose 0.
7227      */
7228 
7229     *res = 1; /* assume success */
7230 
7231     switch (mode) {
7232     case IGRAPH_ALL:
7233         iroot = 0;
7234         break;
7235 
7236     case IGRAPH_IN:
7237     case IGRAPH_OUT: {
7238         igraph_vector_t degree;
7239         igraph_integer_t i;
7240 
7241         IGRAPH_CHECK(igraph_vector_init(&degree, 0));
7242         IGRAPH_FINALLY(igraph_vector_destroy, &degree);
7243 
7244         IGRAPH_CHECK(igraph_degree(graph, &degree, igraph_vss_all(), mode == IGRAPH_IN ? IGRAPH_OUT : IGRAPH_IN, /* loops = */ 1));
7245 
7246         for (i = 0; i < vcount; ++i)
7247             if (VECTOR(degree)[i] == 0) {
7248                 break;
7249             }
7250 
7251         /* if no suitable root is found, the graph is not a tree */
7252         if (i == vcount) {
7253             *res = 0;
7254         } else {
7255             iroot = i;
7256         }
7257 
7258         igraph_vector_destroy(&degree);
7259         IGRAPH_FINALLY_CLEAN(1);
7260     }
7261 
7262     break;
7263     default:
7264         IGRAPH_ERROR("Invalid mode", IGRAPH_EINVMODE);
7265     }
7266 
7267     /* if no suitable root was found, skip visting vertices */
7268     if (*res) {
7269         IGRAPH_CHECK(igraph_i_is_tree_visitor(iroot, &al, &visited_count));
7270         *res = visited_count == vcount;
7271     }
7272 
7273     if (root) {
7274         *root = iroot;
7275     }
7276 
7277     igraph_adjlist_destroy(&al);
7278     IGRAPH_FINALLY_CLEAN(1);
7279 
7280     return IGRAPH_SUCCESS;
7281 }
7282