Coverage Report

Created: 2026-07-16 07:12

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
27.6M
#define FIRST(i)       (VECTOR(*first)[(i)])
229
30.5M
#define LAST(i)        (VECTOR(*first)[(i)+1])
230
41.1M
#define CURRENT(i)     (VECTOR(*current)[(i)])
231
145M
#define RESCAP(i)      (VECTOR(*rescap)[(i)])
232
#define REV(i)         (VECTOR(*rev)[(i)])
233
54.3M
#define HEAD(i)        (VECTOR(*to)[(i)])
234
77.7M
#define EXCESS(i)      (VECTOR(*excess)[(i)])
235
173M
#define DIST(i)        (VECTOR(*distance)[(i)])
236
10.8M
#define DISCHARGE(v)   (igraph_i_mf_discharge((v), &current, &first, &rescap, \
237
10.8M
                        &to, &distance, &excess,        \
238
10.8M
                        no_of_nodes, source, target,    \
239
10.8M
                        &buckets, &ibuckets,        \
240
10.8M
                        &rev, stats, &npushsince,       \
241
10.8M
                        &nrelabelsince))
242
11.0M
#define PUSH(v,e,n)    (igraph_i_mf_push((v), (e), (n), current, rescap,      \
243
11.0M
                        excess, target, source, buckets,     \
244
11.0M
                        ibuckets, distance, rev, stats,      \
245
11.0M
                        npushsince))
246
3.90M
#define RELABEL(v)     (igraph_i_mf_relabel((v), no_of_nodes, distance,       \
247
3.90M
                        first, rescap, to, current,       \
248
3.90M
                        stats, nrelabelsince))
249
90.1k
#define GAP(b)         (igraph_i_mf_gap((b), stats, buckets, ibuckets,        \
250
90.1k
                                        no_of_nodes, distance))
251
19.2k
#define BFS()          (igraph_i_mf_bfs(&bfsq, source, target, no_of_nodes,   \
252
19.2k
                                        &buckets, &ibuckets, &distance,       \
253
19.2k
                                        &first, &current, &to, &excess,       \
254
19.2k
                                        &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
90.1k
                            igraph_vector_int_t *distance) {
260
261
90.1k
    IGRAPH_UNUSED(buckets);
262
263
90.1k
    igraph_int_t bo;
264
90.1k
    (stats->nogap)++;
265
8.74M
    for (bo = b + 1; bo <= no_of_nodes; bo++) {
266
10.5M
        while (!igraph_dbuckets_empty_bucket(ibuckets, bo)) {
267
1.91M
            igraph_int_t n = igraph_dbuckets_pop(ibuckets, bo);
268
1.91M
            (stats->nogapnodes)++;
269
1.91M
            DIST(n) = no_of_nodes;
270
1.91M
        }
271
8.65M
    }
272
90.1k
}
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
3.90M
                                igraph_maxflow_stats_t *stats, igraph_int_t *nrelabelsince) {
280
281
3.90M
    igraph_int_t min = no_of_nodes;
282
3.90M
    igraph_int_t k, l, min_edge = 0;
283
3.90M
    (stats->norelabel)++; (*nrelabelsince)++;
284
3.90M
    DIST(v) = no_of_nodes;
285
26.4M
    for (k = FIRST(v), l = LAST(v); k < l; k++) {
286
22.5M
        if (RESCAP(k) > 0 && DIST(HEAD(k)) < min) {
287
3.94M
            min = DIST(HEAD(k));
288
3.94M
            min_edge = k;
289
3.94M
        }
290
22.5M
    }
291
3.90M
    min++;
292
3.90M
    if (min < no_of_nodes) {
293
3.85M
        DIST(v) = min;
294
3.85M
        CURRENT(v) = min_edge;
295
3.85M
    }
296
3.90M
}
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
11.0M
                             igraph_int_t *npushsince) {
306
307
11.0M
    IGRAPH_UNUSED(current);
308
11.0M
    IGRAPH_UNUSED(source);
309
310
11.0M
    igraph_real_t delta =
311
11.0M
        RESCAP(e) < EXCESS(v) ? RESCAP(e) : EXCESS(v);
312
11.0M
    (stats->nopush)++; (*npushsince)++;
313
11.0M
    if (EXCESS(n) == 0 && n != target) {
314
10.4M
        igraph_dbuckets_delete(ibuckets, DIST(n), n);
315
10.4M
        igraph_buckets_add(buckets, DIST(n), n);
316
10.4M
    }
317
11.0M
    RESCAP(e) -= delta;
318
11.0M
    RESCAP(REV(e)) += delta;
319
11.0M
    EXCESS(n) += delta;
320
11.0M
    EXCESS(v) -= delta;
321
11.0M
}
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
10.8M
                                  igraph_int_t *npushsince, igraph_int_t *nrelabelsince) {
336
337
14.6M
    do {
338
14.6M
        igraph_int_t i;
339
14.6M
        igraph_int_t start = CURRENT(v);
340
14.6M
        igraph_int_t stop = LAST(v);
341
41.1M
        for (i = start; i < stop; i++) {
342
37.2M
            if (RESCAP(i) > 0) {
343
28.8M
                igraph_int_t nei = HEAD(i);
344
28.8M
                if (DIST(v) == DIST(nei) + 1) {
345
11.0M
                    PUSH((v), i, nei);
346
11.0M
                    if (EXCESS(v) == 0) {
347
10.7M
                        break;
348
10.7M
                    }
349
11.0M
                }
350
28.8M
            }
351
37.2M
        }
352
14.6M
        if (i == stop) {
353
3.90M
            igraph_int_t origdist = DIST(v);
354
3.90M
            RELABEL(v);
355
3.90M
            if (igraph_buckets_empty_bucket(buckets, origdist) &&
356
3.67M
                igraph_dbuckets_empty_bucket(ibuckets, origdist)) {
357
90.1k
                GAP(origdist);
358
90.1k
            }
359
3.90M
            if (DIST(v) == no_of_nodes) {
360
57.6k
                break;
361
57.6k
            }
362
10.7M
        } else {
363
10.7M
            CURRENT(v) = i;
364
10.7M
            igraph_dbuckets_add(ibuckets, DIST(v), v);
365
10.7M
            break;
366
10.7M
        }
367
14.6M
    } while (1);
368
10.8M
}
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
138k
                                      igraph_vector_t *rescap, igraph_vector_int_t *rev) {
378
379
138k
    igraph_int_t k, l;
380
381
138k
    IGRAPH_UNUSED(source);
382
383
138k
    igraph_buckets_clear(buckets);
384
138k
    igraph_dbuckets_clear(ibuckets);
385
138k
    igraph_vector_int_fill(distance, no_of_nodes);
386
138k
    DIST(target) = 0;
387
388
138k
    IGRAPH_CHECK(igraph_dqueue_int_push(bfsq, target));
389
12.0M
    while (!igraph_dqueue_int_empty(bfsq)) {
390
11.9M
        igraph_int_t node = igraph_dqueue_int_pop(bfsq);
391
11.9M
        igraph_int_t ndist = DIST(node) + 1;
392
64.7M
        for (k = FIRST(node), l = LAST(node); k < l; k++) {
393
52.7M
            if (RESCAP(REV(k)) > 0) {
394
25.4M
                igraph_int_t nei = HEAD(k);
395
25.4M
                if (DIST(nei) == no_of_nodes) {
396
11.8M
                    DIST(nei) = ndist;
397
11.8M
                    CURRENT(nei) = FIRST(nei);
398
11.8M
                    if (EXCESS(nei) > 0) {
399
443k
                        igraph_buckets_add(buckets, ndist, nei);
400
11.3M
                    } else {
401
11.3M
                        igraph_dbuckets_add(ibuckets, ndist, nei);
402
11.3M
                    }
403
11.8M
                    IGRAPH_CHECK(igraph_dqueue_int_push(bfsq, nei));
404
11.8M
                }
405
25.4M
            }
406
52.7M
        }
407
11.9M
    }
408
409
138k
    return IGRAPH_SUCCESS;
410
138k
}
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
119k
                              igraph_maxflow_stats_t *stats) {
493
494
119k
    const igraph_int_t no_of_nodes = igraph_vcount(graph);
495
119k
    const igraph_int_t no_of_orig_edges = igraph_ecount(graph);
496
119k
    const igraph_int_t no_of_edges = 2 * no_of_orig_edges;
497
498
119k
    igraph_vector_t rescap, excess;
499
119k
    igraph_vector_int_t from, to, rev, distance;
500
119k
    igraph_vector_int_t edges, rank;
501
119k
    igraph_vector_int_t current, first;
502
119k
    igraph_buckets_t buckets;
503
119k
    igraph_dbuckets_t ibuckets;
504
505
119k
    igraph_dqueue_int_t bfsq;
506
507
119k
    igraph_int_t idx;
508
119k
    igraph_int_t npushsince = 0, nrelabelsince = 0;
509
510
119k
    igraph_maxflow_stats_t local_stats;   /* used if the user passed a null pointer for stats */
511
512
119k
    if (stats == NULL) {
513
119k
        stats = &local_stats;
514
119k
    }
515
516
119k
    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
119k
    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
119k
    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
119k
    if (source == target) {
530
0
        IGRAPH_ERROR("Source and target vertices are the same.", IGRAPH_EINVAL);
531
0
    }
532
533
119k
    stats->nopush = stats->norelabel = stats->nogap = stats->nogapnodes =
534
119k
                                           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
119k
#undef FIRST
565
119k
#undef LAST
566
119k
#undef CURRENT
567
119k
#undef RESCAP
568
119k
#undef REV
569
119k
#undef HEAD
570
119k
#undef EXCESS
571
119k
#undef DIST
572
119k
#define FIRST(i)       (VECTOR(first)[(i)])
573
119k
#define LAST(i)        (VECTOR(first)[(i)+1])
574
119k
#define CURRENT(i)     (VECTOR(current)[(i)])
575
1.62M
#define RESCAP(i)      (VECTOR(rescap)[(i)])
576
119k
#define REV(i)         (VECTOR(rev)[(i)])
577
542k
#define HEAD(i)        (VECTOR(to)[(i)])
578
661k
#define EXCESS(i)      (VECTOR(excess)[(i)])
579
119k
#define DIST(i)        (VECTOR(distance)[(i)])
580
581
119k
    IGRAPH_CHECK(igraph_dqueue_int_init(&bfsq, no_of_nodes));
582
119k
    IGRAPH_FINALLY(igraph_dqueue_int_destroy, &bfsq);
583
119k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&to,       no_of_edges);
584
119k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&rev,      no_of_edges);
585
119k
    IGRAPH_VECTOR_INIT_FINALLY(&rescap,       no_of_edges);
