Coverage Report

Created: 2026-01-05 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/igraph/src/flow/flow.c
Line
Count
Source
1
/*
2
   igraph library.
3
   Copyright (C) 2006-2012  Gabor Csardi <csardi.gabor@gmail.com>
4
   334 Harvard street, Cambridge, MA 02139 USA
5
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 2 of the License, or
9
   (at your option) any later version.
10
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
   02110-1301 USA
20
21
*/
22
23
#include "igraph_flow.h"
24
25
#include "igraph_adjlist.h"
26
#include "igraph_components.h"
27
#include "igraph_conversion.h"
28
#include "igraph_constants.h"
29
#include "igraph_constructors.h"
30
#include "igraph_cycles.h"
31
#include "igraph_dqueue.h"
32
#include "igraph_error.h"
33
#include "igraph_interface.h"
34
#include "igraph_progress.h"
35
#include "igraph_operators.h"
36
#include "igraph_structural.h"
37
38
#include "core/buckets.h"
39
#include "core/cutheap.h"
40
#include "core/interruption.h"
41
#include "flow/flow_internal.h"
42
#include "math/safe_intop.h"
43
44
/*
45
 * Some general remarks about the functions in this file.
46
 *
47
 * The following measures can be calculated:
48
 * ( 1) s-t maximum flow value, directed graph
49
 * ( 2) s-t maximum flow value, undirected graph
50
 * ( 3) s-t maximum flow, directed graph
51
 * ( 4) s-t maximum flow, undirected graph
52
 * ( 5) s-t minimum cut value, directed graph
53
 * ( 6) s-t minimum cut value, undirected graph
54
 * ( 7) minimum cut value, directed graph
55
 * ( 8) minimum cut value, undirected graph
56
 * ( 9) s-t minimum cut, directed graph
57
 * (10) s-t minimum cut, undirected graph
58
 * (11) minimum cut, directed graph
59
 * (12) minimum cut, undirected graph
60
 * (13) s-t edge connectivity, directed graph
61
 * (14) s-t edge connectivity, undirected graph
62
 * (15) edge connectivity, directed graph
63
 * (16) edge connectivity, undirected graph
64
 * (17) s-t vertex connectivity, directed graph
65
 * (18) s-t vertex connectivity, undirected graph
66
 * (19) vertex connectivity, directed graph
67
 * (20) vertex connectivity, undirected graph
68
 * (21) s-t number of edge disjoint paths, directed graph
69
 * (22) s-t number of edge disjoint paths, undirected graph
70
 * (23) s-t number of vertex disjoint paths, directed graph
71
 * (24) s-t number of vertex disjoint paths, undirected graph
72
 * (25) graph adhesion, directed graph
73
 * (26) graph adhesion, undirected graph
74
 * (27) graph cohesion, directed graph
75
 * (28) graph cohesion, undirected graph
76
 *
77
 * This is how they are calculated:
78
 * ( 1) igraph_maxflow_value, calls igraph_maxflow.
79
 * ( 2) igraph_maxflow_value, calls igraph_maxflow, this calls
80
 *      igraph_i_maxflow_undirected. This transforms the graph into a
81
 *      directed graph, including two mutual edges instead of every
82
 *      undirected edge, then igraph_maxflow is called again with the
83
 *      directed graph.
84
 * ( 3) igraph_maxflow, does the push-relabel algorithm, optionally
85
 *      calculates the cut, the partitions and the flow itself.
86
 * ( 4) igraph_maxflow calls igraph_i_maxflow_undirected, this converts
87
 *      the undirected graph into a directed one, adding two mutual edges
88
 *      for each undirected edge, then igraph_maxflow is called again,
89
 *      with the directed graph. After igraph_maxflow returns, we need
90
 *      to edit the flow (and the cut) to make it sense for the
91
 *      original graph.
92
 * ( 5) igraph_st_mincut_value, we just call igraph_maxflow_value
93
 * ( 6) igraph_st_mincut_value, we just call igraph_maxflow_value
94
 * ( 7) igraph_mincut_value, we call igraph_maxflow_value (|V|-1)*2
95
 *      times, from vertex 0 to all other vertices and from all other
96
 *      vertices to vertex 0
97
 * ( 8) We call igraph_i_mincut_value_undirected, that calls
98
 *      igraph_i_mincut_undirected with partition=partition2=cut=NULL
99
 *      The Stoer-Wagner algorithm is used.
100
 * ( 9) igraph_st_mincut, just calls igraph_maxflow.
101
 * (10) igraph_st_mincut, just calls igraph_maxflow.
102
 * (11) igraph_mincut, calls igraph_i_mincut_directed, which runs
103
 *      the maximum flow algorithm 2(|V|-1) times, from vertex zero to
104
 *      and from all other vertices and stores the smallest cut.
105
 * (12) igraph_mincut, igraph_i_mincut_undirected is called,
106
 *      this is the Stoer-Wagner algorithm
107
 * (13) We just call igraph_maxflow_value, back to (1)
108
 * (14) We just call igraph_maxflow_value, back to (2)
109
 * (15) We just call igraph_mincut_value (possibly after some basic
110
 *      checks). Back to (7)
111
 * (16) We just call igraph_mincut_value (possibly after some basic
112
 *      checks). Back to (8).
113
 * (17) We call igraph_i_st_vertex_connectivity_directed.
114
 *      That creates a new graph with 2*|V| vertices and smartly chosen
115
 *      edges, so that the s-t edge connectivity of this graph is the
116
 *      same as the s-t vertex connectivity of the original graph.
117
 *      So finally it calls igraph_maxflow_value, go to (1)
118
 * (18) We call igraph_i_st_vertex_connectivity_undirected.
119
 *      We convert the graph to a directed one,
120
 *      IGRAPH_TO_DIRECTED_MUTUAL method. Then we call
121
 *      igraph_i_st_vertex_connectivity_directed, see (17).
122
 * (19) We call igraph_i_vertex_connectivity_directed.
123
 *      That calls igraph_st_vertex_connectivity for all pairs of
124
 *      vertices. Back to (17).
125
 * (20) We call igraph_i_vertex_connectivity_undirected.
126
 *      That converts the graph into a directed one
127
 *      (IGRAPH_TO_DIRECTED_MUTUAL) and calls the directed version,
128
 *      igraph_i_vertex_connectivity_directed, see (19).
129
 * (21) igraph_edge_disjoint_paths, we just call igraph_maxflow_value, (1).
130
 * (22) igraph_edge_disjoint_paths, we just call igraph_maxflow_value, (2).
131
 * (23) igraph_vertex_disjoint_paths, if there is a connection between
132
 *      the two vertices, then we remove that (or all of them if there
133
 *      are many), as this could mess up vertex connectivity
134
 *      calculation. The we call
135
 *      igraph_i_st_vertex_connectivity_directed, see (19).
136
 * (24) igraph_vertex_disjoint_paths, if there is a connection between
137
 *      the two vertices, then we remove that (or all of them if there
138
 *      are many), as this could mess up vertex connectivity
139
 *      calculation. The we call
140
 *      igraph_i_st_vertex_connectivity_undirected, see (20).
141
 * (25) We just call igraph_edge_connectivity, see (15).
142
 * (26) We just call igraph_edge_connectivity, see (16).
143
 * (27) We just call igraph_vertex_connectivity, see (19).
144
 * (28) We just call igraph_vertex_connectivity, see (20).
145
 */
146
147
/*
148
 * This is an internal function that calculates the maximum flow value
149
 * on undirected graphs, either for an s-t vertex pair or for the
150
 * graph (i.e. all vertex pairs).
151
 *
152
 * It does it by converting the undirected graph to a corresponding
153
 * directed graph, including reciprocal directed edges instead of each
154
 * undirected edge.
155
 */
156
157
static igraph_error_t igraph_i_maxflow_undirected(
158
        const igraph_t *graph,
159
        igraph_real_t *value,
160
        igraph_vector_t *flow,
161
        igraph_vector_int_t *cut,
162
        igraph_vector_int_t *partition,
163
        igraph_vector_int_t *partition2,
164
        igraph_int_t source,
165
        igraph_int_t target,
166
        const igraph_vector_t *capacity,
167
0
        igraph_maxflow_stats_t *stats) {
168
169
0
    const igraph_int_t no_of_edges = igraph_ecount(graph);
170
0
    const igraph_int_t no_of_nodes = igraph_vcount(graph);
171
0
    igraph_vector_int_t edges;
172
0
    igraph_vector_t newcapacity;
173
0
    igraph_t newgraph;
174
0
    igraph_int_t size;
175
176
    /* We need to convert this to directed by hand, since we need to be
177
       sure that the edge IDs will be handled properly to build the new
178
       capacity vector. */
179
180
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0);
181
0
    IGRAPH_VECTOR_INIT_FINALLY(&newcapacity, no_of_edges * 2);
182
0
    IGRAPH_SAFE_MULT(no_of_edges, 4, &size);
183
0
    IGRAPH_CHECK(igraph_vector_int_reserve(&edges, size));
184
0
    IGRAPH_CHECK(igraph_get_edgelist(graph, &edges, 0));
185
0
    IGRAPH_CHECK(igraph_vector_int_resize(&edges, size));
186
0
    for (igraph_int_t i = 0; i < no_of_edges; i++) {
187
0
        VECTOR(edges)[no_of_edges * 2 + i * 2] = VECTOR(edges)[i * 2 + 1];
188
0
        VECTOR(edges)[no_of_edges * 2 + i * 2 + 1] = VECTOR(edges)[i * 2];
189
0
        VECTOR(newcapacity)[i] = VECTOR(newcapacity)[no_of_edges + i] =
190
0
                                     capacity ? VECTOR(*capacity)[i] : 1.0;
191
0
    }
192
193
0
    IGRAPH_CHECK(igraph_create(&newgraph, &edges, no_of_nodes, IGRAPH_DIRECTED));
194
0
    IGRAPH_FINALLY(igraph_destroy, &newgraph);
195
196
0
    IGRAPH_CHECK(igraph_maxflow(&newgraph, value, flow, cut, partition,
197
0
                                partition2, source, target, &newcapacity, stats));
198
199
0
    if (cut) {
200
0
        igraph_int_t cs = igraph_vector_int_size(cut);
201
0
        for (igraph_int_t i = 0; i < cs; i++) {
202
0
            if (VECTOR(*cut)[i] >= no_of_edges) {
203
0
                VECTOR(*cut)[i] -= no_of_edges;
204
0
            }
205
0
        }
206
0
    }
207
208
    /* The flow has one non-zero value for each real-nonreal edge pair,
209
       by definition, we convert it to a positive-negative vector. If
210
       for an edge the flow is negative that means that it is going
211
       from the bigger vertex ID to the smaller one. For positive
212
       values the direction is the opposite. */
213
0
    if (flow) {
214
0
        for (igraph_int_t i = 0; i < no_of_edges; i++) {
215
0
            VECTOR(*flow)[i] -= VECTOR(*flow)[i + no_of_edges];
216
0
        }
217
0
        IGRAPH_CHECK(igraph_vector_resize(flow, no_of_edges));
218
0
    }
219
220
0
    igraph_destroy(&newgraph);
221
0
    igraph_vector_int_destroy(&edges);
222
0
    igraph_vector_destroy(&newcapacity);
223
0
    IGRAPH_FINALLY_CLEAN(3);
224
225
0
    return IGRAPH_SUCCESS;
226
0
}
227
228
31.2M
#define FIRST(i)       (VECTOR(*first)[(i)])
229
35.3M
#define LAST(i)        (VECTOR(*first)[(i)+1])
230
45.8M
#define CURRENT(i)     (VECTOR(*current)[(i)])
231
3.33G
#define RESCAP(i)      (VECTOR(*rescap)[(i)])
232
#define REV(i)         (VECTOR(*rev)[(i)])
233
1.08G
#define HEAD(i)        (VECTOR(*to)[(i)])
234
181M
#define EXCESS(i)      (VECTOR(*excess)[(i)])
235
2.32G
#define DIST(i)        (VECTOR(*distance)[(i)])
236
11.0M
#define DISCHARGE(v)   (igraph_i_mf_discharge((v), &current, &first, &rescap, \
237
11.0M
                        &to, &distance, &excess,        \
238
11.0M
                        no_of_nodes, source, target,    \
239
11.0M
                        &buckets, &ibuckets,        \
240
11.0M
                        &rev, stats, &npushsince,       \
241
11.0M
                        &nrelabelsince))
242
31.6M
#define PUSH(v,e,n)    (igraph_i_mf_push((v), (e), (n), current, rescap,      \
243
31.6M
                        excess, target, source, buckets,     \
244
31.6M
                        ibuckets, distance, rev, stats,      \
245
31.6M
                        npushsince))
246
5.94M
#define RELABEL(v)     (igraph_i_mf_relabel((v), no_of_nodes, distance,       \
247
5.94M
                        first, rescap, to, current,       \
248
5.94M
                        stats, nrelabelsince))
249
195k
#define GAP(b)         (igraph_i_mf_gap((b), stats, buckets, ibuckets,        \
250
195k
                                        no_of_nodes, distance))
251
18.0k
#define BFS()          (igraph_i_mf_bfs(&bfsq, source, target, no_of_nodes,   \
252
18.0k
                                        &buckets, &ibuckets, &distance,       \
253
18.0k
                                        &first, &current, &to, &excess,       \
254
18.0k
                                        &rescap, &rev))