586
119k
    IGRAPH_VECTOR_INIT_FINALLY(&excess,       no_of_nodes);
587
119k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&distance, no_of_nodes);
588
119k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&first,    no_of_nodes + 1);
589
590
119k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&rank,         no_of_edges);
591
119k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&from,     no_of_edges);
592
119k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&edges,        no_of_edges);
593
594
    /* Create the basic data structure */
595
119k
    IGRAPH_CHECK(igraph_get_edgelist(graph, &edges, 0));
596
119k
    IGRAPH_CHECK(igraph_i_vector_int_rank(&edges, &rank, no_of_nodes));
597
598
26.4M
    for (igraph_int_t i = 0; i < no_of_edges; i += 2) {
599
26.3M
        const igraph_int_t pos = VECTOR(rank)[i];
600
26.3M
        const igraph_int_t pos2 = VECTOR(rank)[i + 1];
601
26.3M
        VECTOR(from)[pos] = VECTOR(edges)[i];
602
26.3M
        VECTOR(to)[pos]   = VECTOR(edges)[i + 1];
603
26.3M
        VECTOR(from)[pos2] = VECTOR(edges)[i + 1];
604
26.3M
        VECTOR(to)[pos2]   = VECTOR(edges)[i];
605
26.3M
        VECTOR(rev)[pos] = pos2;
606
26.3M
        VECTOR(rev)[pos2] = pos;
607
26.3M
        VECTOR(rescap)[pos] = capacity ? VECTOR(*capacity)[i / 2] : 1.0;
608
26.3M
        VECTOR(rescap)[pos2] = 0.0;
609
26.3M
    }
610
611
    /* The first pointers. This is a but trickier, than one would
612
       think, because of the possible isolate vertices. */
613
614
119k
    idx = -1;
615
238k
    for (igraph_int_t i = 0; i <= VECTOR(from)[0]; i++) {
616
119k
        idx++; VECTOR(first)[idx] = 0;
617
119k
    }
618
52.6M
    for (igraph_int_t i = 1; i < no_of_edges; i++) {
619
52.5M
        const igraph_int_t n = (VECTOR(from)[i] -
620
52.5M
                                    VECTOR(from)[ VECTOR(first)[idx] ]);
621
64.4M
        for (igraph_int_t j = 0; j < n; j++) {
622
11.9M
            idx++; VECTOR(first)[idx] = i;
623
11.9M
        }
624
52.5M
    }
625
119k
    idx++;
626
238k
    while (idx < no_of_nodes + 1) {
627
119k
        VECTOR(first)[idx++] = no_of_edges;
628
119k
    }
629
630
119k
    igraph_vector_int_destroy(&from);
631
119k
    igraph_vector_int_destroy(&edges);
632
119k
    IGRAPH_FINALLY_CLEAN(2);
633
634
119k
    if (!flow) {
635
119k
        igraph_vector_int_destroy(&rank);
636
119k
        IGRAPH_FINALLY_CLEAN(1);
637
119k
    }
638
639
    /* And the current pointers, initially the same as the first */
640
119k
    IGRAPH_VECTOR_INT_INIT_FINALLY(&current, no_of_nodes);
641
12.1M
    for (igraph_int_t i = 0; i < no_of_nodes; i++) {
642
12.0M
        VECTOR(current)[i] = VECTOR(first)[i];
643
12.0M
    }
644
645
    /* OK, the graph is set up, initialization */
646
647
119k
    IGRAPH_CHECK(igraph_buckets_init(&buckets, no_of_nodes + 1, no_of_nodes));
648
119k
    IGRAPH_FINALLY(igraph_buckets_destroy, &buckets);
649
119k
    IGRAPH_CHECK(igraph_dbuckets_init(&ibuckets, no_of_nodes + 1, no_of_nodes));
650
119k
    IGRAPH_FINALLY(igraph_dbuckets_destroy, &ibuckets);
651
652
    /* Send as much flow as possible from the source to its neighbors */
653
661k
    for (igraph_int_t i = FIRST(source), j = LAST(source); i < j; i++) {
654
542k
        if (HEAD(i) != source) {
655
542k
            const igraph_real_t delta = RESCAP(i);
656
542k
            RESCAP(i) = 0;
657
542k
            RESCAP(REV(i)) += delta;
658
542k
            EXCESS(HEAD(i)) += delta;
659
542k
        }
660
542k
    }
661
662
119k
    IGRAPH_CHECK(BFS());
663
119k
    (stats->nobfs)++;
664
665
10.9M
    while (!igraph_buckets_empty(&buckets)) {
666
10.8M
        const igraph_int_t vertex = igraph_buckets_popmax(&buckets);
667
10.8M
        DISCHARGE(vertex);
668
10.8M
        if (npushsince > no_of_nodes / 2 && nrelabelsince > no_of_nodes) {
669
19.2k
            (stats->nobfs)++;
670
19.2k
            BFS();
671
19.2k
            npushsince = nrelabelsince = 0;
672
19.2k
        }
673
10.8M
    }
674
675
    /* Store the result */
676
119k
    if (value) {
677
119k
        *value = EXCESS(target);
678
119k
    }
679
680
    /* If we also need the minimum cut */
681
119k
    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
119k
    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
119k
    igraph_dbuckets_destroy(&ibuckets);
1019
119k
    igraph_buckets_destroy(&buckets);
1020
119k
    igraph_vector_int_destroy(&current);
1021
119k
    igraph_vector_int_destroy(&first);
1022
119k
    igraph_vector_int_destroy(&distance);
1023
119k
    igraph_vector_destroy(&excess);
1024
119k
    igraph_vector_destroy(&rescap);
1025
119k
    igraph_vector_int_destroy(&rev);
1026
119k
    igraph_vector_int_destroy(&to);
1027
119k
    igraph_dqueue_int_destroy(&bfsq);
1028
119k
    IGRAPH_FINALLY_CLEAN(10);
1029
1030
119k
    return IGRAPH_SUCCESS;
1031
119k
}
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
119k
                                    igraph_maxflow_stats_t *stats) {
1092
1093
119k
    return igraph_maxflow(graph, value, /*flow=*/ NULL, /*cut=*/ NULL,
1094
119k
                          /*partition=*/ NULL, /*partition1=*/ NULL,
1095
119k
                          source, target, capacity, stats);
1096
119k
}
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
0
        const igraph_vector_t *capacity) {
1201
1202
0
    igraph_int_t no_of_nodes = igraph_vcount(graph);
1203
0
    igraph_int_t no_of_edges = igraph_ecount(graph);
1204
1205
0
    igraph_i_cutheap_t heap;
1206
0
    igraph_real_t mincut = IGRAPH_INFINITY; /* infinity */
1207
0
    igraph_int_t i;
1208
1209
0
    igraph_adjlist_t adjlist;
1210
0
    igraph_inclist_t inclist;
1211
1212
0
    igraph_vector_int_t mergehist;
1213
0
    igraph_bool_t calc_cut = partition || partition2 || cut;
1214
0
    igraph_int_t act_step = 0, mincut_step = 0;
1215
1216
0
    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
0
    {
1222
0
        igraph_vector_int_t memb;
1223
0
        igraph_vector_int_t csize;
1224
0
        igraph_int_t no;
1225
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&memb, 0);
1226
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&csize, 0);
1227
0
        IGRAPH_CHECK(igraph_connected_components(graph, &memb, &csize, &no, IGRAPH_WEAK));
1228
0
        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
0
        igraph_vector_int_destroy(&csize);
1257
0
        igraph_vector_int_destroy(&memb);
1258
0
        IGRAPH_FINALLY_CLEAN(2);
1259
1260
0
        if (no != 1) {
1261
0
            return IGRAPH_SUCCESS;
1262
0
        }
1263
0
    }
1264
1265
0
    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
0
    IGRAPH_CHECK(igraph_i_cutheap_init(&heap, no_of_nodes));
1271
0
    IGRAPH_FINALLY(igraph_i_cutheap_destroy, &heap);
1272
1273
0
    IGRAPH_CHECK(igraph_inclist_init(graph, &inclist, IGRAPH_OUT, IGRAPH_LOOPS_ONCE));
1274
0
    IGRAPH_FINALLY(igraph_inclist_destroy, &inclist);
1275
1276
0
    IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE));
1277
0
    IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist);
1278
1279
0
    while (igraph_i_cutheap_size(&heap) >= 2) {
1280
1281
0
        igraph_int_t last;
1282
0
        igraph_real_t acut;
1283
0
        igraph_int_t a, n;
1284
1285
0
        igraph_vector_int_t *edges, *edges2;
1286
0
        igraph_vector_int_t *neis, *neis2;
1287
1288
0
        do {
1289
0
            a = igraph_i_cutheap_popmax(&heap);
1290
1291
            /* update the weights of the active vertices connected to a */
1292
0
            edges = igraph_inclist_get(&inclist, a);
1293
0
            neis = igraph_adjlist_get(&adjlist, a);
1294
0
            n = igraph_vector_int_size(edges);
1295
0
            for (i = 0; i < n; i++) {
1296
0
                igraph_int_t edge = VECTOR(*edges)[i];
1297
0
                igraph_int_t to = VECTOR(*neis)[i];
1298
0
                igraph_real_t weight = capacity ? VECTOR(*capacity)[edge] : 1.0;
1299
0
                igraph_i_cutheap_update(&heap, to, weight);
1300
0
            }
1301
1302
0
        } 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
0
        acut = igraph_i_cutheap_maxvalue(&heap);
1307
0
        last = igraph_i_cutheap_popmax(&heap);
1308
1309
0
        if (acut < mincut) {
1310
0
            mincut = acut;
1311
0
            mincut_step = act_step;
1312
0
        }
1313
1314
0
        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
0
        act_step++;
1321
0
        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
0
        edges = igraph_inclist_get(&inclist, a);
1328
0
        neis = igraph_adjlist_get(&adjlist, a);
1329
0
        n = igraph_vector_int_size(edges);
1330
0
        for (i = 0; i < n; ) {
1331
0
            if (VECTOR(*neis)[i] == last) {
1332
0
                VECTOR(*neis)[i] = VECTOR(*neis)[n - 1];
1333
0
                VECTOR(*edges)[i] = VECTOR(*edges)[n - 1];
1334
0
                igraph_vector_int_pop_back(neis);
1335
0
                igraph_vector_int_pop_back(edges);
1336
0
                n--;
1337
0
            } else {
1338
0
                i++;
1339
0
            }
1340
0
        }
1341
1342
0
        edges = igraph_inclist_get(&inclist, last);
1343
0
        neis = igraph_adjlist_get(&adjlist, last);
1344
0
        n = igraph_vector_int_size(edges);
1345
0
        for (i = 0; i < n; ) {
1346
0
            if (VECTOR(*neis)[i] == a) {
1347
0
                VECTOR(*neis)[i] = VECTOR(*neis)[n - 1];
1348
0
                VECTOR(*edges)[i] = VECTOR(*edges)[n - 1];
1349
0
                igraph_vector_int_pop_back(neis);
1350
0
                igraph_vector_int_pop_back(edges);
1351
0
                n--;
1352
0
            } else {
1353
0
                i++;
1354
0
            }
1355
0
        }
1356
1357
        /* Now rewrite the edge lists of last's neighbors */
1358
0
        neis = igraph_adjlist_get(&adjlist, last);
1359
0
        n = igraph_vector_int_size(neis);
1360
0
        for (i = 0; i < n; i++) {
1361
0
            igraph_int_t nei = VECTOR(*neis)[i];
1362
0
            igraph_int_t n2, j;
1363
0
            neis2 = igraph_adjlist_get(&adjlist, nei);
1364
0
            n2 = igraph_vector_int_size(neis2);
1365
0
            for (j = 0; j < n2; j++) {
1366
0
                if (VECTOR(*neis2)[j] == last) {
1367
0
                    VECTOR(*neis2)[j] = a;
1368
0
                }
1369
0
            }
1370
0
        }
1371
1372
        /* And append the lists of last to the lists of a */
1373
0
        edges = igraph_inclist_get(&inclist, a);
1374
0
        neis = igraph_adjlist_get(&adjlist, a);
1375
0
        edges2 = igraph_inclist_get(&inclist, last);
1376
0
        neis2 = igraph_adjlist_get(&adjlist, last);
1377
0
        IGRAPH_CHECK(igraph_vector_int_append(edges, edges2));
1378
0
        IGRAPH_CHECK(igraph_vector_int_append(neis, neis2));
1379
0
        igraph_vector_int_clear(edges2); /* TODO: free it */
1380
0
        igraph_vector_int_clear(neis2);  /* TODO: free it */
1381
1382
        /* Remove the deleted vertex from the heap entirely */
1383
0
        IGRAPH_CHECK(igraph_i_cutheap_reset_undefine(&heap, last));
1384
0
    }
1385
1386
0
    *res = mincut;
1387
1388
0
    igraph_inclist_destroy(&inclist);
1389
0
    igraph_adjlist_destroy(&adjlist);
1390
0
    igraph_i_cutheap_destroy(&heap);
1391
0
    IGRAPH_FINALLY_CLEAN(3);
1392
1393
0
    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_vector_int_clear(&mergehist);
1439
0
            for (i = 0; i < no_of_edges; i++) {
1440
0
                igraph_int_t from = IGRAPH_FROM(graph, i);
1441
0
                igraph_int_t to = IGRAPH_TO(graph, i);
1442
1443
0
                if ((IGRAPH_BIT_TEST(mark, from) && !IGRAPH_BIT_TEST(mark, to)) ||
1444
0
                    (IGRAPH_BIT_TEST(mark, to) && !IGRAPH_BIT_TEST(mark, from))) {
1445
0
                    IGRAPH_CHECK(igraph_vector_int_push_back(&mergehist, i));
1446
0
                }
1447
0
            }
1448
0
            igraph_vector_int_clear(cut);
1449
0
            IGRAPH_CHECK(igraph_vector_int_append(cut, &mergehist));
1450
0
        }
1451
1452
0
        igraph_bitset_destroy(&mark);
1453
0
        igraph_vector_int_destroy(&mergehist);
1454
0
        IGRAPH_FINALLY_CLEAN(2);
1455
0
    }
1456
1457
0
    return IGRAPH_SUCCESS;
1458
0
}
1459
1460
static igraph_error_t igraph_i_mincut_directed(
1461
        const igraph_t *graph,
1462
        igraph_real_t *value,
1463
        igraph_vector_int_t *partition,
1464
        igraph_vector_int_t *partition2,
1465
        igraph_vector_int_t *cut,
1466
0
        const igraph_vector_t *capacity) {
1467
1468
0
    igraph_int_t i;
1469
0
    igraph_int_t no_of_nodes = igraph_vcount(graph);
1470
0
    igraph_real_t flow;
1471
0
    igraph_real_t minmaxflow = IGRAPH_INFINITY;
1472
0
    igraph_vector_int_t mypartition, mypartition2, mycut;
1473
0
    igraph_vector_int_t *ppartition = NULL, *ppartition2 = NULL, *pcut = NULL;
1474
0
    igraph_vector_int_t bestpartition, bestpartition2, bestcut;
1475
1476
0
    if (partition) {
1477
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&bestpartition, 0);
1478
0
    }
1479
0
    if (partition2) {
1480
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&bestpartition2, 0);
1481
0
    }
1482
0
    if (cut) {
1483
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&bestcut, 0);
1484
0
    }
1485
1486
0
    if (partition) {
1487
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&mypartition, 0);
1488
0
        ppartition = &mypartition;
1489
0
    }
1490
0
    if (partition2) {
1491
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&mypartition2, 0);
1492
0
        ppartition2 = &mypartition2;
1493
0
    }
1494
0
    if (cut) {
1495
0
        IGRAPH_VECTOR_INT_INIT_FINALLY(&mycut, 0);
1496
0
        pcut = &mycut;
1497
0
    }
1498
1499
0
    for (i = 1; i < no_of_nodes; i++) {
1500
0
        IGRAPH_CHECK(igraph_maxflow(graph, /*value=*/ &flow, /*flow=*/ NULL,
1501
0
                                    pcut, ppartition, ppartition2, /*source=*/ 0,
1502
0
                                    /*target=*/ i, capacity, NULL));
1503
0
        if (flow < minmaxflow) {
1504
0
            minmaxflow = flow;
1505
0
            if (cut) {
1506
0
                IGRAPH_CHECK(igraph_vector_int_update(&bestcut, &mycut));
1507
0
            }
1508
0
            if (partition) {
1509
0
                IGRAPH_CHECK(igraph_vector_int_update(&bestpartition, &mypartition));
1510
0
            }
1511
0
            if (partition2) {
1512
0
                IGRAPH_CHECK(igraph_vector_int_update(&bestpartition2, &mypartition2));
1513
0
            }
1514
1515
0
            if (minmaxflow == 0) {
1516
0
                break;
1517
0
            }
1518
0
        }
1519
0
        IGRAPH_CHECK(igraph_maxflow(graph, /*value=*/ &flow, /*flow=*/ NULL,
1520
0
                                    pcut, ppartition, ppartition2,
1521
0
                                    /*source=*/ i,
1522
0
                                    /*target=*/ 0, capacity, NULL));
1523
0
        if (flow < minmaxflow) {
1524
0
            minmaxflow = flow;
1525
0
            if (cut) {
1526
0
                IGRAPH_CHECK(igraph_vector_int_update(&bestcut, &mycut));
1527
0
            }
1528
0
            if (partition) {
1529
0
                IGRAPH_CHECK(igraph_vector_int_update(&bestpartition, &mypartition));
1530
0
            }
1531
0
            if (partition2) {
1532
0
                IGRAPH_CHECK(igraph_vector_int_update(&bestpartition2, &mypartition2));
1533
0
            }
1534
1535
0
            if (minmaxflow == 0) {
1536
0
                break;
1537
0
            }
1538
0
        }
1539
0
    }
1540
1541
0
    if (value) {
1542
0
        *value = minmaxflow;
1543
0
    }
1544
1545
0
    if (cut) {
1546
0
        igraph_vector_int_destroy(&mycut);
1547
0
        IGRAPH_FINALLY_CLEAN(1);
1548
0
    }
1549
0
    if (partition) {
1550
0
        igraph_vector_int_destroy(&mypartition);
1551
0
        IGRAPH_FINALLY_CLEAN(1);
1552
0
    }
1553
0
    if (partition2) {
1554
0
        igraph_vector_int_destroy(&mypartition2);
1555
0
        IGRAPH_FINALLY_CLEAN(1);
1556
0
    }
1557
0
    if (cut) {
1558
0
        IGRAPH_CHECK(igraph_vector_int_update(cut, &bestcut));
1559
0
        igraph_vector_int_destroy(&bestcut);
1560
0
        IGRAPH_FINALLY_CLEAN(1);
1561
0
    }
1562
0
    if (partition2) {
1563
0
        IGRAPH_CHECK(igraph_vector_int_update(partition2, &bestpartition2));
1564
0
        igraph_vector_int_destroy(&bestpartition2);
1565
0
        IGRAPH_FINALLY_CLEAN(1);
1566
0
    }