255
256
static void igraph_i_mf_gap(igraph_int_t b, igraph_maxflow_stats_t *stats,
257
                            igraph_buckets_t *buckets, igraph_dbuckets_t *ibuckets,
258
                            igraph_int_t no_of_nodes,
259
195k
                            igraph_vector_int_t *distance) {
260
261
195k
    IGRAPH_UNUSED(buckets);
262
263
195k
    igraph_int_t bo;
264
195k
    (stats->nogap)++;
265
40.5M
    for (bo = b + 1; bo <= no_of_nodes; bo++) {
266
43.8M
        while (!igraph_dbuckets_empty_bucket(ibuckets, bo)) {
267
3.49M
            igraph_int_t n = igraph_dbuckets_pop(ibuckets, bo);
268
3.49M
            (stats->nogapnodes)++;
269
3.49M
            DIST(n) = no_of_nodes;
270
3.49M
        }
271
40.3M
    }
272
195k
}
273
274
static void igraph_i_mf_relabel(igraph_int_t v, igraph_int_t no_of_nodes,
275
                                igraph_vector_int_t *distance,
276
                                igraph_vector_int_t *first,
277
                                igraph_vector_t *rescap, igraph_vector_int_t *to,
278
                                igraph_vector_int_t *current,
279
5.94M
                                igraph_maxflow_stats_t *stats, igraph_int_t *nrelabelsince) {
280
281
5.94M
    igraph_int_t min = no_of_nodes;
282
5.94M
    igraph_int_t k, l, min_edge = 0;
283
5.94M
    (stats->norelabel)++; (*nrelabelsince)++;
284
5.94M
    DIST(v) = no_of_nodes;
285
1.09G
    for (k = FIRST(v), l = LAST(v); k < l; k++) {
286
1.09G
        if (RESCAP(k) > 0 && DIST(HEAD(k)) < min) {
287
8.07M
            min = DIST(HEAD(k));
288
8.07M
            min_edge = k;
289
8.07M
        }
290
1.09G
    }
291
5.94M
    min++;
292
5.94M
    if (min < no_of_nodes) {
293
5.66M
        DIST(v) = min;
294
5.66M
        CURRENT(v) = min_edge;
295
5.66M
    }
296
5.94M
}
297
298
static void igraph_i_mf_push(igraph_int_t v, igraph_int_t e, igraph_int_t n,
299
                             igraph_vector_int_t *current,
300
                             igraph_vector_t *rescap, igraph_vector_t *excess,
301
                             igraph_int_t target, igraph_int_t source,
302
                             igraph_buckets_t *buckets, igraph_dbuckets_t *ibuckets,
303
                             igraph_vector_int_t *distance,
304
                             igraph_vector_int_t *rev, igraph_maxflow_stats_t *stats,
305
31.6M
                             igraph_int_t *npushsince) {
306
307
31.6M
    IGRAPH_UNUSED(current);
308
31.6M
    IGRAPH_UNUSED(source);
309
310
31.6M
    igraph_real_t delta =
311
31.6M
        RESCAP(e) < EXCESS(v) ? RESCAP(e) : EXCESS(v);
312
31.6M
    (stats->nopush)++; (*npushsince)++;
313
31.6M
    if (EXCESS(n) == 0 && n != target) {
314
9.85M
        igraph_dbuckets_delete(ibuckets, DIST(n), n);
315
9.85M
        igraph_buckets_add(buckets, DIST(n), n);
316
9.85M
    }
317
31.6M
    RESCAP(e) -= delta;
318
31.6M
    RESCAP(REV(e)) += delta;
319
31.6M
    EXCESS(n) += delta;
320
31.6M
    EXCESS(v) -= delta;
321
31.6M
}
322
323
static void igraph_i_mf_discharge(igraph_int_t v,
324
                                  igraph_vector_int_t *current,
325
                                  igraph_vector_int_t *first,
326
                                  igraph_vector_t *rescap,
327
                                  igraph_vector_int_t *to,
328
                                  igraph_vector_int_t *distance,
329
                                  igraph_vector_t *excess,
330
                                  igraph_int_t no_of_nodes, igraph_int_t source,
331
                                  igraph_int_t target, igraph_buckets_t *buckets,
332
                                  igraph_dbuckets_t *ibuckets,
333
                                  igraph_vector_int_t *rev,
334
                                  igraph_maxflow_stats_t *stats,
335
11.0M
                                  igraph_int_t *npushsince, igraph_int_t *nrelabelsince) {
336
337
16.7M
    do {
338
16.7M
        igraph_int_t i;
339
16.7M
        igraph_int_t start = CURRENT(v);
340
16.7M
        igraph_int_t stop = LAST(v);
341
1.09G
        for (i = start; i < stop; i++) {
342
1.09G
            if (RESCAP(i) > 0) {
343
576M
                igraph_int_t nei = HEAD(i);
344
576M
                if (DIST(v) == DIST(nei) + 1) {
345
31.6M
                    PUSH((v), i, nei);
346
31.6M
                    if (EXCESS(v) == 0) {
347
10.8M
                        break;
348
10.8M
                    }
349
31.6M
                }
350
576M
            }
351
1.09G
        }
352
16.7M
        if (i == stop) {
353
5.94M
            igraph_int_t origdist = DIST(v);
354
5.94M
            RELABEL(v);
355
5.94M
            if (igraph_buckets_empty_bucket(buckets, origdist) &&
356
3.71M
                igraph_dbuckets_empty_bucket(ibuckets, origdist)) {
357
195k
                GAP(origdist);
358
195k
            }
359
5.94M
            if (DIST(v) == no_of_nodes) {
360
277k
                break;
361
277k
            }
362
10.8M
        } else {
363
10.8M
            CURRENT(v) = i;
364
10.8M
            igraph_dbuckets_add(ibuckets, DIST(v), v);
365
10.8M
            break;
366
10.8M
        }
367
16.7M
    } while (1);
368
11.0M
}
369
370
static igraph_error_t igraph_i_mf_bfs(igraph_dqueue_int_t *bfsq,
371
                                      igraph_int_t source, igraph_int_t target,
372
                                      igraph_int_t no_of_nodes, igraph_buckets_t *buckets,
373
                                      igraph_dbuckets_t *ibuckets,
374
                                      igraph_vector_int_t *distance,
375
                                      igraph_vector_int_t *first, igraph_vector_int_t *current,
376
                                      igraph_vector_int_t *to, igraph_vector_t *excess,
377
69.9k
                                      igraph_vector_t *rescap, igraph_vector_int_t *rev) {
378
379
69.9k
    igraph_int_t k, l;
380
381
69.9k
    IGRAPH_UNUSED(source);
382
383
69.9k
    igraph_buckets_clear(buckets);
384
69.9k
    igraph_dbuckets_clear(ibuckets);
385
69.9k
    igraph_vector_int_fill(distance, no_of_nodes);
386
69.9k
    DIST(target) = 0;
387
388
69.9k
    IGRAPH_CHECK(igraph_dqueue_int_push(bfsq, target));
389
12.7M
    while (!igraph_dqueue_int_empty(bfsq)) {
390
12.6M
        igraph_int_t node = igraph_dqueue_int_pop(bfsq);
391
12.6M
        igraph_int_t ndist = DIST(node) + 1;
392
1.04G
        for (k = FIRST(node), l = LAST(node); k < l; k++) {
393
1.03G
            if (RESCAP(REV(k)) > 0) {
394
509M
                igraph_int_t nei = HEAD(k);
395
509M
                if (DIST(nei) == no_of_nodes) {
396
12.6M
                    DIST(nei) = ndist;
397
12.6M
                    CURRENT(nei) = FIRST(nei);
398
12.6M
                    if (EXCESS(nei) > 0) {
399
1.53M
                        igraph_buckets_add(buckets, ndist, nei);
400
11.0M
                    } else {
401
11.0M
                        igraph_dbuckets_add(ibuckets, ndist, nei);
402
11.0M
                    }
403
12.6M
                    IGRAPH_CHECK(igraph_dqueue_int_push(bfsq, nei));
404
12.6M
                }
405
509M
            }
406
1.03G
        }
407
12.6M
    }
408
409
69.9k
    return IGRAPH_SUCCESS;
410
69.9k
}
411
412
/**
413
 * \function igraph_maxflow
414
 * \brief Maximum network flow between a pair of vertices.
415
 *
416
 * This function implements the Goldberg-Tarjan algorithm for
417
 * calculating value of the maximum flow in a directed or undirected
418
 * graph. The algorithm was given in Andrew V. Goldberg, Robert
419
 * E. Tarjan: A New Approach to the Maximum-Flow Problem, Journal of
420
 * the ACM, 35(4), 921-940, 1988
421
 * https://doi.org/10.1145/48014.61051.
422
 *
423
 * </para><para>
424
 * The input of the function is a graph, a vector
425
 * of real numbers giving the capacity of the edges and two vertices
426
 * of the graph, the source and the target. A flow is a function
427
 * assigning positive real numbers to the edges and satisfying two
428
 * requirements: (1) the flow value is less than the capacity of the
429
 * edge and (2) at each vertex except the source and the target, the
430
 * incoming flow (i.e. the sum of the flow on the incoming edges) is
431
 * the same as the outgoing flow (i.e. the sum of the flow on the
432
 * outgoing edges). The value of the flow is the incoming flow at the
433
 * target vertex. The maximum flow is the flow with the maximum
434
 * value.
435
 *
436
 * \param graph The input graph, either directed or undirected.
437
 * \param value Pointer to a real number, the value of the maximum
438
 *        will be placed here, unless it is a null pointer.
439
 * \param flow If not a null pointer, then it must be a pointer to an
440
 *        initialized vector. The vector will be resized, and the flow
441
 *        on each edge will be placed in it, in the order of the edge
442
 *        IDs. For undirected graphs this argument is bit trickier,
443
 *        since for these the flow direction is not predetermined by
444
 *        the edge direction. For these graphs the elements of the
445
 *        \p flow vector can be negative, this means that the flow
446
 *        goes from the bigger vertex ID to the smaller one. Positive
447
 *        values mean that the flow goes from the smaller vertex ID to
448
 *        the bigger one.
449
 * \param cut A null pointer or a pointer to an initialized vector.
450
 *        If not a null pointer, then the minimum cut corresponding to
451
 *        the maximum flow is stored here, i.e. all edge IDs that are
452
 *        part of the minimum cut are stored in the vector.
453
 * \param partition A null pointer or a pointer to an initialized
454
 *        vector. If not a null pointer, then the first partition of
455
 *        the minimum cut that corresponds to the maximum flow will be
456
 *        placed here. The first partition is always the one that
457
 *        contains the source vertex.
458
 * \param partition2 A null pointer or a pointer to an initialized
459
 *        vector. If not a null pointer, then the second partition of
460
 *        the minimum cut that corresponds to the maximum flow will be
461
 *        placed here. The second partition is always the one that
462
 *        contains the target vertex.
463
 * \param source The id of the source vertex.
464
 * \param target The id of the target vertex.
465
 * \param capacity Vector containing the capacity of the edges. If \c NULL, then
466
 *        every edge is considered to have capacity 1.0.
467
 * \param stats Counts of the number of different operations
468
 *        performed by the algorithm are stored here.
469
 * \return Error code.
470
 *
471
 * Time complexity: O(|V|^3). In practice it is much faster, but I
472
 * cannot prove a better lower bound for the data structure I've
473
 * used. In fact, this implementation runs much faster than the
474
 * \c hi_pr implementation discussed in
475
 * B. V. Cherkassky and A. V. Goldberg: On implementing the
476
 * push-relabel method for the maximum flow problem, (Algorithmica,
477
 * 19:390--410, 1997) on all the graph classes I've tried.
478
 *
479
 * \sa \ref igraph_mincut_value(), \ref igraph_edge_connectivity(),
480
 * \ref igraph_vertex_connectivity() for
481
 * properties based on the maximum flow.
482
 *
483
 * \example examples/simple/flow.c
484
 * \example examples/simple/flow2.c
485
 */
486
487
igraph_error_t igraph_maxflow(const igraph_t *graph, igraph_real_t *value,
488
                              igraph_vector_t *flow, igraph_vector_int_t *cut,
489
                              igraph_vector_int_t *partition, igraph_vector_int_t *partition2,
490
                              igraph_int_t source, igraph_int_t target,
491
                              const igraph_vector_t *capacity,
492
51.8k
                              igraph_maxflow_stats_t *stats) {
493
494
51.8k
    const igraph_int_t no_of_nodes = igraph_vcount(graph);
495
51.8k
    const igraph_int_t no_of_orig_edges = igraph_ecount(graph);
496
51.8k
    const igraph_int_t no_of_edges = 2 * no_of_orig_edges;
497
498
51.8k
    igraph_vector_t rescap, excess;
499
51.8k
    igraph_vector_int_t from, to, rev, distance;
500
51.8k
    igraph_vector_int_t edges, rank;
501
51.8k
    igraph_vector_int_t current, first;
502
51.8k
    igraph_buckets_t buckets;
503
51.8k
    igraph_dbuckets_t ibuckets;
504
505
51.8k
    igraph_dqueue_int_t bfsq;
506
507
51.8k
    igraph_int_t idx;
508
51.8k
    igraph_int_t npushsince = 0, nrelabelsince = 0;
509
510
51.8k
    igraph_maxflow_stats_t local_stats;   /* used if the user passed a null pointer for stats */
511
512
51.8k
    if (stats == NULL) {
513
51.8k
        stats = &local_stats;
514
51.8k
    }
515
516
51.8k
    if (!igraph_is_directed(graph)) {
517
0
        IGRAPH_CHECK(igraph_i_maxflow_undirected(graph, value, flow, cut,
518
0
                     partition, partition2, source,
519
0
                     target, capacity, stats));
520
0
        return IGRAPH_SUCCESS;
521
0
    }
522
523
51.8k
    if (capacity && igraph_vector_size(capacity) != no_of_orig_edges) {
524
0
        IGRAPH_ERROR("Capacity vector must match number of edges in length.", IGRAPH_EINVAL);
525
0
    }
526
51.8k
    if (source < 0 || source >= no_of_nodes || target < 0 || target >= no_of_nodes) {
527
0
        IGRAPH_ERROR("Invalid source or target vertex.", IGRAPH_EINVVID);
528
0
    }
529
51.8k
    if (source == target) {
530
0
        IGRAPH_ERROR("Source and target vertices are the same.", IGRAPH_EINVAL);
531
0
    }
532
533
51.8k
    stats->nopush = stats->norelabel = stats->nogap = stats->nogapnodes =
534
51.8k
                                           stats->nobfs = 0;
535
536
    /*
537
     * The data structure:
538
     * - First of all, we consider every edge twice, first the edge
539
     *   itself, but also its opposite.
540
     * - (from, to) contain all edges (original + opposite), ordered by
541
     *   the id of the source vertex. During the algorithm we just need
542
     *   'to', so from is destroyed soon. We only need it in the
543
     *   beginning, to create the 'first' pointers.
544
     * - 'first' is a pointer vector for 'to', first[i] points to the
545
     *   first neighbor of vertex i and first[i+1]-1 is the last
546
     *   neighbor of vertex i. (Unless vertex i is isolate, in which
547
     *   case first[i]==first[i+1]).
548
     * - 'rev' contains a mapping from an edge to its opposite pair
549
     * - 'rescap' contains the residual capacities of the edges, this is
550
     *   initially equal to the capacity of the edges for the original
551
     *   edges and it is zero for the opposite edges.
552
     * - 'excess' contains the excess flow for the vertices. I.e. the flow
553
     *   that is coming in, but it is not going out.
554
     * - 'current' stores the next neighboring vertex to check, for every
555
     *   vertex, when excess flow is being pushed to neighbors.
556
     * - 'distance' stores the distance of the vertices from the source.
557
     * - 'rank' and 'edges' are only needed temporarily, for ordering and
558
     *   storing the edges.
559
     * - we use an igraph_buckets_t data structure ('buckets') to find
560
     *   the vertices with the highest 'distance' values quickly.
561
     *   This always contains the vertices that have a positive excess
562
     *   flow.
563
     */
564
51.8k
#undef FIRST
565
51.8k
#undef LAST
566
51.8k
#undef CURRENT
567
51.8k
#undef RESCAP
568
51.8k
#undef REV
569
51.8k
#undef HEAD
570
51.8k
#undef EXCESS
571
51.8k
#undef DIST
572
51.8k
#define FIRST(i)       (VECTOR(first)[(i)])
573
51.8k
#define LAST(i)        (VECTOR(first)[(i)+1])
574
51.8k
#define CURRENT(i)     (VECTOR(current)[(i)])
575
26.5M
#define RESCAP(i)      (VECTOR(rescap)[(i)])
576
51.8k
#define REV(i)         (VECTOR(rev)[(i)])
577
30.9M
#define HEAD(i)        (VECTOR(to)[(i)])
578
8.91M
#define EXCESS(i)      (VECTOR(excess)[(i)])
579
51.8k
#define DIST(i)        (VECTOR(distance)[(i)])
580
581
51.8k
    IGRAPH_CHECK(igraph_dqueue_int_init(&bfsq, no_of_nodes));
582
51.8k
    IGRAPH_FINALLY(igraph_dqueue_int_destroy, &bfsq);
583
51.8k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&to,       no_of_edges);
584
51.8k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&rev,      no_of_edges);
585
51.8k
    IGRAPH_VECTOR_INIT_FINALLY(&rescap,       no_of_edges);
586
51.8k
    IGRAPH_VECTOR_INIT_FINALLY(&excess,       no_of_nodes);
587
51.8k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&distance, no_of_nodes);
588
51.8k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&first,    no_of_nodes + 1);
589
590
51.8k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&rank,         no_of_edges);
591
51.8k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&from,     no_of_edges);
592
51.8k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&edges,        no_of_edges);
593
594
    /* Create the basic data structure */
595
51.8k
    IGRAPH_CHECK(igraph_get_edgelist(graph, &edges, 0));
596
51.8k
    IGRAPH_CHECK(igraph_i_vector_int_rank(&edges, &rank, no_of_nodes));
597
598
429M
    for (igraph_int_t i = 0; i < no_of_edges; i += 2) {
599
429M
        const igraph_int_t pos = VECTOR(rank)[i];
600
429M
        const igraph_int_t pos2 = VECTOR(rank)[i + 1];
601
429M
        VECTOR(from)[pos] = VECTOR(edges)[i];
602
429M
        VECTOR(to)[pos]   = VECTOR(edges)[i + 1];
603
429M
        VECTOR(from)[pos2] = VECTOR(edges)[i + 1];
604
429M
        VECTOR(to)[pos2]   = VECTOR(edges)[i];
605
429M
        VECTOR(rev)[pos] = pos2;
606
429M
        VECTOR(rev)[pos2] = pos;
607
429M
        VECTOR(rescap)[pos] = capacity ? VECTOR(*capacity)[i / 2] : 1.0;
608
429M
        VECTOR(rescap)[pos2] = 0.0;
609
429M
    }