1567
0
    if (partition) {
1568
0
        IGRAPH_CHECK(igraph_vector_int_update(partition, &bestpartition));
1569
0
        igraph_vector_int_destroy(&bestpartition);
1570
0
        IGRAPH_FINALLY_CLEAN(1);
1571
0
    }
1572
1573
0
    return IGRAPH_SUCCESS;
1574
0
}
1575
1576
/**
1577
 * \function igraph_mincut
1578
 * \brief Calculates the minimum cut in a graph.
1579
 *
1580
 * This function calculates the minimum cut in a graph.
1581
 * The minimum cut is the minimum set of edges which needs to be
1582
 * removed to disconnect the graph. The minimum is calculated using
1583
 * the weights (\p capacity) of the edges, so the cut with the minimum
1584
 * total capacity is calculated.
1585
 *
1586
 * </para><para> For directed graphs an implementation based on
1587
 * calculating 2|V|-2 maximum flows is used.
1588
 * For undirected graphs we use the Stoer-Wagner
1589
 * algorithm, as described in M. Stoer and F. Wagner: A simple min-cut
1590
 * algorithm, Journal of the ACM, 44 585-591, 1997.
1591
 *
1592
 * </para><para>
1593
 * The first implementation of the actual cut calculation for
1594
 * undirected graphs was made by Gregory Benison, thanks Greg.
1595
 *
1596
 * \param graph The input graph.
1597
 * \param value Pointer to a float, the value of the cut will be
1598
 *    stored here.
1599
 * \param partition Pointer to an initialized vector, the ids
1600
 *    of the vertices in the first partition after separating the
1601
 *    graph will be stored here. The vector will be resized as
1602
 *    needed. This argument is ignored if it is a NULL pointer.
1603
 * \param partition2 Pointer to an initialized vector the ids
1604
 *    of the vertices in the second partition will be stored here.
1605
 *    The vector will be resized as needed. This argument is ignored
1606
 *    if it is a NULL pointer.
1607
 * \param cut Pointer to an initialized vector, the IDs of the edges
1608
 *    in the cut will be stored here. This argument is ignored if it
1609
 *    is a NULL pointer.
1610
 * \param capacity A numeric vector giving the capacities of the
1611
 *    edges. If a null pointer then all edges have unit capacity.
1612
 * \return Error code.
1613
 *
1614
 * \sa \ref igraph_mincut_value(), a simpler interface for calculating
1615
 * the value of the cut only.
1616
 *
1617
 * Time complexity: for directed graphs it is O(|V|^4), but see the
1618
 * remarks at \ref igraph_maxflow(). For undirected graphs it is
1619
 * O(|V||E|+|V|^2 log|V|). |V| and |E| are the number of vertices and
1620
 * edges respectively.
1621
 *
1622
 * \example examples/simple/igraph_mincut.c
1623
 */
1624
1625
igraph_error_t igraph_mincut(const igraph_t *graph,
1626
                             igraph_real_t *value,
1627
                             igraph_vector_int_t *partition,
1628
                             igraph_vector_int_t *partition2,
1629
                             igraph_vector_int_t *cut,
1630
0
                             const igraph_vector_t *capacity) {
1631
1632
0
    if (igraph_is_directed(graph)) {
1633
0
        if (partition || partition2 || cut) {
1634
0
            igraph_i_mincut_directed(graph, value, partition, partition2, cut,
1635
0
                                     capacity);
1636
0
        } else {
1637
0
            return igraph_mincut_value(graph, value, capacity);
1638
0
        }
1639
0
    } else {
1640
0
        IGRAPH_CHECK(igraph_i_mincut_undirected(graph, value, partition,
1641
0
                                                partition2, cut, capacity));
1642
0
        return IGRAPH_SUCCESS;
1643
0
    }
1644
1645
0
    return IGRAPH_SUCCESS;
1646
0
}
1647
1648
1649
static igraph_error_t igraph_i_mincut_value_undirected(
1650
        const igraph_t *graph,
1651
        igraph_real_t *res,
1652
0
        const igraph_vector_t *capacity) {
1653
0
    return igraph_i_mincut_undirected(graph, res, 0, 0, 0, capacity);
1654
0
}
1655
1656
/**
1657
 * \function igraph_mincut_value
1658
 * \brief The minimum edge cut in a graph.
1659
 *
1660
 * </para><para> The minimum edge cut in a graph is the total minimum
1661
 * weight of the edges needed to remove from the graph to make the
1662
 * graph \em not strongly connected. (If the original graph is not
1663
 * strongly connected then this is zero.) Note that in undirected
1664
 * graphs strong connectedness is the same as weak connectedness. </para>
1665
 *
1666
 * <para> The minimum cut can be calculated with maximum flow
1667
 * techniques, although the current implementation does this only for
1668
 * directed graphs and a separate non-flow based implementation is
1669
 * used for undirected graphs. See Mechthild Stoer and Frank Wagner: A
1670
 * simple min-cut algorithm, Journal of the ACM 44 585--591, 1997.
1671
 * For directed graphs
1672
 * the maximum flow is calculated between a fixed vertex and all the
1673
 * other vertices in the graph and this is done in both
1674
 * directions. Then the minimum is taken to get the minimum cut.
1675
 *
1676
 * \param graph The input graph.
1677
 * \param res Pointer to a real variable, the result will be stored
1678
 *    here.
1679
 * \param capacity Pointer to the capacity vector, it should contain
1680
 *    the same number of non-negative numbers as the number of edges in
1681
 *    the graph. If a null pointer then all edges will have unit capacity.
1682
 * \return Error code.
1683
 *
1684
 * \sa \ref igraph_mincut(), \ref igraph_maxflow_value(), \ref
1685
 * igraph_st_mincut_value().
1686
 *
1687
 * Time complexity: O(log(|V|)*|V|^2) for undirected graphs and
1688
 * O(|V|^4) for directed graphs, but see also the discussion at the
1689
 * documentation of \ref igraph_maxflow_value().
1690
 */
1691
1692
igraph_error_t igraph_mincut_value(const igraph_t *graph, igraph_real_t *res,
1693
0
                                   const igraph_vector_t *capacity) {
1694
1695
0
    igraph_int_t no_of_nodes = igraph_vcount(graph);
1696
0
    igraph_real_t minmaxflow, flow;
1697
0
    igraph_int_t i;
1698
1699
0
    minmaxflow = IGRAPH_INFINITY;
1700
1701
0
    if (!igraph_is_directed(graph)) {
1702
0
        IGRAPH_CHECK(igraph_i_mincut_value_undirected(graph, res, capacity));
1703
0
        return IGRAPH_SUCCESS;
1704
0
    }
1705
1706
0
    for (i = 1; i < no_of_nodes; i++) {
1707
0
        IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, 0, i,
1708
0
                                          capacity, NULL));
1709
0
        if (flow < minmaxflow) {
1710
0
            minmaxflow = flow;
1711
0
            if (flow == 0) {
1712
0
                break;
1713
0
            }
1714
0
        }
1715
0
        IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, i, 0,
1716
0
                                          capacity, NULL));
1717
0
        if (flow < minmaxflow) {
1718
0
            minmaxflow = flow;
1719
0
            if (flow == 0) {
1720
0
                break;
1721
0
            }
1722
0
        }
1723
0
    }
1724
1725
0
    if (res) {
1726
0
        *res = minmaxflow;
1727
0
    }
1728
1729
0
    return IGRAPH_SUCCESS;