610
611
    /* The first pointers. This is a but trickier, than one would
612
       think, because of the possible isolate vertices. */
613
614
51.8k
    idx = -1;
615
103k
    for (igraph_int_t i = 0; i <= VECTOR(from)[0]; i++) {
616
51.8k
        idx++; VECTOR(first)[idx] = 0;
617
51.8k
    }
618
858M
    for (igraph_int_t i = 1; i < no_of_edges; i++) {
619
858M
        const igraph_int_t n = (VECTOR(from)[i] -
620
858M
                                    VECTOR(from)[ VECTOR(first)[idx] ]);
621
869M
        for (igraph_int_t j = 0; j < n; j++) {
622
10.7M
            idx++; VECTOR(first)[idx] = i;
623
10.7M
        }
624
858M
    }
625
51.8k
    idx++;
626
103k
    while (idx < no_of_nodes + 1) {
627
51.8k
        VECTOR(first)[idx++] = no_of_edges;
628
51.8k
    }
629
630
51.8k
    igraph_vector_int_destroy(&from);
631
51.8k
    igraph_vector_int_destroy(&edges);
632
51.8k
    IGRAPH_FINALLY_CLEAN(2);
633
634
51.8k
    if (!flow) {
635
51.8k
        igraph_vector_int_destroy(&rank);
636
51.8k
        IGRAPH_FINALLY_CLEAN(1);
637
51.8k
    }
638
639
    /* And the current pointers, initially the same as the first */
640
51.8k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&current, no_of_nodes);
641
10.8M
    for (igraph_int_t i = 0; i < no_of_nodes; i++) {
642
10.8M
        VECTOR(current)[i] = VECTOR(first)[i];
643
10.8M
    }
644
645
    /* OK, the graph is set up, initialization */
646
647
51.8k
    IGRAPH_CHECK(igraph_buckets_init(&buckets, no_of_nodes + 1, no_of_nodes));
648
51.8k
    IGRAPH_FINALLY(igraph_buckets_destroy, &buckets);
649
51.8k
    IGRAPH_CHECK(igraph_dbuckets_init(&ibuckets, no_of_nodes + 1, no_of_nodes));
650
51.8k
    IGRAPH_FINALLY(igraph_dbuckets_destroy, &ibuckets);
651
652
    /* Send as much flow as possible from the source to its neighbors */
653
31.0M
    for (igraph_int_t i = FIRST(source), j = LAST(source); i < j; i++) {
654
30.9M
        if (HEAD(i) != source) {
655
8.85M
            const igraph_real_t delta = RESCAP(i);
656
8.85M
            RESCAP(i) = 0;
657
8.85M
            RESCAP(REV(i)) += delta;
658
8.85M
            EXCESS(HEAD(i)) += delta;
659
8.85M
        }
660
30.9M
    }
661
662
51.8k
    IGRAPH_CHECK(BFS());
663
51.8k
    (stats->nobfs)++;
664
665
11.1M
    while (!igraph_buckets_empty(&buckets)) {
666
11.0M
        const igraph_int_t vertex = igraph_buckets_popmax(&buckets);
667
11.0M
        DISCHARGE(vertex);
668
11.0M
        if (npushsince > no_of_nodes / 2 && nrelabelsince > no_of_nodes) {
669
18.0k
            (stats->nobfs)++;
670
18.0k
            BFS();
671
18.0k
            npushsince = nrelabelsince = 0;
672
18.0k
        }
673
11.0M
    }
674
675
    /* Store the result */
676
51.8k
    if (value) {
677
51.8k
        *value = EXCESS(target);
678
51.8k
    }
679
680
    /* If we also need the minimum cut */
681
51.8k
    if (cut || partition || partition2) {
682
        /* We need to find all vertices from which the target is reachable
683
           in the residual graph. We do a breadth-first search, going
684
           backwards. */
685
0
        igraph_dqueue_int_t Q;
686
0
        igraph_vector_bool_t added;
687
0
        igraph_int_t marked = 0;
688
689
0
        IGRAPH_CHECK(igraph_vector_bool_init(&added, no_of_nodes));
690
0
        IGRAPH_FINALLY(igraph_vector_bool_destroy, &added);
691
692
0
        IGRAPH_CHECK(igraph_dqueue_int_init(&Q, 100));
693
0
        IGRAPH_FINALLY(igraph_dqueue_int_destroy, &Q);
694
695
0
        IGRAPH_CHECK(igraph_dqueue_int_push(&Q, target));
696
0
        VECTOR(added)[target] = true;
697
0
        marked++;
698
0
        while (!igraph_dqueue_int_empty(&Q)) {
699
0
            const igraph_int_t actnode = igraph_dqueue_int_pop(&Q);
700
0
            for (igraph_int_t i = FIRST(actnode), j = LAST(actnode); i < j; i++) {
701
0
                igraph_int_t nei = HEAD(i);
702
0
                if (!VECTOR(added)[nei] && RESCAP(REV(i)) > 0.0) {
703
0
                    VECTOR(added)[nei] = true;
704
0
                    marked++;
705
0
                    IGRAPH_CHECK(igraph_dqueue_int_push(&Q, nei));
706
0
                }
707
0
            }
708
0
        }
709
0
        igraph_dqueue_int_destroy(&Q);
710
0
        IGRAPH_FINALLY_CLEAN(1);
711
712
        /* Now we marked each vertex that is on one side of the cut,
713
           check the crossing edges */
714
715
0
        if (cut) {
716
0
            igraph_vector_int_clear(cut);
717
0
            for (igraph_int_t i = 0; i < no_of_orig_edges; i++) {
718
0
                igraph_int_t f = IGRAPH_FROM(graph, i);
719
0
                igraph_int_t t = IGRAPH_TO(graph, i);
720
0
                if (!VECTOR(added)[f] && VECTOR(added)[t]) {
721
0
                    IGRAPH_CHECK(igraph_vector_int_push_back(cut, i));
722
0
                }
723
0
            }
724
0
        }
725
726
0
        if (partition2) {
727
0
            igraph_int_t x = 0;
728
0
            IGRAPH_CHECK(igraph_vector_int_resize(partition2, marked));
729
0
            for (igraph_int_t i = 0; i < no_of_nodes; i++) {
730
0
                if (VECTOR(added)[i]) {
731
0
                    VECTOR(*partition2)[x++] = i;
732
0
                }
733
0
            }
734
0
        }
735
736
0
        if (partition) {
737
0
            igraph_int_t x = 0;
738
0
            IGRAPH_CHECK(igraph_vector_int_resize(partition,
739
0
                                                  no_of_nodes - marked));
740
0
            for (igraph_int_t i = 0; i < no_of_nodes; i++) {
741
0
                if (!VECTOR(added)[i]) {
742
0
                    VECTOR(*partition)[x++] = i;
743
0
                }
744
0
            }
745
0
        }
746
747
0
        igraph_vector_bool_destroy(&added);
748
0
        IGRAPH_FINALLY_CLEAN(1);
749
0
    }
750
751
51.8k
    if (flow) {
752
        /* Initialize the backward distances, with a breadth-first search
753
           from the source */
754
0
        igraph_dqueue_int_t Q;
755
0
        igraph_vector_int_t added; /* uses more than two values, cannot be bool */
756
0
        igraph_t flow_graph;
757
0
        igraph_vector_int_t flow_edges;
758
0
        igraph_bool_t dag;
759
760
0
        IGRAPH_CHECK(igraph_vector_int_init(&added, no_of_nodes));
761
0
        IGRAPH_FINALLY(igraph_vector_int_destroy, &added);
762
0
        IGRAPH_CHECK(igraph_dqueue_int_init(&Q, 100));
763
0
        IGRAPH_FINALLY(igraph_dqueue_int_destroy, &Q);
764
765
0
        IGRAPH_CHECK(igraph_dqueue_int_push(&Q, source));
766
0
        IGRAPH_CHECK(igraph_dqueue_int_push(&Q, 0));
767
0
        VECTOR(added)[source] = 1;
768
0
        while (!igraph_dqueue_int_empty(&Q)) {
769
0
            const igraph_int_t actnode = igraph_dqueue_int_pop(&Q);
770
0
            const igraph_int_t actdist = igraph_dqueue_int_pop(&Q);
771
0
            DIST(actnode) = actdist;
772
773
0
            for (igraph_int_t i = FIRST(actnode), j = LAST(actnode); i < j; i++) {
774
0
                const igraph_int_t nei = HEAD(i);
775
0
                if (!VECTOR(added)[nei] && RESCAP(REV(i)) > 0.0) {
776
0
                    VECTOR(added)[nei] = 1;
777
0
                    IGRAPH_CHECK(igraph_dqueue_int_push(&Q, nei));
778
0
                    IGRAPH_CHECK(igraph_dqueue_int_push(&Q, actdist + 1));
779
0
                }
780
0
            }
781
0
        } /* !igraph_dqueue_int_empty(&Q) */
782
783
0
        igraph_vector_int_destroy(&added);
784
0
        igraph_dqueue_int_destroy(&Q);
785
0
        IGRAPH_FINALLY_CLEAN(2);
786
787
        /* Reinitialize the buckets */
788
0
        igraph_buckets_clear(&buckets);
789
0
        for (igraph_int_t i = 0; i < no_of_nodes; i++) {
790
0
            if (EXCESS(i) > 0.0 && i != source && i != target) {
791
0
                igraph_buckets_add(&buckets, DIST(i), i);
792
0
            }
793
0
        }
794
795
        /* Now we return the flow to the source */
796
0
        while (!igraph_buckets_empty(&buckets)) {
797
0
            const igraph_int_t vertex = igraph_buckets_popmax(&buckets);
798
799
            /* DISCHARGE(vertex) comes here */
800
0
            do {
801
0
                igraph_int_t i, j;
802
0
                for (i = CURRENT(vertex), j = LAST(vertex); i < j; i++) {
803
0
                    if (RESCAP(i) > 0) {
804
0
                        igraph_int_t nei = HEAD(i);
805
806
0
                        if (DIST(vertex) == DIST(nei) + 1) {
807
0
                            igraph_real_t delta =
808
0
                                RESCAP(i) < EXCESS(vertex) ? RESCAP(i) : EXCESS(vertex);
809
0
                            RESCAP(i) -= delta;
810
0
                            RESCAP(REV(i)) += delta;
811
812
0
                            if (nei != source && EXCESS(nei) == 0.0 &&
813
0
                                DIST(nei) != no_of_nodes) {
814
0
                                igraph_buckets_add(&buckets, DIST(nei), nei);
815
0
                            }
816
817
0
                            EXCESS(nei) += delta;
818
0
                            EXCESS(vertex) -= delta;
819
820
0
                            if (EXCESS(vertex) == 0) {
821
0
                                break;
822
0
                            }
823
824
0
                        }
825
0
                    }
826
0
                }
827
828
0
                if (i == j) {
829
830
                    /* RELABEL(vertex) comes here */
831
0
                    igraph_int_t min;
832
0
                    igraph_int_t min_edge = 0;
833
0
                    DIST(vertex) = min = no_of_nodes;
834
0
                    for (igraph_int_t k = FIRST(vertex), l = LAST(vertex); k < l; k++) {
835
0
                        if (RESCAP(k) > 0) {
836
0
                            if (DIST(HEAD(k)) < min) {
837
0
                                min = DIST(HEAD(k));
838
0
                                min_edge = k;
839
0
                            }
840
0
                        }
841
0
                    }
842
843
0
                    min++;
844
845
0
                    if (min < no_of_nodes) {
846
0
                        DIST(vertex) = min;
847
0
                        CURRENT(vertex) = min_edge;
848
                        /* Vertex is still active */
849
0
                        igraph_buckets_add(&buckets, DIST(vertex), vertex);
850
0
                    }
851
852
                    /* TODO: gap heuristics here ??? */
853
854
0
                } else {
855
0
                    CURRENT(vertex) = FIRST(vertex);
856
0
                }
857
858
0
                break;
859
860
0
            } while (true);
861
0
        }
862
863
        /* We need to eliminate flow cycles now. Before that we check that
864
           there is a cycle in the flow graph.
865
866
           First we do a couple of DFSes from the source vertex to the
867
           target and factor out the paths we find. If there is no more
868
           path to the target, then all remaining flow must be in flow
869
           cycles, so we don't need it at all.
870
871
           Some details. 'stack' contains the whole path of the DFS, both
872
           the vertices and the edges, they are alternating in the stack.
873
           'current' helps finding the next outgoing edge of a vertex
874
           quickly, the next edge of 'v' is FIRST(v)+CURRENT(v). If this
875
           is LAST(v), then there are no more edges to try.
876
877
           The 'added' vector contains 0 if the vertex was not visited
878
           before, 1 if it is currently in 'stack', and 2 if it is not in
879
           'stack', but it was visited before. */
880
881
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&flow_edges, 0);
882
0
        for (igraph_int_t i = 0, j = 0; i < no_of_edges; i += 2, j++) {
883
0
            const igraph_int_t pos = VECTOR(rank)[i];
884
0
            if ((capacity ? VECTOR(*capacity)[j] : 1.0) > RESCAP(pos)) {
885
0
                IGRAPH_CHECK(igraph_vector_int_push_back(&flow_edges,
886
0
                             IGRAPH_FROM(graph, j)));
887
0
                IGRAPH_CHECK(igraph_vector_int_push_back(&flow_edges,
888
0
                             IGRAPH_TO(graph, j)));
889
0
            }
890
0
        }
891
0
        IGRAPH_CHECK(igraph_create(&flow_graph, &flow_edges, no_of_nodes,
892
0
                                   IGRAPH_DIRECTED));
893
0
        igraph_vector_int_destroy(&flow_edges);
894
0
        IGRAPH_FINALLY_CLEAN(1);
895
0
        IGRAPH_FINALLY(igraph_destroy, &flow_graph);
896
0
        IGRAPH_CHECK(igraph_is_dag(&flow_graph, &dag));
897
0
        igraph_destroy(&flow_graph);
898
0
        IGRAPH_FINALLY_CLEAN(1);