1730
0
}
1731
1732
static igraph_error_t igraph_i_st_vertex_connectivity_check_errors(
1733
        const igraph_t *graph,
1734
        igraph_int_t *res,
1735
        igraph_int_t source,
1736
        igraph_int_t target,
1737
        igraph_vconn_nei_t neighbors,
1738
        igraph_bool_t *done,
1739
134k
        igraph_int_t *no_conn) {
1740
1741
134k
    igraph_int_t no_of_nodes = igraph_vcount(graph);
1742
134k
    igraph_int_t eid;
1743
134k
    igraph_bool_t conn;
1744
134k
    *done = true;
1745
134k
    *no_conn = 0;
1746
1747
134k
    if (source == target) {
1748
0
        IGRAPH_ERROR("Source and target vertices are the same.", IGRAPH_EINVAL);
1749
0
    }
1750
1751
134k
    if (source < 0 || source >= no_of_nodes || target < 0 || target >= no_of_nodes) {
1752
0
        IGRAPH_ERROR("Invalid source or target vertex.", IGRAPH_EINVAL);
1753
0
    }
1754
1755
134k
    switch (neighbors) {
1756
0
    case IGRAPH_VCONN_NEI_ERROR:
1757
0
        IGRAPH_CHECK(igraph_are_adjacent(graph, source, target, &conn));
1758
0
        if (conn) {
1759
0
            IGRAPH_ERROR("Source and target vertices connected.", IGRAPH_EINVAL);
1760
0
        }
1761
0
        break;
1762
0
    case IGRAPH_VCONN_NEI_NEGATIVE:
1763
0
        IGRAPH_CHECK(igraph_are_adjacent(graph, source, target, &conn));
1764
0
        if (conn) {
1765
0
            *res = -1;
1766
0
            return IGRAPH_SUCCESS;
1767
0
        }
1768
0
        break;
1769
134k
    case IGRAPH_VCONN_NEI_NUMBER_OF_NODES:
1770
134k
        IGRAPH_CHECK(igraph_are_adjacent(graph, source, target, &conn));
1771
134k
        if (conn) {
1772
15.2k
            *res = no_of_nodes;
1773
15.2k
            return IGRAPH_SUCCESS;
1774
15.2k
        }
1775
119k
        break;
1776
119k
    case IGRAPH_VCONN_NEI_IGNORE:
1777
0
        IGRAPH_CHECK(igraph_get_eid(graph, &eid, source, target, IGRAPH_DIRECTED, /*error=*/ false));
1778
0
        if (eid >= 0) {
1779
0
            IGRAPH_CHECK(igraph_count_multiple_1(graph, no_conn, eid));
1780
0
        }
1781
0
        break;
1782
0
    default:
1783
0
        IGRAPH_ERROR("Unknown `igraph_vconn_nei_t'.", IGRAPH_EINVAL);
1784
0
        break;
1785
134k
    }
1786
119k
    *done = false;
1787
119k
    return IGRAPH_SUCCESS;
1788
134k
}
1789
1790
static igraph_error_t igraph_i_st_vertex_connectivity_directed(
1791
        const igraph_t *graph,
1792
        igraph_int_t *res,
1793
        igraph_int_t source,
1794
        igraph_int_t target,
1795
0
        igraph_vconn_nei_t neighbors) {
1796
1797
0
    igraph_int_t no_of_nodes = igraph_vcount(graph);
1798
0
    igraph_int_t no_of_edges;
1799
0
    igraph_real_t real_res;
1800
0
    igraph_t newgraph;
1801
0
    igraph_int_t i, len;
1802
0
    igraph_bool_t done;
1803
0
    igraph_int_t no_conn;
1804
0
    igraph_vector_int_t incs;
1805
0
    igraph_vector_t capacity;
1806
1807
0
    IGRAPH_CHECK(igraph_i_st_vertex_connectivity_check_errors(graph, res, source, target, neighbors, &done, &no_conn));
1808
0
    if (done) {
1809
0
        return IGRAPH_SUCCESS;
1810
0
    }
1811
1812
    /* Create the new graph */
1813
0
    IGRAPH_CHECK(igraph_i_split_vertices(graph, &newgraph));
1814
0
    IGRAPH_FINALLY(igraph_destroy, &newgraph);
1815
1816
    /* Create the capacity vector, fill it with ones */
1817
0
    no_of_edges = igraph_ecount(&newgraph);
1818
0
    IGRAPH_VECTOR_INIT_FINALLY(&capacity, no_of_edges);
1819
0
    igraph_vector_fill(&capacity, 1);
1820
1821
    /* "Disable" the edges incident on the input half of the source vertex
1822
     * and the output half of the target vertex */
1823
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(&incs, 0);
1824
0
    IGRAPH_CHECK(igraph_incident(&newgraph, &incs, source + no_of_nodes, IGRAPH_ALL, IGRAPH_LOOPS));
1825
0
    len = igraph_vector_int_size(&incs);
1826
0
    for (i = 0; i < len; i++) {
1827
0
        VECTOR(capacity)[VECTOR(incs)[i]] = 0;
1828
0
    }
1829
0
    IGRAPH_CHECK(igraph_incident(&newgraph, &incs, target, IGRAPH_ALL, IGRAPH_LOOPS));
1830
0
    len = igraph_vector_int_size(&incs);
1831
0
    for (i = 0; i < len; i++) {
1832
0
        VECTOR(capacity)[VECTOR(incs)[i]] = 0;
1833
0
    }
1834
0
    igraph_vector_int_destroy(&incs);
1835
0
    IGRAPH_FINALLY_CLEAN(1);
1836
1837
    /* Do the maximum flow */
1838
0
    IGRAPH_CHECK(igraph_maxflow_value(&newgraph, &real_res,
1839
0
                                      source, target + no_of_nodes, &capacity, NULL));
1840
0
    *res = (igraph_int_t) real_res;
1841
1842
0
    *res -= no_conn;
1843
1844
0
    igraph_vector_destroy(&capacity);
1845
0
    igraph_destroy(&newgraph);
1846
0
    IGRAPH_FINALLY_CLEAN(2);
1847
1848
0
    return IGRAPH_SUCCESS;
1849
0
}
1850
1851
static igraph_error_t igraph_i_st_vertex_connectivity_undirected(
1852
        const igraph_t *graph,
1853
        igraph_int_t *res,
1854
        igraph_int_t source,
1855
        igraph_int_t target,
1856
0
        igraph_vconn_nei_t neighbors) {
1857
1858
0
    igraph_t newgraph;
1859
0
    igraph_bool_t done;
1860
0
    igraph_int_t no_conn;
1861
1862
0
    IGRAPH_CHECK(igraph_i_st_vertex_connectivity_check_errors(graph, res, source, target, neighbors, &done, &no_conn));
1863
0
    if (done) {
1864
0
        return IGRAPH_SUCCESS;
1865
0
    }
1866
1867
0
    IGRAPH_CHECK(igraph_copy(&newgraph, graph));
1868
0
    IGRAPH_FINALLY(igraph_destroy, &newgraph);
1869
0
    IGRAPH_CHECK(igraph_to_directed(&newgraph, IGRAPH_TO_DIRECTED_MUTUAL));
1870
1871
0
    IGRAPH_CHECK(igraph_i_st_vertex_connectivity_directed(&newgraph, res,
1872
0
                 source, target,
1873
0
                 IGRAPH_VCONN_NEI_IGNORE));
1874
1875
0
    igraph_destroy(&newgraph);
1876
0
    IGRAPH_FINALLY_CLEAN(1);
1877
1878
0
    return IGRAPH_SUCCESS;
1879
0
}
1880
1881
/**
1882
 * \function igraph_st_vertex_connectivity
1883
 * \brief The vertex connectivity of a pair of vertices.
1884
 *
1885
 * The vertex connectivity of two vertices (\p source and
1886
 * \p target) is the minimum number of vertices that must be
1887
 * deleted to eliminate all paths from \p source to \p
1888
 * target. Directed paths are considered in directed graphs.
1889
 *
1890
 * </para><para>
1891
 * The vertex connectivity of a pair is the same as the number
1892
 * of different (i.e. node-independent) paths from source to
1893
 * target, assuming no direct edges between them.
1894
 *
1895
 * </para><para>
1896
 * The current implementation uses maximum flow calculations to
1897
 * obtain the result.
1898
 *
1899
 * \param graph The input graph.
1900
 * \param res Pointer to an integer, the result will be stored here.
1901
 * \param source The id of the source vertex.
1902
 * \param target The id of the target vertex.
1903
 * \param neighbors A constant giving what to do if the two vertices
1904
 *     are connected. Possible values:
1905
 *     \c IGRAPH_VCONN_NEI_ERROR, stop with an error message,
1906
 *     \c IGRAPH_VCONN_NEI_NEGATIVE, return -1.
1907
 *     \c IGRAPH_VCONN_NEI_NUMBER_OF_NODES, return the number of nodes.
1908
 *     \c IGRAPH_VCONN_NEI_IGNORE, ignore the fact that the two vertices
1909
 *        are connected and calculate the number of vertices needed
1910
 *        to eliminate all paths except for the trivial (direct) paths
1911
 *        between \p source and \p vertex.
1912
 * \return Error code.
1913
 *
1914
 * Time complexity: O(|V|^3), but see the discussion at \ref
1915
 * igraph_maxflow_value().
1916
 *
1917
 * \sa \ref igraph_vertex_connectivity(),
1918
 * \ref igraph_edge_connectivity(),
1919
 * \ref igraph_maxflow_value().
1920
 */