899
900
0
        if (!dag) {
901
0
            igraph_vector_int_t stack;
902
0
            igraph_vector_t mycap;
903
904
0
            IGRAPH_CHECK(igraph_vector_int_init(&stack, 0));
905
0
            IGRAPH_FINALLY(igraph_vector_int_destroy, &stack);
906
0
            IGRAPH_CHECK(igraph_vector_int_init(&added, no_of_nodes));
907
0
            IGRAPH_FINALLY(igraph_vector_int_destroy, &added);
908
0
            IGRAPH_VECTOR_INIT_FINALLY(&mycap, no_of_edges);
909
910
0
#define MYCAP(i)      (VECTOR(mycap)[(i)])
911
912
0
            for (igraph_int_t i = 0; i < no_of_edges; i += 2) {
913
0
                const igraph_int_t pos = VECTOR(rank)[i];
914
0
                const igraph_int_t pos2 = VECTOR(rank)[i + 1];
915
0
                MYCAP(pos) = (capacity ? VECTOR(*capacity)[i / 2] : 1.0) - RESCAP(pos);
916
0
                MYCAP(pos2) = 0.0;
917
0
            }
918
919
0
            do {
920
0
                igraph_vector_int_null(&current);
921
0
                igraph_vector_int_clear(&stack);
922
0
                igraph_vector_int_null(&added);
923
924
0
                IGRAPH_CHECK(igraph_vector_int_push_back(&stack, -1));
925
0
                IGRAPH_CHECK(igraph_vector_int_push_back(&stack, source));
926
0
                VECTOR(added)[source] = 1;
927
0
                while (!igraph_vector_int_empty(&stack) &&
928
0
                       igraph_vector_int_tail(&stack) != target) {
929
0
                    const igraph_int_t actnode = igraph_vector_int_tail(&stack);
930
0
                    igraph_int_t edge = FIRST(actnode) + CURRENT(actnode);
931
0
                    igraph_int_t nei;
932
0
                    while (edge < LAST(actnode) && MYCAP(edge) == 0.0) {
933
0
                        edge++;
934
0
                    }
935
0
                    nei = edge < LAST(actnode) ? HEAD(edge) : -1;
936
937
0
                    if (edge < LAST(actnode) && !VECTOR(added)[nei]) {
938
                        /* Go forward along next edge, if the vertex was not
939
                           visited before */
940
0
                        IGRAPH_CHECK(igraph_vector_int_push_back(&stack, edge));
941
0
                        IGRAPH_CHECK(igraph_vector_int_push_back(&stack, nei));
942
0
                        VECTOR(added)[nei] = 1;
943
0
                        CURRENT(actnode) += 1;
944
0
                    } else if (edge < LAST(actnode) && VECTOR(added)[nei] == 1) {
945
                        /* We found a flow cycle, factor it out. Go back in stack
946
                           until we find 'nei' again, determine the flow along the
947
                           cycle. */
948
0
                        igraph_real_t thisflow = MYCAP(edge);
949
0
                        for (igraph_int_t idx = igraph_vector_int_size(&stack) - 2;
950
0
                             idx >= 0 && VECTOR(stack)[idx + 1] != nei; idx -= 2) {
951
0
                            const igraph_int_t e = VECTOR(stack)[idx];
952
0
                            const igraph_real_t rcap = e >= 0 ? MYCAP(e) : MYCAP(edge);
953
0
                            if (rcap < thisflow) {
954
0
                                thisflow = rcap;
955
0
                            }
956
0
                        }
957
0
                        MYCAP(edge) -= thisflow; RESCAP(edge) += thisflow;
958
0
                        for (igraph_int_t idx = igraph_vector_int_size(&stack) - 2;
959
0
                             idx >= 0 && VECTOR(stack)[idx + 1] != nei; idx -= 2) {
960
0
                            const igraph_int_t e = VECTOR(stack)[idx];
961
0
                            if (e >= 0) {
962
0
                                MYCAP(e) -= thisflow;
963
0
                                RESCAP(e) += thisflow;
964
0
                            }
965
0
                        }
966
0
                        CURRENT(actnode) += 1;
967
0
                    } else if (edge < LAST(actnode)) { /* && VECTOR(added)[nei]==2 */
968
                        /* The next edge leads to a vertex that was visited before,
969
                           but it is currently not in 'stack' */
970
0
                        CURRENT(actnode) += 1;
971
0
                    } else {
972
                        /* Go backward, take out the node and the edge that leads to it */
973
0
                        igraph_vector_int_pop_back(&stack);
974
0
                        igraph_vector_int_pop_back(&stack);
975
0
                        VECTOR(added)[actnode] = 2;
976
0
                    }
977
0
                }
978
979
                /* If non-empty, then it contains a path from source to target
980
                   in the residual graph. We factor out this path from the flow. */
981
0
                if (!igraph_vector_int_empty(&stack)) {
982
0
                    const igraph_int_t pl = igraph_vector_int_size(&stack);
983
0
                    igraph_real_t thisflow = EXCESS(target);
984
0
                    for (igraph_int_t i = 2; i < pl; i += 2) {
985
0
                        const igraph_int_t edge = VECTOR(stack)[i];
986
0
                        const igraph_real_t rcap = MYCAP(edge);
987
0
                        if (rcap < thisflow) {
988
0
                            thisflow = rcap;
989
0
                        }
990
0
                    }
991
0
                    for (igraph_int_t i = 2; i < pl; i += 2) {
992
0
                        const igraph_int_t edge = VECTOR(stack)[i];
993
0
                        MYCAP(edge) -= thisflow;
994
0
                    }
995
0
                }
996
997
0
            } while (!igraph_vector_int_empty(&stack));
998
999
0
            igraph_vector_destroy(&mycap);
1000
0
            igraph_vector_int_destroy(&added);
1001
0
            igraph_vector_int_destroy(&stack);
1002
0
            IGRAPH_FINALLY_CLEAN(3);
1003
0
        }
1004
1005
        /* ----------------------------------------------------------- */
1006
1007
0
        IGRAPH_CHECK(igraph_vector_resize(flow, no_of_orig_edges));
1008
0
        for (igraph_int_t i = 0, j = 0; i < no_of_edges; i += 2, j++) {
1009
0
            const igraph_int_t pos = VECTOR(rank)[i];
1010
0
            VECTOR(*flow)[j] = (capacity ? VECTOR(*capacity)[j] : 1.0) -
1011
0
                               RESCAP(pos);
1012
0
        }
1013
1014
0
        igraph_vector_int_destroy(&rank);
1015
0
        IGRAPH_FINALLY_CLEAN(1);
1016
0
    }
1017
1018
51.8k
    igraph_dbuckets_destroy(&ibuckets);
1019
51.8k
    igraph_buckets_destroy(&buckets);
1020
51.8k
    igraph_vector_int_destroy(&current);
1021
51.8k
    igraph_vector_int_destroy(&first);
1022
51.8k
    igraph_vector_int_destroy(&distance);
1023
51.8k
    igraph_vector_destroy(&excess);
1024
51.8k
    igraph_vector_destroy(&rescap);
1025
51.8k
    igraph_vector_int_destroy(&rev);
1026
51.8k
    igraph_vector_int_destroy(&to);
1027
51.8k
    igraph_dqueue_int_destroy(&bfsq);
1028
51.8k
    IGRAPH_FINALLY_CLEAN(10);
1029
1030
51.8k
    return IGRAPH_SUCCESS;
1031
51.8k
}
1032
1033
/**
1034
 * \function igraph_maxflow_value
1035
 * \brief Maximum flow in a network with the push/relabel algorithm.
1036
 *
1037
 * This function implements the Goldberg-Tarjan algorithm for
1038
 * calculating value of the maximum flow in a directed or undirected
1039
 * graph. The algorithm was given in Andrew V. Goldberg, Robert
1040
 * E. Tarjan: A New Approach to the Maximum-Flow Problem, Journal of
1041
 * the ACM, 35(4), 921-940, 1988
1042
 * https://doi.org/10.1145/48014.61051.
1043
 *
1044
 * </para><para>
1045
 * The input of the function is a graph, a vector
1046
 * of real numbers giving the capacity of the edges and two vertices
1047
 * of the graph, the source and the target. A flow is a function
1048
 * assigning positive real numbers to the edges and satisfying two
1049
 * requirements: (1) the flow value is less than the capacity of the
1050
 * edge and (2) at each vertex except the source and the target, the
1051
 * incoming flow (i.e. the sum of the flow on the incoming edges) is
1052
 * the same as the outgoing flow (i.e. the sum of the flow on the
1053
 * outgoing edges). The value of the flow is the incoming flow at the
1054
 * target vertex. The maximum flow is the flow with the maximum
1055
 * value.
1056
 *
1057
 * </para><para>
1058
 * According to a theorem by Ford and Fulkerson
1059
 * (L. R. Ford Jr. and D. R. Fulkerson. Maximal flow through a
1060
 * network. Canadian J. Math., 8:399-404, 1956.) the maximum flow
1061
 * between two vertices is the same as the
1062
 * minimum cut between them (also called the minimum s-t cut). So \ref
1063
 * igraph_st_mincut_value() gives the same result in all cases as \ref
1064
 * igraph_maxflow_value().
1065
 *
1066
 * </para><para>
1067
 * Note that the value of the maximum flow is the same as the
1068
 * minimum cut in the graph.
1069
 *
1070
 * \param graph The input graph, either directed or undirected.
1071
 * \param value Pointer to a real number, the result will be placed here.
1072
 * \param source The id of the source vertex.
1073
 * \param target The id of the target vertex.
1074
 * \param capacity Vector containing the capacity of the edges. If NULL, then
1075
 *        every edge is considered to have capacity 1.0.
1076
 * \param stats Counts of the number of different operations
1077
 *        preformed by the algorithm are stored here.
1078
 * \return Error code.
1079
 *
1080
 * Time complexity: O(|V|^3).
1081
 *
1082
 * \sa \ref igraph_maxflow() to calculate the actual flow.
1083
 * \ref igraph_mincut_value(), \ref igraph_edge_connectivity(),
1084
 * \ref igraph_vertex_connectivity() for
1085
 * properties based on the maximum flow.
1086
 */
1087
1088
igraph_error_t igraph_maxflow_value(const igraph_t *graph, igraph_real_t *value,
1089
                                    igraph_int_t source, igraph_int_t target,
1090
                                    const igraph_vector_t *capacity,
1091
51.8k
                                    igraph_maxflow_stats_t *stats) {
1092
1093
51.8k
    return igraph_maxflow(graph, value, /*flow=*/ NULL, /*cut=*/ NULL,
1094
51.8k
                          /*partition=*/ NULL, /*partition1=*/ NULL,
1095
51.8k
                          source, target, capacity, stats);
1096
51.8k
}
1097
1098
/**
1099
 * \function igraph_st_mincut_value
1100
 * \brief The minimum s-t cut in a graph.
1101
 *
1102
 * </para><para> The minimum s-t cut in a weighted (=valued) graph is the
1103
 * total minimum edge weight needed to remove from the graph to
1104
 * eliminate all paths from a given vertex (\p source) to
1105
 * another vertex (\p target). Directed paths are considered in
1106
 * directed graphs, and undirected paths in undirected graphs.  </para>
1107
 *
1108
 * <para> The minimum s-t cut between two vertices is known to be same
1109
 * as the maximum flow between these two vertices. So this function
1110
 * calls \ref igraph_maxflow_value() to do the calculation.
1111
 *
1112
 * \param graph The input graph.
1113
 * \param value Pointer to a real variable, the result will be stored
1114
 *        here.
1115
 * \param source The id of the source vertex.
1116
 * \param target The id of the target vertex.
1117
 * \param capacity Pointer to the capacity vector, it should contain
1118
 *        non-negative numbers and its length should be the same the
1119
 *        the number of edges in the graph. It can be a null pointer, then
1120
 *        every edge has unit capacity.
1121
 * \return Error code.
1122
 *
1123
 * Time complexity: O(|V|^3), see also the discussion for \ref
1124
 * igraph_maxflow_value(), |V| is the number of vertices.
1125
 */
1126
1127
igraph_error_t igraph_st_mincut_value(const igraph_t *graph, igraph_real_t *value,
1128
                                      igraph_int_t source, igraph_int_t target,
1129
0
                                      const igraph_vector_t *capacity) {
1130
1131
0
    if (source == target) {
1132
0
        IGRAPH_ERROR("source and target vertices are the same", IGRAPH_EINVAL);
1133
0
    }
1134
1135
0
    IGRAPH_CHECK(igraph_maxflow_value(graph, value, source, target, capacity, NULL));
1136
1137
0
    return IGRAPH_SUCCESS;
1138
0
}
1139
1140
/**
1141
 * \function igraph_st_mincut
1142
 * \brief Minimum cut between a source and a target vertex.
1143
 *
1144
 * Finds the edge set that has the smallest total capacity among all
1145
 * edge sets that disconnect the source and target vertices.
1146
 *
1147
 * </para><para>The calculation is performed using maximum flow
1148
 * techniques, by calling \ref igraph_maxflow().
1149
 *
1150
 * \param graph The input graph.
1151
 * \param value Pointer to a real variable, the value of the cut is
1152
 *        stored here.
1153
 * \param cut Pointer to an initialized vector, the edge IDs that are included
1154
 *        in the cut are stored here. This argument is ignored if it
1155
 *        is a null pointer.
1156
 * \param partition Pointer to an initialized vector, the vertex IDs of the
1157
 *        vertices in the first partition of the cut are stored
1158
 *        here. The first partition is always the one that contains the
1159
 *        source vertex. This argument is ignored if it is a null pointer.
1160
 * \param partition2 Pointer to an initialized vector, the vertex IDs of the
1161
 *        vertices in the second partition of the cut are stored here.
1162
 *        The second partition is always the one that contains the
1163
 *        target vertex. This argument is ignored if it is a null pointer.
1164
 * \param source Integer, the id of the source vertex.
1165
 * \param target Integer, the id of the target vertex.
1166
 * \param capacity Vector containing the capacity of the edges. If a
1167
 *        null pointer, then every edge is considered to have capacity
1168
 *        1.0.
1169
 * \return Error code.
1170
 *
1171
 * \sa \ref igraph_maxflow().
1172
 *
1173
 * Time complexity: see \ref igraph_maxflow().
1174
 */
1175
1176
igraph_error_t igraph_st_mincut(const igraph_t *graph, igraph_real_t *value,
1177
                                igraph_vector_int_t *cut, igraph_vector_int_t *partition,
1178
                                igraph_vector_int_t *partition2,
1179
                                igraph_int_t source, igraph_int_t target,
1180
0
                                const igraph_vector_t *capacity) {
1181
1182
0
    return igraph_maxflow(graph, value, /*flow=*/ NULL,
1183
0
                          cut, partition, partition2,
1184
0
                          source, target, capacity, NULL);
1185
0
}
1186
1187
/*
1188
 * This is the Stoer-Wagner algorithm, it works for calculating the
1189
 * minimum cut for undirected graphs, for the whole graph.
1190
 * I.e. this is basically the edge-connectivity of the graph.
1191
 * It can also calculate the cut itself, not just the cut value.
1192
 */
1193
1194
static igraph_error_t igraph_i_mincut_undirected(
1195
        const igraph_t *graph,
1196
        igraph_real_t *res,
1197
        igraph_vector_int_t *partition,
1198
        igraph_vector_int_t *partition2,
1199
        igraph_vector_int_t *cut,
1200
643
        const igraph_vector_t *capacity) {
1201
1202
643
    igraph_int_t no_of_nodes = igraph_vcount(graph);
1203
643
    igraph_int_t no_of_edges = igraph_ecount(graph);
1204
1205
643
    igraph_i_cutheap_t heap;
1206
643
    igraph_real_t mincut = IGRAPH_INFINITY; /* infinity */
1207
643
    igraph_int_t i;
1208
1209
643
    igraph_adjlist_t adjlist;
1210
643
    igraph_inclist_t inclist;
1211
1212
643
    igraph_vector_int_t mergehist;
1213
643
    igraph_bool_t calc_cut = partition || partition2 || cut;
1214
643
    igraph_int_t act_step = 0, mincut_step = 0;
1215
1216
643
    if (capacity && igraph_vector_size(capacity) != no_of_edges) {
1217
0
        IGRAPH_ERROR("Invalid capacity vector size", IGRAPH_EINVAL);
1218
0
    }
1219
1220
    /* Check if the graph is connected at all */
1221
643
    {
1222
643
        igraph_vector_int_t memb;
1223
643
        igraph_vector_int_t csize;
1224
643
        igraph_int_t no;
1225
643
        IGRAPH_VECTOR_INT_INIT_FINALLY(&memb, 0);
1226
643
        IGRAPH_VECTOR_INT_INIT_FINALLY(&csize, 0);
1227
643
        IGRAPH_CHECK(igraph_connected_components(graph, &memb, &csize, &no, IGRAPH_WEAK));
1228
643
        if (no != 1) {
1229
0
            if (res) {
1230
0
                *res = 0;
1231
0
            }
1232
0
            if (cut) {
1233
0
                igraph_vector_int_clear(cut);
1234
0
            }
1235
0
            if (partition) {
1236
0
                igraph_int_t j = 0;
1237
0
                IGRAPH_CHECK(igraph_vector_int_resize(partition,
1238
0
                                                      VECTOR(csize)[0]));
1239
0
                for (i = 0; i < no_of_nodes; i++) {
1240
0
                    if (VECTOR(memb)[i] == 0) {
1241
0
                        VECTOR(*partition)[j++] = i;
1242
0
                    }
1243
0
                }
1244
0
            }
1245
0
            if (partition2) {
1246
0
                igraph_int_t j = 0;
1247
0
                IGRAPH_CHECK(igraph_vector_int_resize(partition2, no_of_nodes -
1248
0
                                                      VECTOR(csize)[0]));
1249
0
                for (i = 0; i < no_of_nodes; i++) {
1250
0
                    if (VECTOR(memb)[i] != 0) {
1251
0
                        VECTOR(*partition2)[j++] = i;
1252
0
                    }
1253
0
                }
1254
0
            }
1255
0
        }
1256
643
        igraph_vector_int_destroy(&csize);
1257
643
        igraph_vector_int_destroy(&memb);
1258
643
        IGRAPH_FINALLY_CLEAN(2);
1259
1260
643
        if (no != 1) {
1261
0
            return IGRAPH_SUCCESS;
1262
0
        }
1263
643
    }
1264
1265
643
    if (calc_cut) {
1266
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&mergehist, 0);
1267
0
        IGRAPH_CHECK(igraph_vector_int_reserve(&mergehist, no_of_nodes * 2));
1268
0
    }
1269
1270
643
    IGRAPH_CHECK(igraph_i_cutheap_init(&heap, no_of_nodes));
1271
643
    IGRAPH_FINALLY(igraph_i_cutheap_destroy, &heap);
1272
1273
643
    IGRAPH_CHECK(igraph_inclist_init(graph, &inclist, IGRAPH_OUT, IGRAPH_LOOPS_ONCE));
1274
643
    IGRAPH_FINALLY(igraph_inclist_destroy, &inclist);
1275
1276
643
    IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE));
1277
643
    IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist);
1278
1279
38.5k
    while (igraph_i_cutheap_size(&heap) >= 2) {
1280
1281
37.9k
        igraph_int_t last;
1282
37.9k
        igraph_real_t acut;
1283
37.9k
        igraph_int_t a, n;
1284
1285
37.9k
        igraph_vector_int_t *edges, *edges2;
1286
37.9k
        igraph_vector_int_t *neis, *neis2;
1287
1288
3.73M
        do {
1289
3.73M
            a = igraph_i_cutheap_popmax(&heap);
1290
1291
            /* update the weights of the active vertices connected to a */
1292
3.73M
            edges = igraph_inclist_get(&inclist, a);
1293
3.73M
            neis = igraph_adjlist_get(&adjlist, a);
1294
3.73M
            n = igraph_vector_int_size(edges);
1295
181M
            for (i = 0; i < n; i++) {
1296
177M
                igraph_int_t edge = VECTOR(*edges)[i];
1297
177M
                igraph_int_t to = VECTOR(*neis)[i];
1298
177M
                igraph_real_t weight = capacity ? VECTOR(*capacity)[edge] : 1.0;
1299
177M
                igraph_i_cutheap_update(&heap, to, weight);
1300
177M
            }
1301
1302
3.73M
        } while (igraph_i_cutheap_active_size(&heap) > 1);
1303
1304
        /* Now, there is only one active vertex left,
1305
           calculate the cut of the phase */
1306
37.9k
        acut = igraph_i_cutheap_maxvalue(&heap);
1307
37.9k
        last = igraph_i_cutheap_popmax(&heap);
1308
1309
37.9k
        if (acut < mincut) {
1310
741
            mincut = acut;
1311
741
            mincut_step = act_step;
1312
741
        }
1313
1314
37.9k
        if (mincut == 0) {
1315
0
            break;
1316
0
        }
1317
1318
        /* And contract the last and the remaining vertex (a and last) */
1319
        /* Before actually doing that, make some notes */
1320
37.9k
        act_step++;
1321
37.9k
        if (calc_cut) {
1322
0
            IGRAPH_CHECK(igraph_vector_int_push_back(&mergehist, a));
1323
0
            IGRAPH_CHECK(igraph_vector_int_push_back(&mergehist, last));
1324
0
        }
1325
        /* First remove the a--last edge if there is one, a is still the
1326
           last deactivated vertex */
1327
37.9k
        edges = igraph_inclist_get(&inclist, a);
1328
37.9k
        neis = igraph_adjlist_get(&adjlist, a);
1329
37.9k
        n = igraph_vector_int_size(edges);
1330
2.58M
        for (i = 0; i < n; ) {
1331
2.54M
            if (VECTOR(*neis)[i] == last) {
1332
381k
                VECTOR(*neis)[i] = VECTOR(*neis)[n - 1];
1333
381k
                VECTOR(*edges)[i] = VECTOR(*edges)[n - 1];
1334
381k
                igraph_vector_int_pop_back(neis);
1335
381k
                igraph_vector_int_pop_back(edges);
1336
381k
                n--;
1337
2.16M
            } else {
1338
2.16M
                i++;
1339
2.16M
            }
1340
2.54M
        }
1341
1342
37.9k
        edges = igraph_inclist_get(&inclist, last);
1343
37.9k
        neis = igraph_adjlist_get(&adjlist, last);
1344
37.9k
        n = igraph_vector_int_size(edges);
1345
2.49M
        for (i = 0; i < n; ) {
1346
2.45M
            if (VECTOR(*neis)[i] == a) {
1347
381k
                VECTOR(*neis)[i] = VECTOR(*neis)[n - 1];
1348
381k
                VECTOR(*edges)[i] = VECTOR(*edges)[n - 1];
1349
381k
                igraph_vector_int_pop_back(neis);
1350
381k
                igraph_vector_int_pop_back(edges);
1351
381k
                n--;
1352
2.07M
            } else {
1353
2.07M
                i++;
1354
2.07M
            }
1355
2.45M
        }
1356
1357
        /* Now rewrite the edge lists of last's neighbors */
1358
37.9k
        neis = igraph_adjlist_get(&adjlist, last);
1359
37.9k
        n = igraph_vector_int_size(neis);
1360
2.10M
        for (i = 0; i < n; i++) {
1361
2.07M
            igraph_int_t nei = VECTOR(*neis)[i];
1362
2.07M
            igraph_int_t n2, j;
1363
2.07M
            neis2 = igraph_adjlist_get(&adjlist, nei);
1364
2.07M
            n2 = igraph_vector_int_size(neis2);
1365
2.46G
            for (j = 0; j < n2; j++) {
1366
2.45G
                if (VECTOR(*neis2)[j] == last) {
1367
2.07M
                    VECTOR(*neis2)[j] = a;
1368
2.07M
                }
1369
2.45G
            }
1370
2.07M
        }
1371
1372
        /* And append the lists of last to the lists of a */
1373
37.9k
        edges = igraph_inclist_get(&inclist, a);
1374
37.9k
        neis = igraph_adjlist_get(&adjlist, a);
1375
37.9k
        edges2 = igraph_inclist_get(&inclist, last);
1376
37.9k
        neis2 = igraph_adjlist_get(&adjlist, last);
1377
37.9k
        IGRAPH_CHECK(igraph_vector_int_append(edges, edges2));
1378
37.9k
        IGRAPH_CHECK(igraph_vector_int_append(neis, neis2));
1379
37.9k
        igraph_vector_int_clear(edges2); /* TODO: free it */
1380
37.9k
        igraph_vector_int_clear(neis2);  /* TODO: free it */
1381
1382
        /* Remove the deleted vertex from the heap entirely */
1383
37.9k
        igraph_i_cutheap_reset_undefine(&heap, last);
1384
37.9k
    }
1385
1386
643
    *res = mincut;
1387
1388
643
    igraph_inclist_destroy(&inclist);
1389
643
    igraph_adjlist_destroy(&adjlist);
1390
643
    igraph_i_cutheap_destroy(&heap);
1391
643
    IGRAPH_FINALLY_CLEAN(3);
1392
1393
643
    if (calc_cut) {
1394
0
        igraph_int_t bignode = VECTOR(mergehist)[2 * mincut_step + 1];
1395
0
        igraph_int_t i, idx;
1396
0
        igraph_int_t size = 1;
1397
0
        igraph_bitset_t mark;
1398
1399
0
        IGRAPH_BITSET_INIT_FINALLY(&mark, no_of_nodes);
1400
1401
        /* first count the vertices in the partition */
1402
0
        IGRAPH_BIT_SET(mark, bignode);
1403
0
        for (i = mincut_step - 1; i >= 0; i--) {
1404
0
            if ( IGRAPH_BIT_TEST(mark, VECTOR(mergehist)[2 * i]) ) {
1405
0
                size++;
1406
0
                IGRAPH_BIT_SET(mark, VECTOR(mergehist)[2 * i + 1]);
1407
0
            }
1408
0
        }
1409
1410
        /* now store them, if requested */
1411
0
        if (partition) {
1412
0
            IGRAPH_CHECK(igraph_vector_int_resize(partition, size));
1413
0
            idx = 0;
1414
0
            VECTOR(*partition)[idx++] = bignode;
1415
0
            for (i = mincut_step - 1; i >= 0; i--) {
1416
0
                if (IGRAPH_BIT_TEST(mark, VECTOR(mergehist)[2 * i])) {
1417
0
                    VECTOR(*partition)[idx++] = VECTOR(mergehist)[2 * i + 1];
1418
0
                }
1419
0
            }
1420
0
        }
1421
1422
        /* The other partition too? */
1423
0
        if (partition2) {
1424
0
            IGRAPH_CHECK(igraph_vector_int_resize(partition2, no_of_nodes - size));
1425
0
            idx = 0;
1426
0
            for (i = 0; i < no_of_nodes; i++) {
1427
0
                if (!IGRAPH_BIT_TEST(mark, i)) {
1428
0
                    VECTOR(*partition2)[idx++] = i;
1429
0
                }
1430
0
            }
1431
0
        }
1432
1433
        /* The edges in the cut are also requested? */
1434
        /* We want as few memory allocated for 'cut' as possible,
1435
           so we first collect the edges in mergehist, we don't
1436
           need that anymore. Then we copy it to 'cut';  */
1437
0
        if (cut) {
1438
0
            igraph_int_t from, to;
1439
0
            igraph_vector_int_clear(&mergehist);
1440
0
            for (i = 0; i < no_of_edges; i++) {
1441
0
                igraph_edge(graph, i, &from, &to);
1442
0
                if ((IGRAPH_BIT_TEST(mark, from) && !IGRAPH_BIT_TEST(mark, to)) ||
1443
0
                    (IGRAPH_BIT_TEST(mark, to) && !IGRAPH_BIT_TEST(mark, from))) {
1444
0
                    IGRAPH_CHECK(igraph_vector_int_push_back(&mergehist, i));
1445
0
                }
1446
0
            }
1447
0
            igraph_vector_int_clear(cut);
1448
0
            IGRAPH_CHECK(igraph_vector_int_append(cut, &mergehist));
1449
0
        }
1450
1451
0
        igraph_bitset_destroy(&mark);
1452
0
        igraph_vector_int_destroy(&mergehist);
1453
0
        IGRAPH_FINALLY_CLEAN(2);
1454
0
    }
1455
1456
643
    return IGRAPH_SUCCESS;
1457
643
}
1458
1459
static igraph_error_t igraph_i_mincut_directed(
1460
        const igraph_t *graph,
1461
        igraph_real_t *value,
1462
        igraph_vector_int_t *partition,
1463
        igraph_vector_int_t *partition2,
1464
        igraph_vector_int_t *cut,
1465
0
        const igraph_vector_t *capacity) {
1466
1467
0
    igraph_int_t i;
1468
0
    igraph_int_t no_of_nodes = igraph_vcount(graph);
1469
0
    igraph_real_t flow;
1470
0
    igraph_real_t minmaxflow = IGRAPH_INFINITY;
1471
0
    igraph_vector_int_t mypartition, mypartition2, mycut;
1472
0
    igraph_vector_int_t *ppartition = NULL, *ppartition2 = NULL, *pcut = NULL;
1473
0
    igraph_vector_int_t bestpartition, bestpartition2, bestcut;
1474
1475
0
    if (partition) {
1476
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&bestpartition, 0);
1477
0
    }
1478
0
    if (partition2) {
1479
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&bestpartition2, 0);
1480
0
    }
1481
0
    if (cut) {
1482
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&bestcut, 0);
1483
0
    }
1484
1485
0
    if (partition) {
1486
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&mypartition, 0);
1487
0
        ppartition = &mypartition;
1488
0
    }
1489
0
    if (partition2) {
1490
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&mypartition2, 0);
1491
0
        ppartition2 = &mypartition2;
1492
0
    }
1493
0
    if (cut) {
1494
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&mycut, 0);
1495
0
        pcut = &mycut;
1496
0
    }
1497
1498
0
    for (i = 1; i < no_of_nodes; i++) {
1499
0
        IGRAPH_CHECK(igraph_maxflow(graph, /*value=*/ &flow, /*flow=*/ NULL,
1500
0
                                    pcut, ppartition, ppartition2, /*source=*/ 0,
1501
0
                                    /*target=*/ i, capacity, NULL));
1502
0
        if (flow < minmaxflow) {
1503
0
            minmaxflow = flow;
1504
0
            if (cut) {
1505
0
                IGRAPH_CHECK(igraph_vector_int_update(&bestcut, &mycut));
1506
0
            }
1507
0
            if (partition) {
1508
0
                IGRAPH_CHECK(igraph_vector_int_update(&bestpartition, &mypartition));
1509
0
            }
1510
0
            if (partition2) {
1511
0
                IGRAPH_CHECK(igraph_vector_int_update(&bestpartition2, &mypartition2));
1512
0
            }
1513
1514
0
            if (minmaxflow == 0) {
1515
0
                break;
1516
0
            }
1517
0
        }
1518
0
        IGRAPH_CHECK(igraph_maxflow(graph, /*value=*/ &flow, /*flow=*/ NULL,
1519
0
                                    pcut, ppartition, ppartition2,
1520
0
                                    /*source=*/ i,
1521
0
                                    /*target=*/ 0, capacity, NULL));
1522
0
        if (flow < minmaxflow) {
1523
0
            minmaxflow = flow;
1524
0
            if (cut) {
1525
0
                IGRAPH_CHECK(igraph_vector_int_update(&bestcut, &mycut));
1526
0
            }
1527
0
            if (partition) {
1528
0
                IGRAPH_CHECK(igraph_vector_int_update(&bestpartition, &mypartition));
1529
0
            }
1530
0
            if (partition2) {
1531
0
                IGRAPH_CHECK(igraph_vector_int_update(&bestpartition2, &mypartition2));
1532
0
            }
1533
1534
0
            if (minmaxflow == 0) {
1535
0
                break;
1536
0
            }
1537
0
        }
1538
0
    }
1539
1540
0
    if (value) {
1541
0
        *value = minmaxflow;
1542
0
    }
1543
1544
0
    if (cut) {
1545
0
        igraph_vector_int_destroy(&mycut);
1546
0
        IGRAPH_FINALLY_CLEAN(1);
1547
0
    }
1548
0
    if (partition) {
1549
0
        igraph_vector_int_destroy(&mypartition);
1550
0
        IGRAPH_FINALLY_CLEAN(1);
1551
0
    }
1552
0
    if (partition2) {
1553
0
        igraph_vector_int_destroy(&mypartition2);
1554
0
        IGRAPH_FINALLY_CLEAN(1);
1555
0
    }
1556
0
    if (cut) {
1557
0
        IGRAPH_CHECK(igraph_vector_int_update(cut, &bestcut));
1558
0
        igraph_vector_int_destroy(&bestcut);
1559
0
        IGRAPH_FINALLY_CLEAN(1);
1560
0
    }
1561
0
    if (partition2) {
1562
0
        IGRAPH_CHECK(igraph_vector_int_update(partition2, &bestpartition2));
1563
0
        igraph_vector_int_destroy(&bestpartition2);
1564
0
        IGRAPH_FINALLY_CLEAN(1);
1565
0
    }
1566
0
    if (partition) {
1567
0
        IGRAPH_CHECK(igraph_vector_int_update(partition, &bestpartition));
1568
0
        igraph_vector_int_destroy(&bestpartition);
1569
0
        IGRAPH_FINALLY_CLEAN(1);
1570
0
    }
1571
1572
0
    return IGRAPH_SUCCESS;