1921
1922
igraph_error_t igraph_st_vertex_connectivity(
1923
        const igraph_t *graph,
1924
        igraph_int_t *res,
1925
        igraph_int_t source,
1926
        igraph_int_t target,
1927
0
        igraph_vconn_nei_t neighbors) {
1928
1929
0
    if (igraph_is_directed(graph)) {
1930
0
        IGRAPH_CHECK(igraph_i_st_vertex_connectivity_directed(graph, res,
1931
0
                     source, target,
1932
0
                     neighbors));
1933
0
    } else {
1934
0
        IGRAPH_CHECK(igraph_i_st_vertex_connectivity_undirected(graph, res,
1935
0
                     source, target,
1936
0
                     neighbors));
1937
0
    }
1938
1939
0
    return IGRAPH_SUCCESS;
1940
0
}
1941
1942
static igraph_error_t igraph_i_vertex_connectivity_directed(
1943
        const igraph_t *graph,
1944
        igraph_int_t *res,
1945
520
        igraph_bool_t all_edges_are_mutual) {
1946
1947
520
    igraph_int_t no_of_nodes = igraph_vcount(graph);
1948
520
    igraph_int_t no_of_edges;
1949
520
    igraph_int_t i, j, k, len;
1950
520
    igraph_int_t minconn = no_of_nodes - 1, conn = 0;
1951
520
    igraph_t split_graph;
1952
520
    igraph_vector_t capacity;
1953
520
    igraph_bool_t done;
1954
520
    igraph_int_t dummy_num_connections;
1955
520
    igraph_vector_int_t incs;
1956
520
    igraph_real_t real_res;
1957
1958
    /* Create the new graph */
1959
520
    IGRAPH_CHECK(igraph_i_split_vertices(graph, &split_graph));
1960
520
    IGRAPH_FINALLY(igraph_destroy, &split_graph);
1961
1962
    /* Create the capacity vector, fill it with ones */
1963
520
    no_of_edges = igraph_ecount(&split_graph);
1964
520
    IGRAPH_VECTOR_INIT_FINALLY(&capacity, no_of_edges);
1965
520
    igraph_vector_fill(&capacity, 1);
1966
1967
520
    IGRAPH_VECTOR_INT_INIT_FINALLY(&incs, 0);
1968
1969
8.48k
    for (i = 0; i < no_of_nodes; i++) {
1970
143k
        for (j = all_edges_are_mutual ? i + 1 : 0; j < no_of_nodes; j++) {
1971
135k
            if (i == j) {
1972
1.29k
                continue;
1973
1.29k
            }
1974
1975
134k
            IGRAPH_ALLOW_INTERRUPTION();
1976
1977
            /* Check for easy cases */
1978
134k
            IGRAPH_CHECK(igraph_i_st_vertex_connectivity_check_errors(
1979
134k
                             graph, &conn, i, j, IGRAPH_VCONN_NEI_NUMBER_OF_NODES, &done,
1980
134k
                             &dummy_num_connections
1981
134k
                         ));
1982
1983
            /* 'done' will be set to true if the two vertices are already
1984
             * connected, and in this case 'res' will be set to the number of
1985
             * nodes-1.
1986
             *
1987
             * Also, since we used IGRAPH_VCONN_NEI_NUMBER_OF_NODES,
1988
             * dummy_num_connections will always be zero, no need to deal with
1989
             * it */
1990
134k
            IGRAPH_ASSERT(dummy_num_connections == 0);
1991
1992
134k
            if (!done) {
1993
                /* "Disable" the edges incident on the input half of the source vertex
1994
                * and the output half of the target vertex */
1995
119k
                IGRAPH_CHECK(igraph_incident(&split_graph, &incs, i + no_of_nodes, IGRAPH_ALL, IGRAPH_LOOPS));
1996
119k
                len = igraph_vector_int_size(&incs);
1997
662k
                for (k = 0; k < len; k++) {
1998
543k
                    VECTOR(capacity)[VECTOR(incs)[k]] = 0;
1999
543k
                }
2000
119k
                IGRAPH_CHECK(igraph_incident(&split_graph, &incs, j, IGRAPH_ALL, IGRAPH_LOOPS));
2001
119k
                len = igraph_vector_int_size(&incs);
2002
589k
                for (k = 0; k < len; k++) {
2003
469k
                    VECTOR(capacity)[VECTOR(incs)[k]] = 0;
2004
469k
                }
2005
2006
                /* Do the maximum flow */
2007
119k
                IGRAPH_CHECK(igraph_maxflow_value(
2008
119k
                                 &split_graph, &real_res, i, j + no_of_nodes, &capacity, NULL
2009
119k
                             ));
2010
2011
                /* Restore the capacities */
2012
119k
                IGRAPH_CHECK(igraph_incident(&split_graph, &incs, i + no_of_nodes, IGRAPH_ALL, IGRAPH_LOOPS));
2013
119k
                len = igraph_vector_int_size(&incs);
2014
662k
                for (k = 0; k < len; k++) {
2015
543k
                    VECTOR(capacity)[VECTOR(incs)[k]] = 1;
2016
543k
                }
2017
119k
                IGRAPH_CHECK(igraph_incident(&split_graph, &incs, j, IGRAPH_ALL, IGRAPH_LOOPS));
2018
119k
                len = igraph_vector_int_size(&incs);
2019
589k
                for (k = 0; k < len; k++) {
2020
469k
                    VECTOR(capacity)[VECTOR(incs)[k]] = 1;
2021
469k
                }
2022
2023
119k
                conn = (igraph_int_t) real_res;
2024
119k
            }
2025
2026
134k
            if (conn < minconn) {
2027
769
                minconn = conn;
2028
769
                if (conn == 0) {
2029
0
                    break;
2030
0
                }
2031
769
            }
2032
134k
        }
2033
2034
7.96k
        if (minconn == 0) {
2035
0
            break;
2036
0
        }
2037
7.96k
    }
2038
2039
520
    if (res) {
2040
520
        *res = minconn;
2041
520
    }
2042
2043
520
    igraph_vector_int_destroy(&incs);
2044
520
    igraph_vector_destroy(&capacity);
2045
520
    igraph_destroy(&split_graph);
2046
520
    IGRAPH_FINALLY_CLEAN(3);
2047
2048
520
    return IGRAPH_SUCCESS;
2049
520
}
2050
2051
static igraph_error_t igraph_i_vertex_connectivity_undirected(
2052
        const igraph_t *graph,
2053
398
        igraph_int_t *res) {
2054
2055
398
    igraph_t newgraph;
2056
2057
398
    IGRAPH_CHECK(igraph_copy(&newgraph, graph));
2058
398
    IGRAPH_FINALLY(igraph_destroy, &newgraph);
2059
398
    IGRAPH_CHECK(igraph_to_directed(&newgraph, IGRAPH_TO_DIRECTED_MUTUAL));
2060
2061
398
    IGRAPH_CHECK(igraph_i_vertex_connectivity_directed(&newgraph, res, /* all_edges_are_mutual = */ true));
2062
2063
398
    igraph_destroy(&newgraph);
2064
398
    IGRAPH_FINALLY_CLEAN(1);
2065
2066
398
    return IGRAPH_SUCCESS;
2067
398
}
2068
2069
/* Use that vertex.connectivity(G) <= edge.connectivity(G) <= min(degree(G))
2070
 *
2071
 * Check if the graph is connected, and if its minimum degree is 1.
2072
 * This is sufficient to determine both the vertex and edge connectivity,
2073
 * which are returned in 'res'. 'found' will indicate if the connectivity
2074
 * could be determined.
2075
 */
2076
static igraph_error_t igraph_i_connectivity_checks(
2077
        const igraph_t *graph,
2078
        igraph_int_t *res,
2079
1.70k
        igraph_bool_t *found) {
2080
2081
1.70k
    igraph_bool_t conn;
2082
1.70k
    *found = false;
2083
2084
1.70k
    if (igraph_vcount(graph) == 0) {
2085
2
        *res = 0;
2086
2
        *found = true;
2087
2
        return IGRAPH_SUCCESS;
2088
2
    }
2089
2090
1.70k
    IGRAPH_CHECK(igraph_is_connected(graph, &conn, IGRAPH_STRONG));
2091
1.70k
    if (!conn) {
2092
955
        *res = 0;
2093
955
        *found = true;
2094
955
    } else {
2095
747
        igraph_vector_int_t degree;
2096
747
        IGRAPH_VECTOR_INT_INIT_FINALLY(&degree, 0);
2097
747
        if (!igraph_is_directed(graph)) {
2098
541
            IGRAPH_CHECK(igraph_degree(graph, &degree, igraph_vss_all(),
2099
541
                                       IGRAPH_OUT, IGRAPH_LOOPS));
2100
541
            if (igraph_vector_int_min(&degree) == 1) {
2101
76
                *res = 1;
2102
76
                *found = true;
2103
76
            }
2104
541
        } else {
2105
            /* directed, check both in- & out-degree */
2106
206
            IGRAPH_CHECK(igraph_degree(graph, &degree, igraph_vss_all(),
2107
206
                                       IGRAPH_OUT, IGRAPH_LOOPS));
2108
206
            if (igraph_vector_int_min(&degree) == 1) {
2109
39
                *res = 1;
2110
39
                *found = true;
2111
167
            } else {
2112
167
                IGRAPH_CHECK(igraph_degree(graph, &degree, igraph_vss_all(),
2113
167
                                           IGRAPH_IN, IGRAPH_LOOPS));
2114
167
                if (igraph_vector_int_min(&degree) == 1) {
2115
9
                    *res = 1;
2116
9
                    *found = true;
2117
9
                }
2118
167
            }
2119
206
        }
2120
747
        igraph_vector_int_destroy(&degree);
2121
747
        IGRAPH_FINALLY_CLEAN(1);
2122
747
    }
2123
1.70k
    return IGRAPH_SUCCESS;
2124
1.70k
}
2125
2126
/**
2127
 * \function igraph_vertex_connectivity
2128
 * \brief The vertex connectivity of a graph.
2129
 *
2130
 * </para><para> The vertex connectivity of a graph is the minimum
2131
 * vertex connectivity along each pairs of vertices in the graph.
2132
 * </para>
2133
 *
2134
 * <para> The vertex connectivity of a graph is the same as group
2135
 * cohesion as defined in Douglas R. White and Frank Harary: The
2136
 * cohesiveness of blocks in social networks: node connectivity and
2137
 * conditional density, Sociological Methodology 31:305--359, 2001
2138
 * https://doi.org/10.1111/0081-1750.00098.
2139
 *
2140
 * \param graph The input graph.
2141
 * \param res Pointer to an integer, the result will be stored here.
2142
 * \param checks Boolean constant. Whether to check if the graph is
2143
 *    connected or complete and also the degree of the vertices. If the graph is
2144
 *    not (strongly) connected then the connectivity is obviously zero. Otherwise
2145
 *    if the minimum degree is 1 then the vertex connectivity is also
2146
 *    1. If the graph is complete, the connectivity is the vertex count
2147
 *    minus one. It is a good idea to perform these checks, as they can be
2148
 *    done quickly compared to the connectivity calculation itself.
2149
 *    They were suggested by Peter McMahan, thanks Peter.
2150
 * \return Error code.
2151
 *
2152
 * Time complexity: O(|V|^5).
2153
 *
2154
 * \sa \ref igraph_st_vertex_connectivity(), \ref igraph_maxflow_value(),
2155
 * and \ref igraph_edge_connectivity().
2156
 */
2157
2158
igraph_error_t igraph_vertex_connectivity(
2159
        const igraph_t *graph, igraph_int_t *res,
2160
1.70k
        igraph_bool_t checks) {
2161
2162
1.70k
    igraph_bool_t ret = false;
2163
2164
1.70k
    if (checks) {
2165
1.70k
        IGRAPH_CHECK(igraph_i_connectivity_checks(graph, res, &ret));
2166
1.70k
    }
2167
2168
1.70k
    if (checks && !ret) {
2169
        /* The vertex connectivity of a complete graph is vcount-1 by definition.
2170
         * This check cannot be performed within igraph_i_connectivity_checks(),
2171
         * as that function is used both for vertex and edge connectivities.
2172
         * Checking if the graph is complete does not suffice to determine the
2173
         * edge connectivity of a complete multigraph. */
2174
623
        igraph_bool_t complete;
2175
623
        IGRAPH_CHECK(igraph_is_complete(graph, &complete));
2176
623
        if (complete) {
2177
103
            *res = igraph_vcount(graph) - 1;
2178
103
            ret = true;
2179
103
        }
2180
623
    }
2181
2182
    /* Are we done yet? */
2183
1.70k
    if (!ret) {
2184
520
        if (igraph_is_directed(graph)) {
2185
122
            IGRAPH_CHECK(igraph_i_vertex_connectivity_directed(graph, res, /* all_edges_are_mutual = */ false));
2186
398
        } else {
2187
398
            IGRAPH_CHECK(igraph_i_vertex_connectivity_undirected(graph, res));
2188
398
        }
2189
520
    }
2190
2191
1.70k
    return IGRAPH_SUCCESS;
2192
1.70k
}
2193
2194
/**
2195
 * \function igraph_st_edge_connectivity
2196
 * \brief Edge connectivity of a pair of vertices.
2197
 *
2198
 * The edge connectivity of two vertices (\p source and \p target) is the
2199
 * minimum number of edges that have to be deleted from the graph to eliminate
2200
 * all paths from \p source to \p target.
2201
 *
2202
 * </para><para>This function uses the maximum flow algorithm to calculate
2203
 * the edge connectivity.
2204
 *
2205
 * \param graph The input graph, it has to be directed.
2206
 * \param res Pointer to an integer, the result will be stored here.
2207
 * \param source The id of the source vertex.
2208
 * \param target The id of the target vertex.
2209
 * \return Error code.
2210
 *
2211
 * Time complexity: O(|V|^3).
2212
 *
2213
 * \sa \ref igraph_maxflow_value(), \ref igraph_edge_disjoint_paths(),
2214
 * \ref igraph_edge_connectivity(),
2215
 * \ref igraph_st_vertex_connectivity(), \ref
2216
 * igraph_vertex_connectivity().
2217
 */
2218
2219
igraph_error_t igraph_st_edge_connectivity(const igraph_t *graph,
2220
                                           igraph_int_t *res,
2221
                                           igraph_int_t source,
2222
0
                                           igraph_int_t target) {
2223
2224
0
    igraph_real_t flow;
2225
2226
0
    if (source == target) {
2227
0
        IGRAPH_ERROR("The source and target vertices must be different.", IGRAPH_EINVAL);
2228
0
    }
2229
2230
0
    IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, source, target, NULL, NULL));
2231
0
    *res = (igraph_int_t) flow;
2232
2233
0
    return IGRAPH_SUCCESS;
2234
0
}
2235
2236
2237
/**
2238
 * \function igraph_edge_connectivity
2239
 * \brief The minimum edge connectivity in a graph.
2240
 *
2241
 * </para><para> This is the minimum of the edge connectivity over all
2242
 * pairs of vertices in the graph. </para>
2243
 *
2244
 * <para>
2245
 * The edge connectivity of a graph is the same as group adhesion as
2246
 * defined in Douglas R. White and Frank Harary: The cohesiveness of
2247
 * blocks in social networks: node connectivity and conditional
2248
 * density, Sociological Methodology 31:305--359, 2001
2249
 * https://doi.org/10.1111/0081-1750.00098.
2250
 *
2251
 * \param graph The input graph.
2252
 * \param res Pointer to an integer, the result will be stored here.
2253
 * \param checks Boolean constant. Whether to check that the graph is
2254
 *    connected and also the degree of the vertices. If the graph is
2255
 *    not (strongly) connected then the connectivity is obviously zero. Otherwise
2256
 *    if the minimum degree is one then the edge connectivity is also
2257
 *    one. It is a good idea to perform these checks, as they can be
2258
 *    done quickly compared to the connectivity calculation itself.
2259
 *    They were suggested by Peter McMahan, thanks Peter.
2260
 * \return Error code.
2261
 *
2262
 * Time complexity: O(log(|V|)*|V|^2) for undirected graphs and
2263
 * O(|V|^4) for directed graphs, but see also the discussion at the
2264
 * documentation of \ref igraph_maxflow_value().
2265
 *
2266
 * \sa \ref igraph_st_edge_connectivity(), \ref igraph_maxflow_value(),
2267
 * \ref igraph_vertex_connectivity().
2268
 */
2269
2270
igraph_error_t igraph_edge_connectivity(const igraph_t *graph,
2271
                                        igraph_int_t *res,
2272
0
                                        igraph_bool_t checks) {
2273
2274
0
    igraph_bool_t ret = false;
2275
0
    igraph_int_t number_of_nodes = igraph_vcount(graph);
2276
2277
    /* igraph_mincut_value returns infinity for the singleton graph,
2278
     * which cannot be cast to an integer. We catch this case early
2279
     * and postulate the edge-connectivity of this graph to be 0.
2280
     * This is consistent with what other software packages return. */
2281
0
    if (number_of_nodes <= 1) {
2282
0
        *res = 0;
2283
0
        return IGRAPH_SUCCESS;
2284
0
    }
2285
2286
    /* Use that vertex.connectivity(G) <= edge.connectivity(G) <= min(degree(G)) */
2287
0
    if (checks) {
2288
0
        IGRAPH_CHECK(igraph_i_connectivity_checks(graph, res, &ret));
2289
0
    }
2290
2291
0
    if (!ret) {
2292
0
        igraph_real_t real_res;
2293
0
        IGRAPH_CHECK(igraph_mincut_value(graph, &real_res, 0));
2294
0
        *res = (igraph_int_t)real_res;
2295
0
    }
2296
2297
0
    return IGRAPH_SUCCESS;
2298
0
}
2299
2300
/**
2301
 * \function igraph_edge_disjoint_paths
2302
 * \brief The maximum number of edge-disjoint paths between two vertices.
2303
 *
2304
 * A set of paths between two vertices is called edge-disjoint if they do not
2305
 * share any edges. The maximum number of edge-disjoint paths are calculated
2306
 * by this function using maximum flow techniques. Directed paths are
2307
 * considered in directed graphs.
2308
 *
2309
 * </para><para>Note that the number of disjoint paths is the same as the
2310
 * edge connectivity of the two vertices using uniform edge weights.
2311
 *
2312
 * \param graph The input graph, can be directed or undirected.
2313
 * \param res Pointer to an integer variable, the result will be
2314
 *        stored here.
2315
 * \param source The id of the source vertex.
2316
 * \param target The id of the target vertex.
2317
 * \return Error code.
2318
 *
2319
 * Time complexity: O(|V|^3), but see the discussion at \ref
2320
 * igraph_maxflow_value().
2321
 *
2322
 * \sa \ref igraph_vertex_disjoint_paths(), \ref
2323
 * igraph_st_edge_connectivity(), \ref igraph_maxflow_value().
2324
 */
2325
2326
igraph_error_t igraph_edge_disjoint_paths(const igraph_t *graph,
2327
                                          igraph_int_t *res,
2328
                                          igraph_int_t source,
2329
0
                                          igraph_int_t target) {
2330
2331
0
    igraph_real_t flow;
2332
2333
0
    if (source == target) {
2334
0
        IGRAPH_ERROR("Not implemented when the source and target are the same.",
2335
0
                     IGRAPH_UNIMPLEMENTED);
2336
0
    }
2337
2338
0
    IGRAPH_CHECK(igraph_maxflow_value(graph, &flow, source, target, NULL, NULL));
2339
2340
0
    *res = (igraph_int_t) flow;
2341
2342
0
    return IGRAPH_SUCCESS;
2343
0
}
2344
2345
/**
2346
 * \function igraph_vertex_disjoint_paths
2347
 * \brief Maximum number of vertex-disjoint paths between two vertices.
2348
 *
2349
 * A set of paths between two vertices is called vertex-disjoint if
2350
 * they share no vertices, other than the endpoints. This function computes
2351
 * the largest number of such paths that can be constructed between
2352
 * a source and a target vertex. The calculation is performed by using maximum
2353
 * flow techniques.
2354
 *
2355
 * </para><para>
2356
 * When there are no edges from the source to the target, the number of
2357
 * vertex-disjoint paths is the same as the vertex connectivity of
2358
 * the two vertices. When some edges are present, each one of them
2359
 * contributes one extra path.
2360
 *
2361
 * \param graph The input graph.
2362
 * \param res Pointer to an integer variable, the result will be
2363
 *        stored here.
2364
 * \param source The id of the source vertex.
2365
 * \param target The id of the target vertex.
2366
 * \return Error code.
2367
 *
2368
 * Time complexity: O(|V|^3).
2369
 *
2370
 * \sa \ref igraph_edge_disjoint_paths(),
2371
 * \ref igraph_st_vertex_connectivity(), \ref igraph_maxflow_value().
2372
 */
2373
2374
igraph_error_t igraph_vertex_disjoint_paths(const igraph_t *graph,
2375
                                            igraph_int_t *res,
2376
                                            igraph_int_t source,
2377
0
                                            igraph_int_t target) {
2378
2379
0
    igraph_vector_int_t eids;
2380
2381
0
    if (source == target) {
2382
0
        IGRAPH_ERROR("Not implemented when the source and target are the same.",
2383
0
                     IGRAPH_UNIMPLEMENTED);
2384
0
    }
2385
2386
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(&eids, 4);
2387
0
    IGRAPH_CHECK(igraph_get_all_eids_between(graph, &eids, source, target, /*directed*/ true));
2388
2389
0
    if (igraph_is_directed(graph)) {
2390
0
        IGRAPH_CHECK(igraph_i_st_vertex_connectivity_directed(graph, res,
2391
0
                     source, target,
2392
0
                     IGRAPH_VCONN_NEI_IGNORE));
2393
0
    } else {
2394
0
        IGRAPH_CHECK(igraph_i_st_vertex_connectivity_undirected(graph, res,
2395
0
                     source, target,
2396
0
                     IGRAPH_VCONN_NEI_IGNORE));
2397
0
    }
2398
2399
0
    *res += igraph_vector_int_size(&eids);
2400
2401
0
    igraph_vector_int_destroy(&eids);
2402
0
    IGRAPH_FINALLY_CLEAN(1);
2403
2404
0
    return IGRAPH_SUCCESS;
2405
0
}
2406
2407
/**
2408
 * \function igraph_adhesion
2409
 * \brief Graph adhesion, this is (almost) the same as edge connectivity.
2410
 *
2411
 * </para><para> This quantity is defined by White and Harary in
2412
 * The cohesiveness of blocks in social networks: node connectivity and
2413
 * conditional density, (Sociological Methodology 31:305--359, 2001)
2414
 * and basically it is the edge connectivity of the graph
2415
 * with uniform edge weights.
2416
 *
2417
 * \param graph The input graph, either directed or undirected.
2418
 * \param res Pointer to an integer, the result will be stored here.
2419
 * \param checks Boolean constant. Whether to check that the graph is
2420
 *    connected and also the degree of the vertices. If the graph is
2421
 *    not (strongly) connected then the adhesion is obviously zero. Otherwise
2422
 *    if the minimum degree is one then the adhesion is also
2423
 *    one. It is a good idea to perform these checks, as they can be
2424
 *    done quickly compared to the edge connectivity calculation itself.
2425
 *    They were suggested by Peter McMahan, thanks Peter.
2426
* \return Error code.
2427
 *
2428
 * Time complexity: O(log(|V|)*|V|^2) for undirected graphs and
2429
 * O(|V|^4) for directed graphs, but see also the discussion at the
2430
 * documentation of \ref igraph_maxflow_value().
2431
 *
2432
 * \sa \ref igraph_cohesion(), \ref igraph_maxflow_value(), \ref
2433
 * igraph_edge_connectivity(), \ref igraph_mincut_value().
2434
 */