1573
0
}
1574
1575
/**
1576
 * \function igraph_mincut
1577
 * \brief Calculates the minimum cut in a graph.
1578
 *
1579
 * This function calculates the minimum cut in a graph.
1580
 * The minimum cut is the minimum set of edges which needs to be
1581
 * removed to disconnect the graph. The minimum is calculated using
1582
 * the weights (\p capacity) of the edges, so the cut with the minimum
1583
 * total capacity is calculated.
1584
 *
1585
 * </para><para> For directed graphs an implementation based on
1586
 * calculating 2|V|-2 maximum flows is used.
1587
 * For undirected graphs we use the Stoer-Wagner
1588
 * algorithm, as described in M. Stoer and F. Wagner: A simple min-cut
1589
 * algorithm, Journal of the ACM, 44 585-591, 1997.
1590
 *
1591
 * </para><para>
1592
 * The first implementation of the actual cut calculation for
1593
 * undirected graphs was made by Gregory Benison, thanks Greg.
1594
 *
1595
 * \param graph The input graph.
1596
 * \param value Pointer to a float, the value of the cut will be
1597
 *    stored here.
1598
 * \param partition Pointer to an initialized vector, the ids
1599
 *    of the vertices in the first partition after separating the
1600
 *    graph will be stored here. The vector will be resized as
1601
 *    needed. This argument is ignored if it is a NULL pointer.
1602
 * \param partition2 Pointer to an initialized vector the ids
1603
 *    of the vertices in the second partition will be stored here.
1604
 *    The vector will be resized as needed. This argument is ignored
1605
 *    if it is a NULL pointer.
1606
 * \param cut Pointer to an initialized vector, the IDs of the edges
1607
 *    in the cut will be stored here. This argument is ignored if it
1608
 *    is a NULL pointer.
1609
 * \param capacity A numeric vector giving the capacities of the
1610
 *    edges. If a null pointer then all edges have unit capacity.
1611
 * \return Error code.
1612
 *
1613
 * \sa \ref igraph_mincut_value(), a simpler interface for calculating
1614
 * the value of the cut only.
1615
 *
1616
 * Time complexity: for directed graphs it is O(|V|^4), but see the
1617
 * remarks at \ref igraph_maxflow(). For undirected graphs it is
1618
 * O(|V||E|+|V|^2 log|V|). |V| and |E| are the number of vertices and
1619
 * edges respectively.
1620
 *
1621
 * \example examples/simple/igraph_mincut.c
1622
 */
1623
1624
igraph_error_t igraph_mincut(const igraph_t *graph,
1625
                             igraph_real_t *value,
1626
                             igraph_vector_int_t *partition,
1627
                             igraph_vector_int_t *partition2,
1628
                             igraph_vector_int_t *cut,
1629
0
                             const igraph_vector_t *capacity) {
1630
1631
0
    if (igraph_is_directed(graph)) {
1632
0
        if (partition || partition2 || cut) {
1633
0
            igraph_i_mincut_directed(graph, value, partition, partition2, cut,
1634
0
                                     capacity);
1635
0
        } else {
1636
0
            return igraph_mincut_value(graph, value, capacity);
1637
0
        }
1638
0
    } else {
1639
0
        IGRAPH_CHECK(igraph_i_mincut_undirected(graph, value, partition,
1640
0
                                                partition2, cut, capacity));
1641
0
        return IGRAPH_SUCCESS;
1642
0
    }
1643
1644
0
    return IGRAPH_SUCCESS;
1645
0
}
1646
1647
1648
static igraph_error_t igraph_i_mincut_value_undirected(
1649
        const igraph_t *graph,
1650
        igraph_real_t *res,
1651
643
        const igraph_vector_t *capacity) {
1652
643
    return igraph_i_mincut_undirected(graph, res, 0, 0, 0, capacity);
1653
643
}
1654
1655
/**
1656
 * \function igraph_mincut_value
1657
 * \brief The minimum edge cut in a graph.
1658
 *
1659
 * </para><para> The minimum edge cut in a graph is the total minimum
1660
 * weight of the edges needed to remove from the graph to make the
1661
 * graph \em not strongly connected. (If the original graph is not
1662
 * strongly connected then this is zero.) Note that in undirected
1663
 * graphs strong connectedness is the same as weak connectedness. </para>
1664
 *
1665
 * <para> The minimum cut can be calculated with maximum flow
1666
 * techniques, although the current implementation does this only for
1667
 * directed graphs and a separate non-flow based implementation is
1668
 * used for undirected graphs. See Mechthild Stoer and Frank Wagner: A
1669
 * simple min-cut algorithm, Journal of the ACM 44 585--591, 1997.
1670
 * For directed graphs
1671
 * the maximum flow is calculated between a fixed vertex and all the
1672
 * other vertices in the graph and this is done in both
1673
 * directions. Then the minimum is taken to get the minimum cut.
1674
 *
1675
 * \param graph The input graph.
1676
 * \param res Pointer to a real variable, the result will be stored
1677
 *    here.
1678
 * \param capacity Pointer to the capacity vector, it should contain
1679
 *    the same number of non-negative numbers as the number of edges in
1680
 *    the graph. If a null pointer then all edges will have unit capacity.
1681
 * \return Error code.
1682
 *
1683
 * \sa \ref igraph_mincut(), \ref igraph_maxflow_value(), \ref
1684
 * igraph_st_mincut_value().
1685
 *
1686
 * Time complexity: O(log(|V|)*|V|^2) for undirected graphs and
1687
 * O(|V|^4) for directed graphs, but see also the discussion at the
1688
 * documentation of \ref igraph_maxflow_value().
1689
 */
1690
1691
igraph_error_t igraph_mincut_value(const igraph_t *graph, igraph_real_t *res,
1692
1.05k
                                   const igraph_vector_t *capacity) {
1693
1694
1.05k
    igraph_int_t no_of_nodes = igraph_vcount(graph);
1695
1.05k
    igraph_real_t minmaxflow, flow;
1696
1.05k
    igraph_int_t i;
1697
1698
1.05k
    minmaxflow = IGRAPH_INFINITY;
1699
1700
1.05k
    if (!igraph_is_directed(graph)) {
1701
643
        IGRAPH_CHECK(igraph_i_mincut_value_undirected(graph, res, capacity));
1702
643
        return IGRAPH_SUCCESS;
1703
643
    }
1704
1705
26.3k
    for (i = 1; i < no_of_nodes; i++) {
1706
25.9k
        IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, 0, i,
1707
25.9k
                                          capacity, NULL));
1708
25.9k
        if (flow < minmaxflow) {
1709
790
            minmaxflow = flow;
1710
790
            if (flow == 0) {
1711
0
                break;
1712
0
            }
1713
790
        }
1714
25.9k
        IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, i, 0,
1715
25.9k
                                          capacity, NULL));
1716
25.9k
        if (flow < minmaxflow) {
1717
409
            minmaxflow = flow;
1718
409
            if (flow == 0) {
1719
0
                break;
1720
0
            }
1721
409
        }
1722
25.9k
    }
1723
1724
416
    if (res) {
1725
416
        *res = minmaxflow;
1726
416
    }
1727
1728
416
    return IGRAPH_SUCCESS;
1729
416
}
1730
1731
static igraph_error_t igraph_i_st_vertex_connectivity_check_errors(
1732
        const igraph_t *graph,
1733
        igraph_int_t *res,
1734
        igraph_int_t source,
1735
        igraph_int_t target,
1736
        igraph_vconn_nei_t neighbors,
1737
        igraph_bool_t *done,
1738
0
        igraph_int_t *no_conn) {
1739
1740
0
    igraph_int_t no_of_nodes = igraph_vcount(graph);
1741
0
    igraph_int_t eid;
1742
0
    igraph_bool_t conn;
1743
0
    *done = true;
1744
0
    *no_conn = 0;
1745
1746
0
    if (source == target) {
1747
0
        IGRAPH_ERROR("Source and target vertices are the same.", IGRAPH_EINVAL);
1748
0
    }
1749
1750
0
    if (source < 0 || source >= no_of_nodes || target < 0 || target >= no_of_nodes) {
1751
0
        IGRAPH_ERROR("Invalid source or target vertex.", IGRAPH_EINVAL);
1752
0
    }
1753
1754
0
    switch (neighbors) {
1755
0
    case IGRAPH_VCONN_NEI_ERROR:
1756
0
        IGRAPH_CHECK(igraph_are_adjacent(graph, source, target, &conn));
1757
0
        if (conn) {
1758
0
            IGRAPH_ERROR("Source and target vertices connected.", IGRAPH_EINVAL);
1759
0
        }
1760
0
        break;
1761
0
    case IGRAPH_VCONN_NEI_NEGATIVE:
1762
0
        IGRAPH_CHECK(igraph_are_adjacent(graph, source, target, &conn));
1763
0
        if (conn) {
1764
0
            *res = -1;
1765
0
            return IGRAPH_SUCCESS;
1766
0
        }
1767
0
        break;
1768
0
    case IGRAPH_VCONN_NEI_NUMBER_OF_NODES:
1769
0
        IGRAPH_CHECK(igraph_are_adjacent(graph, source, target, &conn));
1770
0
        if (conn) {
1771
0
            *res = no_of_nodes;
1772
0
            return IGRAPH_SUCCESS;
1773
0
        }
1774
0
        break;
1775
0
    case IGRAPH_VCONN_NEI_IGNORE:
1776
0
        IGRAPH_CHECK(igraph_get_eid(graph, &eid, source, target, IGRAPH_DIRECTED, /*error=*/ false));
1777
0
        if (eid >= 0) {
1778
0
            IGRAPH_CHECK(igraph_count_multiple_1(graph, no_conn, eid));
1779
0
        }
1780
0
        break;
1781
0
    default:
1782
0
        IGRAPH_ERROR("Unknown `igraph_vconn_nei_t'.", IGRAPH_EINVAL);
1783
0
        break;
1784
0
    }
1785
0
    *done = false;
1786
0
    return IGRAPH_SUCCESS;
1787
0
}
1788
1789
static igraph_error_t igraph_i_st_vertex_connectivity_directed(
1790
        const igraph_t *graph,
1791
        igraph_int_t *res,
1792
        igraph_int_t source,
1793
        igraph_int_t target,
1794
0
        igraph_vconn_nei_t neighbors) {
1795
1796
0
    igraph_int_t no_of_nodes = igraph_vcount(graph);
1797
0
    igraph_int_t no_of_edges;
1798
0
    igraph_real_t real_res;
1799
0
    igraph_t newgraph;
1800
0
    igraph_int_t i, len;
1801
0
    igraph_bool_t done;
1802
0
    igraph_int_t no_conn;
1803
0
    igraph_vector_int_t incs;
1804
0
    igraph_vector_t capacity;
1805
1806
0
    IGRAPH_CHECK(igraph_i_st_vertex_connectivity_check_errors(graph, res, source, target, neighbors, &done, &no_conn));
1807
0
    if (done) {
1808
0
        return IGRAPH_SUCCESS;
1809
0
    }
1810
1811
    /* Create the new graph */
1812
0
    IGRAPH_CHECK(igraph_i_split_vertices(graph, &newgraph));
1813
0
    IGRAPH_FINALLY(igraph_destroy, &newgraph);
1814
1815
    /* Create the capacity vector, fill it with ones */
1816
0
    no_of_edges = igraph_ecount(&newgraph);
1817
0
    IGRAPH_VECTOR_INIT_FINALLY(&capacity, no_of_edges);
1818
0
    igraph_vector_fill(&capacity, 1);
1819
1820
    /* "Disable" the edges incident on the input half of the source vertex
1821
     * and the output half of the target vertex */
1822
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(&incs, 0);
1823
0
    IGRAPH_CHECK(igraph_incident(&newgraph, &incs, source + no_of_nodes, IGRAPH_ALL, IGRAPH_LOOPS));
1824
0
    len = igraph_vector_int_size(&incs);
1825
0
    for (i = 0; i < len; i++) {
1826
0
        VECTOR(capacity)[VECTOR(incs)[i]] = 0;
1827
0
    }
1828
0
    IGRAPH_CHECK(igraph_incident(&newgraph, &incs, target, IGRAPH_ALL, IGRAPH_LOOPS));
1829
0
    len = igraph_vector_int_size(&incs);
1830
0
    for (i = 0; i < len; i++) {
1831
0
        VECTOR(capacity)[VECTOR(incs)[i]] = 0;
1832
0
    }
1833
0
    igraph_vector_int_destroy(&incs);
1834
0
    IGRAPH_FINALLY_CLEAN(1);
1835
1836
    /* Do the maximum flow */
1837
0
    IGRAPH_CHECK(igraph_maxflow_value(&newgraph, &real_res,
1838
0
                                      source, target + no_of_nodes, &capacity, NULL));
1839
0
    *res = (igraph_int_t) real_res;
1840
1841
0
    *res -= no_conn;
1842
1843
0
    igraph_vector_destroy(&capacity);
1844
0
    igraph_destroy(&newgraph);
1845
0
    IGRAPH_FINALLY_CLEAN(2);
1846
1847
0
    return IGRAPH_SUCCESS;
1848
0
}
1849
1850
static igraph_error_t igraph_i_st_vertex_connectivity_undirected(
1851
        const igraph_t *graph,
1852
        igraph_int_t *res,
1853
        igraph_int_t source,
1854
        igraph_int_t target,
1855
0
        igraph_vconn_nei_t neighbors) {
1856
1857
0
    igraph_t newgraph;
1858
0
    igraph_bool_t done;
1859
0
    igraph_int_t no_conn;
1860
1861
0
    IGRAPH_CHECK(igraph_i_st_vertex_connectivity_check_errors(graph, res, source, target, neighbors, &done, &no_conn));
1862
0
    if (done) {
1863
0
        return IGRAPH_SUCCESS;
1864
0
    }
1865
1866
0
    IGRAPH_CHECK(igraph_copy(&newgraph, graph));
1867
0
    IGRAPH_FINALLY(igraph_destroy, &newgraph);
1868
0
    IGRAPH_CHECK(igraph_to_directed(&newgraph, IGRAPH_TO_DIRECTED_MUTUAL));
1869
1870
0
    IGRAPH_CHECK(igraph_i_st_vertex_connectivity_directed(&newgraph, res,
1871
0
                 source, target,
1872
0
                 IGRAPH_VCONN_NEI_IGNORE));
1873
1874
0
    igraph_destroy(&newgraph);
1875
0
    IGRAPH_FINALLY_CLEAN(1);
1876
1877
0
    return IGRAPH_SUCCESS;
1878
0
}
1879
1880
/**
1881
 * \function igraph_st_vertex_connectivity
1882
 * \brief The vertex connectivity of a pair of vertices.
1883
 *
1884
 * The vertex connectivity of two vertices (\p source and
1885
 * \p target) is the minimum number of vertices that must be
1886
 * deleted to eliminate all paths from \p source to \p
1887
 * target. Directed paths are considered in directed graphs.
1888
 *
1889
 * </para><para>
1890
 * The vertex connectivity of a pair is the same as the number
1891
 * of different (i.e. node-independent) paths from source to
1892
 * target, assuming no direct edges between them.
1893
 *
1894
 * </para><para>
1895
 * The current implementation uses maximum flow calculations to
1896
 * obtain the result.
1897
 *
1898
 * \param graph The input graph.
1899
 * \param res Pointer to an integer, the result will be stored here.
1900
 * \param source The id of the source vertex.
1901
 * \param target The id of the target vertex.
1902
 * \param neighbors A constant giving what to do if the two vertices
1903
 *     are connected. Possible values:
1904
 *     \c IGRAPH_VCONN_NEI_ERROR, stop with an error message,
1905
 *     \c IGRAPH_VCONN_NEI_NEGATIVE, return -1.
1906
 *     \c IGRAPH_VCONN_NEI_NUMBER_OF_NODES, return the number of nodes.
1907
 *     \c IGRAPH_VCONN_NEI_IGNORE, ignore the fact that the two vertices
1908
 *        are connected and calculate the number of vertices needed
1909
 *        to eliminate all paths except for the trivial (direct) paths
1910
 *        between \p source and \p vertex.
1911
 * \return Error code.
1912
 *
1913
 * Time complexity: O(|V|^3), but see the discussion at \ref
1914
 * igraph_maxflow_value().
1915
 *
1916
 * \sa \ref igraph_vertex_connectivity(),
1917
 * \ref igraph_edge_connectivity(),
1918
 * \ref igraph_maxflow_value().
1919
 */