2435
2436
igraph_error_t igraph_adhesion(const igraph_t *graph,
2437
                               igraph_int_t *res,
2438
0
                               igraph_bool_t checks) {
2439
0
    return igraph_edge_connectivity(graph, res, checks);
2440
0
}
2441
2442
/**
2443
 * \function igraph_cohesion
2444
 * \brief Graph cohesion, this is the same as vertex connectivity.
2445
 *
2446
 * </para><para> This quantity was defined by White and Harary in <quote>The
2447
 * cohesiveness of blocks in social networks: node connectivity and
2448
 * conditional density</quote>, (Sociological Methodology 31:305--359, 2001)
2449
 * and it is the same as the vertex connectivity of a graph.
2450
 *
2451
 * \param graph The input graph.
2452
 * \param res Pointer to an integer variable, the result will be
2453
 *        stored here.
2454
 * \param checks Boolean constant. Whether to check that the graph is
2455
 *    connected and also the degree of the vertices. If the graph is
2456
 *    not (strongly) connected then the cohesion is obviously zero. Otherwise
2457
 *    if the minimum degree is one then the cohesion is also
2458
 *    one. It is a good idea to perform these checks, as they can be
2459
 *    done quickly compared to the vertex connectivity calculation itself.
2460
 *    They were suggested by Peter McMahan, thanks Peter.
2461
 * \return Error code.
2462
 *
2463
 * Time complexity: O(|V|^4), |V| is the number of vertices. In
2464
 * practice it is more like O(|V|^2), see \ref igraph_maxflow_value().
2465
 *
2466
 * \sa \ref igraph_vertex_connectivity(), \ref igraph_adhesion(),
2467
 * \ref igraph_maxflow_value().
2468
 */
2469
2470
igraph_error_t igraph_cohesion(const igraph_t *graph,
2471
                               igraph_int_t *res,
2472
0
                               igraph_bool_t checks) {
2473
2474
0
    IGRAPH_CHECK(igraph_vertex_connectivity(graph, res, checks));
2475
0
    return IGRAPH_SUCCESS;
2476
0
}
2477
2478
/**
2479
 * \function igraph_gomory_hu_tree
2480
 * \brief Gomory-Hu tree of a graph.
2481
 *
2482
 * </para><para>
2483
 * The Gomory-Hu tree is a concise representation of the value of all the
2484
 * maximum flows (or minimum cuts) in a graph. The vertices of the tree
2485
 * correspond exactly to the vertices of the original graph in the same order.
2486
 * Edges of the Gomory-Hu tree are annotated by flow values.  The value of
2487
 * the maximum flow (or minimum cut) between an arbitrary (u,v) vertex
2488
 * pair in the original graph is then given by the minimum flow value (i.e.
2489
 * edge annotation) along the shortest path between u and v in the
2490
 * Gomory-Hu tree.
2491
 *
2492
 * </para><para>This implementation uses Gusfield's algorithm to construct the
2493
 * Gomory-Hu tree. See the following paper for more details:
2494
 *
2495
 * </para><para>
2496
 * Reference:
2497
 *
2498
 * </para><para>
2499
 * Gusfield D: Very simple methods for all pairs network flow analysis. SIAM J
2500
 * Comput 19(1):143-155, 1990
2501
 * https://doi.org/10.1137/0219009.
2502
 *
2503
 * \param graph The input graph.
2504
 * \param tree  Pointer to an uninitialized graph; the result will be
2505
 *              stored here.
2506
 * \param flows Pointer to an uninitialized vector; the flow values
2507
 *              corresponding to each edge in the Gomory-Hu tree will
2508
 *              be returned here. You may pass a NULL pointer here if you are
2509
 *              not interested in the flow values.
2510
 * \param capacity Vector containing the capacity of the edges. If NULL, then
2511
 *        every edge is considered to have capacity 1.0.
2512
 * \return Error code.
2513
 *
2514
 * Time complexity: O(|V|^4) since it performs a max-flow calculation
2515
 * between vertex zero and every other vertex and max-flow is
2516
 * O(|V|^3).
2517
 *
2518
 * \sa \ref igraph_maxflow()
2519
 */
2520
igraph_error_t igraph_gomory_hu_tree(const igraph_t *graph,
2521
                                     igraph_t *tree,
2522
                                     igraph_vector_t *flows,
2523
0
                                     const igraph_vector_t *capacity) {
2524
2525
0
    igraph_int_t no_of_nodes = igraph_vcount(graph);
2526
0
    igraph_int_t source, target, mid, i, n;
2527
0
    igraph_vector_int_t neighbors;
2528
0
    igraph_vector_t flow_values;
2529
0
    igraph_vector_int_t partition;
2530
0
    igraph_vector_int_t partition2;
2531
0
    igraph_real_t flow_value;
2532
2533
0
    if (igraph_is_directed(graph)) {
2534
0
        IGRAPH_ERROR("Gomory-Hu tree can only be calculated for undirected graphs.",
2535
0
                     IGRAPH_EINVAL);
2536
0
    }
2537
2538
    /* Allocate memory */
2539
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(&neighbors, no_of_nodes);
2540
0
    IGRAPH_VECTOR_INIT_FINALLY(&flow_values, no_of_nodes);
2541
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(&partition, 0);
2542
0
    IGRAPH_VECTOR_INT_INIT_FINALLY(&partition2, 0);
2543
2544
    /* Initialize the tree: every edge points to node 0 */
2545
    /* Actually, this is done implicitly since both 'neighbors' and 'flow_values' are
2546
     * initialized to zero already */
2547
2548
    /* For each source vertex except vertex zero... */
2549
0
    for (source = 1; source < no_of_nodes; source++) {
2550
0
        IGRAPH_ALLOW_INTERRUPTION();
2551
0
        IGRAPH_PROGRESS("Gomory-Hu tree", (100.0 * (source - 1)) / (no_of_nodes - 1), 0);
2552
2553
        /* Find its current neighbor in the tree */
2554
0
        target = VECTOR(neighbors)[source];
2555
2556
        /* Find the maximum flow between source and target */
2557
0
        IGRAPH_CHECK(igraph_maxflow(graph, &flow_value, NULL, NULL, &partition, &partition2,
2558
0
                                    source, target, capacity, 0));
2559
2560
        /* Store the maximum flow */
2561
0
        VECTOR(flow_values)[source] = flow_value;
2562
2563
        /* Update the tree */
2564
        /* igraph_maxflow() guarantees that the source vertex will be in &partition
2565
         * and not in &partition2 so we need to iterate over &partition to find
2566
         * all the nodes that are of interest to us */
2567
0
        n = igraph_vector_int_size(&partition);
2568
0
        for (i = 0; i < n; i++) {
2569
0
            mid = VECTOR(partition)[i];
2570
0
            if (mid != source) {
2571
0
                if (VECTOR(neighbors)[mid] == target) {
2572
0
                    VECTOR(neighbors)[mid] = source;
2573
0
                } else if (VECTOR(neighbors)[target] == mid) {
2574
0
                    VECTOR(neighbors)[target] = source;
2575
0
                    VECTOR(neighbors)[source] = mid;
2576
0
                    VECTOR(flow_values)[source] = VECTOR(flow_values)[target];
2577
0
                    VECTOR(flow_values)[target] = flow_value;
2578
0
                }
2579
0
            }
2580
0
        }
2581
0
    }
2582
2583
0
    IGRAPH_PROGRESS("Gomory-Hu tree", 100.0, 0);
2584
2585
    /* Re-use the 'partition' vector as an edge list now */
2586
0
    IGRAPH_CHECK(igraph_vector_int_resize(&partition, no_of_nodes > 0 ? 2 * (no_of_nodes - 1) : 0));
2587
0
    for (i = 1, mid = 0; i < no_of_nodes; i++, mid += 2) {
2588
0
        VECTOR(partition)[mid]   = i;
2589
0
        VECTOR(partition)[mid + 1] = VECTOR(neighbors)[i];
2590
0
    }
2591
2592
    /* Create the tree graph; we use igraph_subgraph_from_edges here to keep the
2593
     * graph and vertex attributes */
2594
0
    IGRAPH_CHECK(igraph_subgraph_from_edges(graph, tree, igraph_ess_none(), 0));
2595
0
    IGRAPH_CHECK(igraph_add_edges(tree, &partition, 0));
2596
2597
    /* Free the allocated memory */
2598
0
    igraph_vector_int_destroy(&partition2);
2599
0
    igraph_vector_int_destroy(&partition);
2600
0
    igraph_vector_int_destroy(&neighbors);
2601
0
    IGRAPH_FINALLY_CLEAN(3);
2602
2603
    /* Return the flow values to the caller */
2604
0
    if (flows != 0) {
2605
0
        IGRAPH_CHECK(igraph_vector_update(flows, &flow_values));
2606
0
        if (no_of_nodes > 0) {
2607
0
            igraph_vector_remove(flows, 0);
2608
0
        }
2609
0
    }
2610
2611
    /* Free the remaining allocated memory */
2612
0
    igraph_vector_destroy(&flow_values);
2613
0
    IGRAPH_FINALLY_CLEAN(1);
2614
2615
0
    return IGRAPH_SUCCESS;
2616
0
}