1920
1921
igraph_error_t igraph_st_vertex_connectivity(
1922
        const igraph_t *graph,
1923
        igraph_int_t *res,
1924
        igraph_int_t source,
1925
        igraph_int_t target,
1926
0
        igraph_vconn_nei_t neighbors) {
1927
1928
0
    if (igraph_is_directed(graph)) {
1929
0
        IGRAPH_CHECK(igraph_i_st_vertex_connectivity_directed(graph, res,
1930
0
                     source, target,
1931
0
                     neighbors));
1932
0
    } else {
1933
0
        IGRAPH_CHECK(igraph_i_st_vertex_connectivity_undirected(graph, res,
1934
0
                     source, target,
1935
0
                     neighbors));
1936
0
    }
1937
1938
0
    return IGRAPH_SUCCESS;
1939
0
}
1940
1941
static igraph_error_t igraph_i_vertex_connectivity_directed(
1942
        const igraph_t *graph,
1943
        igraph_int_t *res,
1944
0
        igraph_bool_t all_edges_are_mutual) {
1945
1946
0
    igraph_int_t no_of_nodes = igraph_vcount(graph);
1947
0
    igraph_int_t no_of_edges;
1948
0
    igraph_int_t i, j, k, len;
1949
0
    igraph_int_t minconn = no_of_nodes - 1, conn = 0;
1950
0
    igraph_t split_graph;
1951
0
    igraph_vector_t capacity;
1952
0
    igraph_bool_t done;
1953
0
    igraph_int_t dummy_num_connections;
1954
0
    igraph_vector_int_t incs;
1955
0
    igraph_real_t real_res;
1956
1957
    /* Create the new graph */
1958
0
    IGRAPH_CHECK(igraph_i_split_vertices(graph, &split_graph));
1959
0
    IGRAPH_FINALLY(igraph_destroy, &split_graph);
1960
1961
    /* Create the capacity vector, fill it with ones */
1962
0
    no_of_edges = igraph_ecount(&split_graph);
1963
0
    IGRAPH_VECTOR_INIT_FINALLY(&capacity, no_of_edges);
1964
0
    igraph_vector_fill(&capacity, 1);
1965
1966
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(&incs, 0);
1967
1968
0
    for (i = 0; i < no_of_nodes; i++) {
1969
0
        for (j = all_edges_are_mutual ? i + 1 : 0; j < no_of_nodes; j++) {
1970
0
            if (i == j) {
1971
0
                continue;
1972
0
            }
1973
1974
0
            IGRAPH_ALLOW_INTERRUPTION();
1975
1976
            /* Check for easy cases */
1977
0
            IGRAPH_CHECK(igraph_i_st_vertex_connectivity_check_errors(
1978
0
                             graph, &conn, i, j, IGRAPH_VCONN_NEI_NUMBER_OF_NODES, &done,
1979
0
                             &dummy_num_connections
1980
0
                         ));
1981
1982
            /* 'done' will be set to true if the two vertices are already
1983
             * connected, and in this case 'res' will be set to the number of
1984
             * nodes-1.
1985
             *
1986
             * Also, since we used IGRAPH_VCONN_NEI_NUMBER_OF_NODES,
1987
             * dummy_num_connections will always be zero, no need to deal with
1988
             * it */
1989
0
            IGRAPH_ASSERT(dummy_num_connections == 0);
1990
1991
0
            if (!done) {
1992
                /* "Disable" the edges incident on the input half of the source vertex
1993
                * and the output half of the target vertex */
1994
0
                IGRAPH_CHECK(igraph_incident(&split_graph, &incs, i + no_of_nodes, IGRAPH_ALL, IGRAPH_LOOPS));
1995
0
                len = igraph_vector_int_size(&incs);
1996
0
                for (k = 0; k < len; k++) {
1997
0
                    VECTOR(capacity)[VECTOR(incs)[k]] = 0;
1998
0
                }
1999
0
                IGRAPH_CHECK(igraph_incident(&split_graph, &incs, j, IGRAPH_ALL, IGRAPH_LOOPS));
2000
0
                len = igraph_vector_int_size(&incs);
2001
0
                for (k = 0; k < len; k++) {
2002
0
                    VECTOR(capacity)[VECTOR(incs)[k]] = 0;
2003
0
                }
2004
2005
                /* Do the maximum flow */
2006
0
                IGRAPH_CHECK(igraph_maxflow_value(
2007
0
                                 &split_graph, &real_res, i, j + no_of_nodes, &capacity, NULL
2008
0
                             ));
2009
2010
                /* Restore the capacities */
2011
0
                IGRAPH_CHECK(igraph_incident(&split_graph, &incs, i + no_of_nodes, IGRAPH_ALL, IGRAPH_LOOPS));
2012
0
                len = igraph_vector_int_size(&incs);
2013
0
                for (k = 0; k < len; k++) {
2014
0
                    VECTOR(capacity)[VECTOR(incs)[k]] = 1;
2015
0
                }
2016
0
                IGRAPH_CHECK(igraph_incident(&split_graph, &incs, j, IGRAPH_ALL, IGRAPH_LOOPS));
2017
0
                len = igraph_vector_int_size(&incs);
2018
0
                for (k = 0; k < len; k++) {
2019
0
                    VECTOR(capacity)[VECTOR(incs)[k]] = 1;
2020
0
                }
2021
2022
0
                conn = (igraph_int_t) real_res;
2023
0
            }
2024
2025
0
            if (conn < minconn) {
2026
0
                minconn = conn;
2027
0
                if (conn == 0) {
2028
0
                    break;
2029
0
                }
2030
0
            }
2031
0
        }
2032
2033
0
        if (minconn == 0) {
2034
0
            break;
2035
0
        }
2036
0
    }
2037
2038
0
    if (res) {
2039
0
        *res = minconn;
2040
0
    }
2041
2042
0
    igraph_vector_int_destroy(&incs);
2043
0
    igraph_vector_destroy(&capacity);
2044
0
    igraph_destroy(&split_graph);
2045
0
    IGRAPH_FINALLY_CLEAN(3);
2046
2047
0
    return IGRAPH_SUCCESS;
2048
0
}
2049
2050
static igraph_error_t igraph_i_vertex_connectivity_undirected(
2051
        const igraph_t *graph,
2052
0
        igraph_int_t *res) {
2053
2054
0
    igraph_t newgraph;
2055
2056
0
    IGRAPH_CHECK(igraph_copy(&newgraph, graph));
2057
0
    IGRAPH_FINALLY(igraph_destroy, &newgraph);
2058
0
    IGRAPH_CHECK(igraph_to_directed(&newgraph, IGRAPH_TO_DIRECTED_MUTUAL));
2059
2060
0
    IGRAPH_CHECK(igraph_i_vertex_connectivity_directed(&newgraph, res, /* all_edges_are_mutual = */ true));
2061
2062
0
    igraph_destroy(&newgraph);
2063
0
    IGRAPH_FINALLY_CLEAN(1);
2064
2065
0
    return IGRAPH_SUCCESS;
2066
0
}
2067
2068
/* Use that vertex.connectivity(G) <= edge.connectivity(G) <= min(degree(G))
2069
 *
2070
 * Check if the graph is connected, and if its minimum degree is 1.
2071
 * This is sufficient to determine both the vertex and edge connectivity,
2072
 * which are returned in 'res'. 'found' will indicate if the connectivity
2073
 * could be determined.
2074
 */
2075
static igraph_error_t igraph_i_connectivity_checks(
2076
        const igraph_t *graph,
2077
        igraph_int_t *res,
2078
2.15k
        igraph_bool_t *found) {
2079
2080
2.15k
    igraph_bool_t conn;
2081
2.15k
    *found = false;
2082
2083
2.15k
    if (igraph_vcount(graph) == 0) {
2084
0
        *res = 0;
2085
0
        *found = true;
2086
0
        return IGRAPH_SUCCESS;
2087
0
    }
2088
2089
2.15k
    IGRAPH_CHECK(igraph_is_connected(graph, &conn, IGRAPH_STRONG));
2090
2.15k
    if (!conn) {
2091
966
        *res = 0;
2092
966
        *found = true;
2093
1.19k
    } else {
2094
1.19k
        igraph_vector_int_t degree;
2095
1.19k
        IGRAPH_VECTOR_INT_INIT_FINALLY(&degree, 0);
2096
1.19k
        if (!igraph_is_directed(graph)) {
2097
721
            IGRAPH_CHECK(igraph_degree(graph, &degree, igraph_vss_all(),
2098
721
                                       IGRAPH_OUT, IGRAPH_LOOPS));
2099
721
            if (igraph_vector_int_min(&degree) == 1) {
2100
78
                *res = 1;
2101
78
                *found = true;
2102
78
            }
2103
721
        } else {
2104
            /* directed, check both in- & out-degree */
2105
471
            IGRAPH_CHECK(igraph_degree(graph, &degree, igraph_vss_all(),
2106
471
                                       IGRAPH_OUT, IGRAPH_LOOPS));
2107
471
            if (igraph_vector_int_min(&degree) == 1) {
2108
40
                *res = 1;
2109
40
                *found = true;
2110
431
            } else {
2111
431
                IGRAPH_CHECK(igraph_degree(graph, &degree, igraph_vss_all(),
2112
431
                                           IGRAPH_IN, IGRAPH_LOOPS));
2113
431
                if (igraph_vector_int_min(&degree) == 1) {
2114
15
                    *res = 1;
2115
15
                    *found = true;
2116
15
                }
2117
431
            }
2118
471
        }
2119
1.19k
        igraph_vector_int_destroy(&degree);
2120
1.19k
        IGRAPH_FINALLY_CLEAN(1);
2121
1.19k
    }
2122
2.15k
    return IGRAPH_SUCCESS;
2123
2.15k
}
2124
2125
/**
2126
 * \function igraph_vertex_connectivity
2127
 * \brief The vertex connectivity of a graph.
2128
 *
2129
 * </para><para> The vertex connectivity of a graph is the minimum
2130
 * vertex connectivity along each pairs of vertices in the graph.
2131
 * </para>
2132
 *
2133
 * <para> The vertex connectivity of a graph is the same as group
2134
 * cohesion as defined in Douglas R. White and Frank Harary: The
2135
 * cohesiveness of blocks in social networks: node connectivity and
2136
 * conditional density, Sociological Methodology 31:305--359, 2001
2137
 * https://doi.org/10.1111/0081-1750.00098.
2138
 *
2139
 * \param graph The input graph.
2140
 * \param res Pointer to an integer, the result will be stored here.
2141
 * \param checks Boolean constant. Whether to check if the graph is
2142
 *    connected or complete and also the degree of the vertices. If the graph is
2143
 *    not (strongly) connected then the connectivity is obviously zero. Otherwise
2144
 *    if the minimum degree is 1 then the vertex connectivity is also
2145
 *    1. If the graph is complete, the connectivity is the vertex count
2146
 *    minus one. It is a good idea to perform these checks, as they can be
2147
 *    done quickly compared to the connectivity calculation itself.
2148
 *    They were suggested by Peter McMahan, thanks Peter.
2149
 * \return Error code.
2150
 *
2151
 * Time complexity: O(|V|^5).
2152
 *
2153
 * \sa \ref igraph_st_vertex_connectivity(), \ref igraph_maxflow_value(),
2154
 * and \ref igraph_edge_connectivity().
2155
 */
2156
2157
igraph_error_t igraph_vertex_connectivity(
2158
        const igraph_t *graph, igraph_int_t *res,
2159
0
        igraph_bool_t checks) {
2160
2161
0
    igraph_bool_t ret = false;
2162
2163
0
    if (checks) {
2164
0
        IGRAPH_CHECK(igraph_i_connectivity_checks(graph, res, &ret));
2165
0
    }
2166
2167
0
    if (checks && !ret) {
2168
        /* The vertex connectivity of a complete graph is vcount-1 by definition.
2169
         * This check cannot be performed within igraph_i_connectivity_checks(),
2170
         * as that function is used both for vertex and edge connectivities.
2171
         * Checking if the graph is complete does not suffice to determine the
2172
         * edge connectivity of a complete multigraph. */
2173
0
        igraph_bool_t complete;
2174
0
        IGRAPH_CHECK(igraph_is_complete(graph, &complete));
2175
0
        if (complete) {
2176
0
            *res = igraph_vcount(graph) - 1;
2177
0
            ret = true;
2178
0
        }
2179
0
    }
2180
2181
    /* Are we done yet? */
2182
0
    if (!ret) {
2183
0
        if (igraph_is_directed(graph)) {
2184
0
            IGRAPH_CHECK(igraph_i_vertex_connectivity_directed(graph, res, /* all_edges_are_mutual = */ false));
2185
0
        } else {
2186
0
            IGRAPH_CHECK(igraph_i_vertex_connectivity_undirected(graph, res));
2187
0
        }
2188
0
    }
2189
2190
0
    return IGRAPH_SUCCESS;
2191
0
}
2192
2193
/**
2194
 * \function igraph_st_edge_connectivity
2195
 * \brief Edge connectivity of a pair of vertices.
2196
 *
2197
 * The edge connectivity of two vertices (\p source and \p target) is the
2198
 * minimum number of edges that have to be deleted from the graph to eliminate
2199
 * all paths from \p source to \p target.
2200
 *
2201
 * </para><para>This function uses the maximum flow algorithm to calculate
2202
 * the edge connectivity.
2203
 *
2204
 * \param graph The input graph, it has to be directed.
2205
 * \param res Pointer to an integer, the result will be stored here.
2206
 * \param source The id of the source vertex.
2207
 * \param target The id of the target vertex.
2208
 * \return Error code.
2209
 *
2210
 * Time complexity: O(|V|^3).
2211
 *
2212
 * \sa \ref igraph_maxflow_value(), \ref igraph_edge_disjoint_paths(),
2213
 * \ref igraph_edge_connectivity(),
2214
 * \ref igraph_st_vertex_connectivity(), \ref
2215
 * igraph_vertex_connectivity().
2216
 */
2217
2218
igraph_error_t igraph_st_edge_connectivity(const igraph_t *graph,
2219
                                           igraph_int_t *res,
2220
                                           igraph_int_t source,
2221
0
                                           igraph_int_t target) {
2222
2223
0
    igraph_real_t flow;
2224
2225
0
    if (source == target) {
2226
0
        IGRAPH_ERROR("The source and target vertices must be different.", IGRAPH_EINVAL);
2227
0
    }
2228
2229
0
    IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, source, target, NULL, NULL));
2230
0
    *res = (igraph_int_t) flow;
2231
2232
0
    return IGRAPH_SUCCESS;
2233
0
}
2234
2235
2236
/**
2237
 * \function igraph_edge_connectivity
2238
 * \brief The minimum edge connectivity in a graph.
2239
 *
2240
 * </para><para> This is the minimum of the edge connectivity over all
2241
 * pairs of vertices in the graph. </para>
2242
 *
2243
 * <para>
2244
 * The edge connectivity of a graph is the same as group adhesion as
2245
 * defined in Douglas R. White and Frank Harary: The cohesiveness of
2246
 * blocks in social networks: node connectivity and conditional
2247
 * density, Sociological Methodology 31:305--359, 2001
2248
 * https://doi.org/10.1111/0081-1750.00098.
2249
 *
2250
 * \param graph The input graph.
2251
 * \param res Pointer to an integer, the result will be stored here.
2252
 * \param checks Boolean constant. Whether to check that the graph is
2253
 *    connected and also the degree of the vertices. If the graph is
2254
 *    not (strongly) connected then the connectivity is obviously zero. Otherwise
2255
 *    if the minimum degree is one then the edge connectivity is also
2256
 *    one. It is a good idea to perform these checks, as they can be
2257
 *    done quickly compared to the connectivity calculation itself.
2258
 *    They were suggested by Peter McMahan, thanks Peter.
2259
 * \return Error code.
2260
 *
2261
 * Time complexity: O(log(|V|)*|V|^2) for undirected graphs and
2262
 * O(|V|^4) for directed graphs, but see also the discussion at the
2263
 * documentation of \ref igraph_maxflow_value().
2264
 *
2265
 * \sa \ref igraph_st_edge_connectivity(), \ref igraph_maxflow_value(),
2266
 * \ref igraph_vertex_connectivity().
2267
 */
2268
2269
igraph_error_t igraph_edge_connectivity(const igraph_t *graph,
2270
                                        igraph_int_t *res,
2271
2.16k
                                        igraph_bool_t checks) {
2272
2273
2.16k
    igraph_bool_t ret = false;
2274
2.16k
    igraph_int_t number_of_nodes = igraph_vcount(graph);
2275
2276
    /* igraph_mincut_value returns infinity for the singleton graph,
2277
     * which cannot be cast to an integer. We catch this case early
2278
     * and postulate the edge-connectivity of this graph to be 0.
2279
     * This is consistent with what other software packages return. */
2280
2.16k
    if (number_of_nodes <= 1) {
2281
6
        *res = 0;
2282
6
        return IGRAPH_SUCCESS;
2283
6
    }
2284
2285
    /* Use that vertex.connectivity(G) <= edge.connectivity(G) <= min(degree(G)) */
2286
2.15k
    if (checks) {
2287
2.15k
        IGRAPH_CHECK(igraph_i_connectivity_checks(graph, res, &ret));
2288
2.15k
    }
2289
2290
2.15k
    if (!ret) {
2291
1.05k
        igraph_real_t real_res;
2292
1.05k
        IGRAPH_CHECK(igraph_mincut_value(graph, &real_res, 0));
2293
1.05k
        *res = (igraph_int_t)real_res;
2294
1.05k
    }
2295
2296
2.15k
    return IGRAPH_SUCCESS;
2297
2.15k
}
2298
2299
/**
2300
 * \function igraph_edge_disjoint_paths
2301
 * \brief The maximum number of edge-disjoint paths between two vertices.
2302
 *
2303
 * A set of paths between two vertices is called edge-disjoint if they do not
2304
 * share any edges. The maximum number of edge-disjoint paths are calculated
2305
 * by this function using maximum flow techniques. Directed paths are
2306
 * considered in directed graphs.
2307
 *
2308
 * </para><para>Note that the number of disjoint paths is the same as the
2309
 * edge connectivity of the two vertices using uniform edge weights.
2310
 *
2311
 * \param graph The input graph, can be directed or undirected.
2312
 * \param res Pointer to an integer variable, the result will be
2313
 *        stored here.
2314
 * \param source The id of the source vertex.
2315
 * \param target The id of the target vertex.
2316
 * \return Error code.
2317
 *
2318
 * Time complexity: O(|V|^3), but see the discussion at \ref
2319
 * igraph_maxflow_value().
2320
 *
2321
 * \sa \ref igraph_vertex_disjoint_paths(), \ref
2322
 * igraph_st_edge_connectivity(), \ref igraph_maxflow_value().
2323
 */
2324
2325
igraph_error_t igraph_edge_disjoint_paths(const igraph_t *graph,
2326
                                          igraph_int_t *res,
2327
                                          igraph_int_t source,
2328
0
                                          igraph_int_t target) {
2329
2330
0
    igraph_real_t flow;
2331
2332
0
    if (source == target) {
2333
0
        IGRAPH_ERROR("Not implemented when the source and target are the same.",
2334
0
                     IGRAPH_UNIMPLEMENTED);
2335
0
    }
2336
2337
0
    IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, source, target, NULL, NULL));
2338
2339
0
    *res = (igraph_int_t) flow;
2340
2341
0
    return IGRAPH_SUCCESS;
2342
0
}
2343
2344
/**
2345
 * \function igraph_vertex_disjoint_paths
2346
 * \brief Maximum number of vertex-disjoint paths between two vertices.
2347
 *
2348
 * A set of paths between two vertices is called vertex-disjoint if
2349
 * they share no vertices, other than the endpoints. This function computes
2350
 * the largest number of such paths that can be constructed between
2351
 * a source and a target vertex. The calculation is performed by using maximum
2352
 * flow techniques.
2353
 *
2354
 * </para><para>
2355
 * When there are no edges from the source to the target, the number of
2356
 * vertex-disjoint paths is the same as the vertex connectivity of
2357
 * the two vertices. When some edges are present, each one of them
2358
 * contributes one extra path.
2359
 *
2360
 * \param graph The input graph.
2361
 * \param res Pointer to an integer variable, the result will be
2362
 *        stored here.
2363
 * \param source The id of the source vertex.
2364
 * \param target The id of the target vertex.
2365
 * \return Error code.
2366
 *
2367
 * Time complexity: O(|V|^3).
2368
 *
2369
 * \sa \ref igraph_edge_disjoint_paths(),
2370
 * \ref igraph_st_vertex_connectivity(), \ref igraph_maxflow_value().
2371
 */
2372
2373
igraph_error_t igraph_vertex_disjoint_paths(const igraph_t *graph,
2374
                                            igraph_int_t *res,
2375
                                            igraph_int_t source,
2376
0
                                            igraph_int_t target) {
2377
2378
0
    igraph_vector_int_t eids;
2379
2380
0
    if (source == target) {
2381
0
        IGRAPH_ERROR("Not implemented when the source and target are the same.",
2382
0
                     IGRAPH_UNIMPLEMENTED);
2383
0
    }
2384
2385
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(&eids, 4);
2386
0
    IGRAPH_CHECK(igraph_get_all_eids_between(graph, &eids, source, target, /*directed*/ true));
2387
2388
0
    if (igraph_is_directed(graph)) {
2389
0
        IGRAPH_CHECK(igraph_i_st_vertex_connectivity_directed(graph, res,
2390
0
                     source, target,
2391
0
                     IGRAPH_VCONN_NEI_IGNORE));
2392
0
    } else {
2393
0
        IGRAPH_CHECK(igraph_i_st_vertex_connectivity_undirected(graph, res,
2394
0
                     source, target,
2395
0
                     IGRAPH_VCONN_NEI_IGNORE));
2396
0
    }
2397
2398
0
    *res += igraph_vector_int_size(&eids);
2399
2400
0
    igraph_vector_int_destroy(&eids);
2401
0
    IGRAPH_FINALLY_CLEAN(1);
2402
2403
0
    return IGRAPH_SUCCESS;
2404
0
}
2405
2406
/**
2407
 * \function igraph_adhesion
2408
 * \brief Graph adhesion, this is (almost) the same as edge connectivity.
2409
 *
2410
 * </para><para> This quantity is defined by White and Harary in
2411
 * The cohesiveness of blocks in social networks: node connectivity and
2412
 * conditional density, (Sociological Methodology 31:305--359, 2001)
2413
 * and basically it is the edge connectivity of the graph
2414
 * with uniform edge weights.
2415
 *
2416
 * \param graph The input graph, either directed or undirected.
2417
 * \param res Pointer to an integer, the result will be stored here.
2418
 * \param checks Boolean constant. Whether to check that the graph is
2419
 *    connected and also the degree of the vertices. If the graph is
2420
 *    not (strongly) connected then the adhesion is obviously zero. Otherwise
2421
 *    if the minimum degree is one then the adhesion is also
2422
 *    one. It is a good idea to perform these checks, as they can be
2423
 *    done quickly compared to the edge connectivity calculation itself.
2424
 *    They were suggested by Peter McMahan, thanks Peter.
2425
* \return Error code.
2426
 *
2427
 * Time complexity: O(log(|V|)*|V|^2) for undirected graphs and
2428
 * O(|V|^4) for directed graphs, but see also the discussion at the
2429
 * documentation of \ref igraph_maxflow_value().
2430
 *
2431
 * \sa \ref igraph_cohesion(), \ref igraph_maxflow_value(), \ref
2432
 * igraph_edge_connectivity(), \ref igraph_mincut_value().
2433
 */
2434
2435
igraph_error_t igraph_adhesion(const igraph_t *graph,
2436
                               igraph_int_t *res,
2437
0
                               igraph_bool_t checks) {
2438
0
    return igraph_edge_connectivity(graph, res, checks);
2439
0
}
2440
2441
/**
2442
 * \function igraph_cohesion
2443
 * \brief Graph cohesion, this is the same as vertex connectivity.
2444
 *
2445
 * </para><para> This quantity was defined by White and Harary in <quote>The
2446
 * cohesiveness of blocks in social networks: node connectivity and
2447
 * conditional density</quote>, (Sociological Methodology 31:305--359, 2001)
2448
 * and it is the same as the vertex connectivity of a graph.
2449
 *
2450
 * \param graph The input graph.
2451
 * \param res Pointer to an integer variable, the result will be
2452
 *        stored here.
2453
 * \param checks Boolean constant. Whether to check that the graph is
2454
 *    connected and also the degree of the vertices. If the graph is
2455
 *    not (strongly) connected then the cohesion is obviously zero. Otherwise
2456
 *    if the minimum degree is one then the cohesion is also
2457
 *    one. It is a good idea to perform these checks, as they can be
2458
 *    done quickly compared to the vertex connectivity calculation itself.
2459
 *    They were suggested by Peter McMahan, thanks Peter.
2460
 * \return Error code.
2461
 *
2462
 * Time complexity: O(|V|^4), |V| is the number of vertices. In
2463
 * practice it is more like O(|V|^2), see \ref igraph_maxflow_value().
2464
 *
2465
 * \sa \ref igraph_vertex_connectivity(), \ref igraph_adhesion(),
2466
 * \ref igraph_maxflow_value().
2467
 */
2468
2469
igraph_error_t igraph_cohesion(const igraph_t *graph,
2470
                               igraph_int_t *res,
2471
0
                               igraph_bool_t checks) {
2472
2473
0
    IGRAPH_CHECK(igraph_vertex_connectivity(graph, res, checks));
2474
0
    return IGRAPH_SUCCESS;
2475
0
}
2476
2477
/**
2478
 * \function igraph_gomory_hu_tree
2479
 * \brief Gomory-Hu tree of a graph.
2480
 *
2481
 * </para><para>
2482
 * The Gomory-Hu tree is a concise representation of the value of all the
2483
 * maximum flows (or minimum cuts) in a graph. The vertices of the tree
2484
 * correspond exactly to the vertices of the original graph in the same order.
2485
 * Edges of the Gomory-Hu tree are annotated by flow values.  The value of
2486
 * the maximum flow (or minimum cut) between an arbitrary (u,v) vertex
2487
 * pair in the original graph is then given by the minimum flow value (i.e.
2488
 * edge annotation) along the shortest path between u and v in the
2489
 * Gomory-Hu tree.
2490
 *
2491
 * </para><para>This implementation uses Gusfield's algorithm to construct the
2492
 * Gomory-Hu tree. See the following paper for more details:
2493
 *
2494
 * </para><para>
2495
 * Reference:
2496
 *
2497
 * </para><para>
2498
 * Gusfield D: Very simple methods for all pairs network flow analysis. SIAM J
2499
 * Comput 19(1):143-155, 1990
2500
 * https://doi.org/10.1137/0219009.
2501
 *
2502
 * \param graph The input graph.
2503
 * \param tree  Pointer to an uninitialized graph; the result will be
2504
 *              stored here.
2505
 * \param flows Pointer to an uninitialized vector; the flow values
2506
 *              corresponding to each edge in the Gomory-Hu tree will
2507
 *              be returned here. You may pass a NULL pointer here if you are
2508
 *              not interested in the flow values.
2509
 * \param capacity Vector containing the capacity of the edges. If NULL, then
2510
 *        every edge is considered to have capacity 1.0.
2511
 * \return Error code.
2512
 *
2513
 * Time complexity: O(|V|^4) since it performs a max-flow calculation
2514
 * between vertex zero and every other vertex and max-flow is
2515
 * O(|V|^3).
2516
 *
2517
 * \sa \ref igraph_maxflow()
2518
 */
2519
igraph_error_t igraph_gomory_hu_tree(const igraph_t *graph,
2520
                                     igraph_t *tree,
2521
                                     igraph_vector_t *flows,
2522
0
                                     const igraph_vector_t *capacity) {
2523
2524
0
    igraph_int_t no_of_nodes = igraph_vcount(graph);
2525
0
    igraph_int_t source, target, mid, i, n;
2526
0
    igraph_vector_int_t neighbors;
2527
0
    igraph_vector_t flow_values;
2528
0
    igraph_vector_int_t partition;
2529
0
    igraph_vector_int_t partition2;
2530
0
    igraph_real_t flow_value;
2531
2532
0
    if (igraph_is_directed(graph)) {
2533
0
        IGRAPH_ERROR("Gomory-Hu tree can only be calculated for undirected graphs.",
2534
0
                     IGRAPH_EINVAL);
2535
0
    }
2536
2537
    /* Allocate memory */
2538
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(&neighbors, no_of_nodes);
2539
0
    IGRAPH_VECTOR_INIT_FINALLY(&flow_values, no_of_nodes);
2540
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(&partition, 0);
2541
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(&partition2, 0);
2542
2543
    /* Initialize the tree: every edge points to node 0 */
2544
    /* Actually, this is done implicitly since both 'neighbors' and 'flow_values' are
2545
     * initialized to zero already */
2546
2547
    /* For each source vertex except vertex zero... */
2548
0
    for (source = 1; source < no_of_nodes; source++) {
2549
0
        IGRAPH_ALLOW_INTERRUPTION();
2550
0
        IGRAPH_PROGRESS("Gomory-Hu tree", (100.0 * (source - 1)) / (no_of_nodes - 1), 0);
2551
2552
        /* Find its current neighbor in the tree */
2553
0
        target = VECTOR(neighbors)[source];
2554
2555
        /* Find the maximum flow between source and target */
2556
0
        IGRAPH_CHECK(igraph_maxflow(graph, &flow_value, NULL, NULL, &partition, &partition2,
2557
0
                                    source, target, capacity, 0));
2558
2559
        /* Store the maximum flow */
2560
0
        VECTOR(flow_values)[source] = flow_value;
2561
2562
        /* Update the tree */
2563
        /* igraph_maxflow() guarantees that the source vertex will be in &partition
2564
         * and not in &partition2 so we need to iterate over &partition to find
2565
         * all the nodes that are of interest to us */
2566
0
        n = igraph_vector_int_size(&partition);
2567
0
        for (i = 0; i < n; i++) {
2568
0
            mid = VECTOR(partition)[i];
2569
0
            if (mid != source) {
2570
0
                if (VECTOR(neighbors)[mid] == target) {
2571
0
                    VECTOR(neighbors)[mid] = source;
2572
0
                } else if (VECTOR(neighbors)[target] == mid) {
2573
0
                    VECTOR(neighbors)[target] = source;
2574
0
                    VECTOR(neighbors)[source] = mid;
2575
0
                    VECTOR(flow_values)[source] = VECTOR(flow_values)[target];
2576
0
                    VECTOR(flow_values)[target] = flow_value;
2577
0
                }
2578
0
            }
2579
0
        }
2580
0
    }
2581
2582
0
    IGRAPH_PROGRESS("Gomory-Hu tree", 100.0, 0);
2583
2584
    /* Re-use the 'partition' vector as an edge list now */
2585
0
    IGRAPH_CHECK(igraph_vector_int_resize(&partition, no_of_nodes > 0 ? 2 * (no_of_nodes - 1) : 0));
2586
0
    for (i = 1, mid = 0; i < no_of_nodes; i++, mid += 2) {
2587
0
        VECTOR(partition)[mid]   = i;
2588
0
        VECTOR(partition)[mid + 1] = VECTOR(neighbors)[i];
2589
0
    }
2590
2591
    /* Create the tree graph; we use igraph_subgraph_from_edges here to keep the
2592
     * graph and vertex attributes */
2593
0
    IGRAPH_CHECK(igraph_subgraph_from_edges(graph, tree, igraph_ess_none(), 0));
2594
0
    IGRAPH_CHECK(igraph_add_edges(tree, &partition, 0));
2595
2596
    /* Free the allocated memory */
2597
0
    igraph_vector_int_destroy(&partition2);
2598
0
    igraph_vector_int_destroy(&partition);
2599
0
    igraph_vector_int_destroy(&neighbors);
2600
0
    IGRAPH_FINALLY_CLEAN(3);
2601
2602
    /* Return the flow values to the caller */
2603
0
    if (flows != 0) {
2604
0
        IGRAPH_CHECK(igraph_vector_update(flows, &flow_values));
2605
0
        if (no_of_nodes > 0) {
2606
0
            igraph_vector_remove(flows, 0);
2607
0
        }
2608
0
    }
2609
2610
    /* Free the remaining allocated memory */
2611
0
    igraph_vector_destroy(&flow_values);
2612
0
    IGRAPH_FINALLY_CLEAN(1);
2613
2614
0
    return IGRAPH_SUCCESS;
2615
0
}