Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_kgraph.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
70# ifndef TPL_KGRAPH_H
71# define TPL_KGRAPH_H
72
73# include <ah-graph-concepts.H>
74
75# include <limits>
76# include <tpl_dynSetTree.H>
77# include <tpl_net.H>
78# include <cookie_guard.H>
79
80namespace Aleph
81{
109 template <AlephGraph GT,
110 template <class> class Max_Flow = Random_Preflow_Maximum_Flow,
113 {
114 const SA sa;
116 << "edge_connectivity() does not work on digraphs";
117
118 const auto num_nodes = g.get_num_nodes();
119 if (num_nodes == 0)
120 return 0;
121
122 typename GT::Node *source_node = nullptr;
123 long min_degree = std::numeric_limits<long>::max();
124 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
125 {
126 auto p = it.get_curr();
127 long degree = 0;
128 for (Node_Arc_Iterator<GT, SA> it_arc(p, sa); it_arc.has_curr();
129 it_arc.next_ne())
130 ++degree;
131 if (degree < min_degree)
132 {
133 min_degree = degree;
134 source_node = p;
135 }
136 }
137
139 if (dfs(g, source_node) != num_nodes)
140 return 0;
141
142 if (min_degree <= 1)
143 return min_degree;
144
146 Net net;
147
148 // Cookie_Guard clears cookies when function exits (prevents dangling pointers)
149 Cookie_Guard<GT> cookie_guard(g, true, false);
150
151 typename Net::Node *source = nullptr;
152 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
153 {
154 auto p = it.get_curr();
155 auto q = net.insert_node();
156 NODE_COOKIE(p) = q;
157 if (p == source_node)
158 source = q;
159 }
160
161 for (Arc_Iterator<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
162 {
163 auto a = it.get_curr();
164 auto src = mapped_node<GT, Net>(g.get_src_node(a));
165 auto tgt = mapped_node<GT, Net>(g.get_tgt_node(a));
166 net.insert_arc(tgt, src, typename Net::Flow_Type(1));
167 net.insert_arc(src, tgt, typename Net::Flow_Type(1));
168 }
169
170 long min_k = min_degree;
171 const typename Net::Flow_Type super_cap =
172 static_cast<typename Net::Flow_Type>(min_degree) + 1;
173
175 for (Node_Iterator<Net> it(net); it.has_curr(); it.next_ne())
176 {
177 auto node = it.get_curr();
178 if (node != source)
179 sinks.append(node);
180 }
181
183 it.has_curr(); it.next_ne())
184 {
185 const auto sink = it.get_curr();
186 const auto super_source = net.insert_node();
187 const auto super_sink = net.insert_node();
188 net.insert_arc(super_source, source, super_cap);
189 net.insert_arc(sink, super_sink, super_cap);
190
191 if (const typename Net::Flow_Type flow = Max_Flow<Net>()(net); flow < min_k)
192 min_k = flow;
193
194 net.remove_node(super_source);
195 net.remove_node(super_sink);
196 net.reset(); // reset flow to zero
197 }
198
199 return min_k;
200 }
201
209 template <AlephGraph GT,
210 template <class> class Max_Flow = Heap_Preflow_Maximum_Flow>
212 {
213 public:
222 };
223
224
262 template <AlephGraph GT,
263 template <class> class Max_Flow = Heap_Preflow_Maximum_Flow,
269 {
270 const SA sa;
271 l.empty();
272 r.empty();
273 cut.empty();
274
276 << "compute_min_cut() does not work on digraphs";
277
278 const auto num_nodes = g.get_num_nodes();
279 if (num_nodes == 0)
280 return 0;
281
282 typename GT::Node *source_node = nullptr;
283 long min_degree = std::numeric_limits<long>::max();
284 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
285 {
286 auto p = it.get_curr();
287 long degree = 0;
288 for (Node_Arc_Iterator<GT, SA> it_arc(p, sa); it_arc.has_curr();
289 it_arc.next_ne())
290 ++degree;
291 if (degree < min_degree)
292 {
293 min_degree = degree;
294 source_node = p;
295 }
296 }
297
299 if (dfs(g, source_node) != num_nodes)
300 {
301 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
302 {
303 auto p = it.get_curr();
305 l.insert(p);
306 else
307 r.insert(p);
308 }
309 return 0;
310 }
311
312 if (min_degree <= 1)
313 {
314 if (source_node != nullptr)
316
317 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
318 {
319 auto p = it.get_curr();
320 if (p != source_node)
321 r.insert(p);
322 }
323
325 it.has_curr(); it.next_ne())
326 {
327 auto arc = it.get_curr();
328 auto other = g.get_connected_node(arc, source_node);
329 if (other != source_node)
330 cut.append(arc);
331 }
332
333 return min_degree;
334 }
335
337 Net net;
340 typename Net::Node *source = nullptr;
341 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
342 {
343 auto p = it.get_curr();
344 auto q = net.insert_node();
345 NODE_COOKIE(p) = nullptr;
346 GT::map_nodes(p, q);
347 net_node_map.insert(q, p);
348 if (p == source_node)
349 source = q;
350 }
351
352 for (Arc_Iterator<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
353 {
354 auto a = it.get_curr();
355 auto src = mapped_node<GT, Net>(g.get_src_node(a));
356 auto tgt = mapped_node<GT, Net>(g.get_tgt_node(a));
357 auto arc = net.insert_arc(tgt, src, static_cast<typename Net::Flow_Type>(1));
358 ARC_COOKIE(arc) = a;
359 net_arc_map.insert(arc, a);
360
361 arc = net.insert_arc(src, tgt, static_cast<typename Net::Flow_Type>(1));
362 ARC_COOKIE(arc) = a;
363 net_arc_map.insert(arc, a);
364 }
365
368 long min_k = std::numeric_limits<long>::max();
369 const typename Net::Flow_Type super_cap =
370 static_cast<typename Net::Flow_Type>(min_degree) + 1;
371
373 for (Node_Iterator<Net> it(net); it.has_curr(); it.next_ne())
374 if (auto node = it.get_curr(); node != source)
375 sinks.append(node);
376
378 it.has_curr(); it.next_ne())
379 {
380 auto sink = it.get_curr();
381 auto super_source = net.insert_node();
382 auto super_sink = net.insert_node();
383 net.insert_arc(super_source, source, super_cap);
384 net.insert_arc(sink, super_sink, super_cap);
385
388 const auto flow = Min_Cut<Net, Max_Flow>()(net, vs, vt, cuts, cutt);
389
390 if (flow < min_k)
391 {
394
396 it.has_curr(); it.next_ne())
397 if (auto node = it.get_curr(); net_node_map.contains(node))
398 vs_filtered.insert(node);
399
401 it.has_curr(); it.next_ne())
402 if (auto node = it.get_curr(); net_node_map.contains(node))
403 vt_filtered.insert(node);
404
406 it.has_curr(); it.next_ne())
407 if (auto arc = it.get_curr(); net_arc_map.contains(arc))
408 cuts_filtered.append(arc);
409
411 it.has_curr(); it.next_ne())
412 if (auto arc = it.get_curr(); net_arc_map.contains(arc))
413 cutt_filtered.append(arc);
414
415 min_k = flow;
416 tmp_vs.swap(vs_filtered);
417 tmp_vt.swap(vt_filtered);
420 }
421
422 net.remove_node(super_source);
423 net.remove_node(super_sink);
424 net.reset(); // reset flow to zero
425 }
426
428 it.has_curr(); it.next_ne())
429 l.insert(net_node_map.find(it.get_curr()));
430
432 it.has_curr(); it.next_ne())
433 r.insert(net_node_map.find(it.get_curr()));
434
436 it.has_curr(); it.next_ne())
437 {
438 typename Net::Arc *arc = it.get_curr();
439 cut.append(net_arc_map.find(arc));
440 }
441
442 return min_k;
443 }
444
453 template <AlephGraph GT,
454 template <class> class Max_Flow = Heap_Preflow_Maximum_Flow,
457 {
458 public:
467 };
468
469
496 template <AlephGraph GT,
497 template <class> class Max_Flow = Random_Preflow_Maximum_Flow,
500 {
501 const SA sa;
503 << "vertex_connectivity() does not work on digraphs";
504
505 const auto num_nodes = g.get_num_nodes();
506 if (num_nodes <= 1)
507 return 0;
508
509 typename GT::Node *source_node = nullptr;
510 long min_degree = std::numeric_limits<long>::max();
511 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
512 {
513 auto p = it.get_curr();
514 long degree = 0;
515 for (Node_Arc_Iterator<GT, SA> it_arc(p, sa); it_arc.has_curr();
516 it_arc.next_ne())
517 ++degree;
518 if (degree < min_degree)
519 {
520 min_degree = degree;
521 source_node = p;
522 }
523 }
524
526 if (dfs(g, source_node) != num_nodes)
527 return 0;
528
529 if (min_degree <= 1)
530 return min_degree;
531
533 Net net;
534
535 // Cookie_Guard clears cookies when function exits (prevents dangling pointers)
536 Cookie_Guard<GT> cookie_guard(g, true, false);
537
538 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
539 {
540 auto p = it.get_curr();
541 NODE_COOKIE(p) = net.insert_node();
542 }
543
544 for (Arc_Iterator<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
545 {
546 auto a = it.get_curr();
547 auto src = mapped_node<GT, Net>(g.get_src_node(a));
548 auto tgt = mapped_node<GT, Net>(g.get_tgt_node(a));
549 net.insert_arc(tgt, src, static_cast<typename Net::Flow_Type>(1));
550 net.insert_arc(src, tgt, static_cast<typename Net::Flow_Type>(1));
551 }
552
553 long min_k = min_degree;
554
555 for (Node_Iterator<Net> k(net); k.has_curr() and min_k > 1; k.next_ne())
556 {
557 auto source = k.get_curr();
559 for (_In_Iterator<Net> it(source); it.has_curr(); it.next_ne())
560 to_source_list.append(it.get_curr());
561
563 it.has_curr(); it.next_ne())
564 net.disconnect_arc(it.get_curr());
565
566 {
568 for (j.next(); j.has_curr(); j.next_ne())
569 {
570 auto sink = j.get_curr();
571 if (search_arc<Net>(net, source, sink) != nullptr)
572 continue; // adjacent nodes: skip to next sink
573
575
576 for (_Out_Iterator<Net> it(sink); it.has_curr(); it.next_ne())
577 from_sink_arcs.append(it.get_curr());
578
580 it(from_sink_arcs); it.has_curr(); it.next_ne())
581 net.disconnect_arc(it.get_curr());
582
583 {
584 // Build node-splitting network to model vertex capacities.
585 Net aux_net;
586 {
588 for (Node_Iterator<Net> it(net); it.has_curr(); it.next_ne())
589 {
590 auto p = it.get_curr();
591 if (p == source or p == sink)
592 {
593 NODE_COOKIE(p) = aux_net.insert_node();
594 continue;
595 }
596
597 auto ps = aux_net.insert_node(p->get_info());
598 auto pt = aux_net.insert_node(p->get_info());
599 map.insert(p, aux_net.insert_arc(ps, pt, typename Net::Flow_Type(1)));
600 }
601
602 for (Arc_Iterator<Net> it(net); it.has_curr(); it.next_ne())
603 {
604 auto a = it.get_curr();
605 auto nsrc = net.get_src_node(a);
606 auto ntgt = net.get_tgt_node(a);
607 typename Net::Node *asrc = nullptr;
608 typename Net::Node *atgt = nullptr;
609
610 if (nsrc == source)
611 asrc = static_cast<typename Net::Node *>(NODE_COOKIE(nsrc));
612 else
613 {
614 auto arc = map.find(nsrc);
615 asrc = aux_net.get_tgt_node(arc);
616 }
617
618 if (ntgt == sink)
619 atgt = static_cast<typename Net::Node *>(NODE_COOKIE(ntgt));
620 else
621 {
622 auto arc = map.find(ntgt);
623 atgt = aux_net.get_src_node(arc);
624 }
625 aux_net.insert_arc(asrc, atgt, typename Net::Flow_Type(1));
626 }
627 } // end mapping block
628
629 const auto flow = Max_Flow<Net>()(aux_net);
630 if (flow < min_k)
631 min_k = flow;
632 }
633
634 while (not from_sink_arcs.is_empty())
635 net.connect_arc(from_sink_arcs.get());
636
637 net.reset(); // reset flow to zero
638 }
639
640 while (not to_source_list.is_empty())
641 net.connect_arc(to_source_list.get());
642 }
643 }
644
645 return min_k;
646 }
647} // end namespace Aleph
648
649# endif // TPL_KGRAPH_H
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
C++20 concepts for the protocol shared by graph algorithms.
List_Graph< Graph_Node< Node_Info >, Graph_Arc< Arc_Info > > GT
int num_nodes
Definition btreepic.C:410
Functor wrapper for compute_min_cut().
Definition tpl_kgraph.H:457
long operator()(GT &g, DynSetTree< typename GT::Node * > &l, DynSetTree< typename GT::Node * > &r, DynDlist< typename GT::Arc * > &cut)
Compute a minimum edge cut for g.
Definition tpl_kgraph.H:460
RAII guard that clears graph cookies on destruction.
Stateful depth-first traversal functor.
bool has_curr() const noexcept
Return true the iterator has an current arc.
Definition tpl_graph.H:1726
Iterator dynamic list.
Dynamic doubly linked list with O(1) size and bidirectional access.
void empty() noexcept
@brief Empties the container.
T & append(const T &item)
Append a copied item at the end of the list.
Iterator on the items of list.
Definition htlist.H:1420
Doubly-linked list (defined in tpl_dynList.H).
Definition htlist.H:1155
T & insert(const T &item)
Definition htlist.H:1220
void empty() noexcept
empty the list
Definition htlist.H:1389
Dynamic map implemented with a treap.
Pair * insert(const Key &key, const Data &data)
Insert a key-value pair.
Data & find(const Key &key)
Find the value associated with key.
Dynamic set backed by balanced binary search trees with automatic memory management.
Functor wrapper for edge_connectivity().
Definition tpl_kgraph.H:212
long operator()(GT &g)
Compute edge connectivity of g.
Definition tpl_kgraph.H:221
void next()
Advances the iterator to the next filtered element.
void next_ne() noexcept
Advances the iterator to the next filtered element (noexcept version).
bool has_curr() const noexcept
Definition htlist.H:930
Filtered iterator on the nodes of a graph.
Definition tpl_graph.H:1207
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:779
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:737
bool is_digraph() const noexcept
Return true if the graph this is directed.
Definition graph-dry.H:699
Node * get_connected_node(Arc *arc, Node *node) const noexcept
Return the adjacent node to node through arc.
Definition graph-dry.H:820
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:785
static void map_nodes(N1 *p, N2 *q) noexcept
Map the nodes through their cookies.
Definition graph-dry.H:1043
RAII guards for graph node/arc cookies.
long edge_connectivity(GT &g)
Compute edge connectivity (arc connectivity) of an undirected graph.
Definition tpl_kgraph.H:112
#define ARC_COOKIE(p)
Return the arc cookie
long compute_min_cut(GT &g, DynSetTree< typename GT::Node * > &l, DynSetTree< typename GT::Node * > &r, DynDlist< typename GT::Arc * > &cut)
Compute a minimum edge cut of an undirected graph.
Definition tpl_kgraph.H:265
#define IS_NODE_VISITED(p, bit)
Determine whether the control bit is set or not to one.
#define NODE_COOKIE(p)
Return the node cookie
long vertex_connectivity(GT &g)
Compute vertex connectivity of an undirected graph.
Definition tpl_kgraph.H:499
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
@ Depth_First
Definition aleph-graph.H:73
Net_Graph< Net_Node< string >, Net_Arc< Empty_Class, FlowType > > Net
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
Filtered iterator on all the arcs of a graph.
Definition tpl_graph.H:1165
Default filter for filtered iterators on arcs.
Definition tpl_graph.H:1001
Functor wrapper for heap_preflow_maximum_flow().
Definition tpl_net.H:1812
Arc of a flow network implemented with adjacency lists.
Definition tpl_net.H:115
Flow network implemented with adjacency lists.
Definition tpl_net.H:261
Node * insert_node(const Node_Type &node_info)
Insert a new node by copying node_info.
Definition tpl_net.H:559
Arc * connect_arc(Arc *arc)
Connect a previously disconnected arc.
Definition tpl_net.H:641
Arc * insert_arc(Node *src_node, Node *tgt_node, const Flow_Type &cap, const Flow_Type &flow, const typename Arc::Arc_Type &arc_info=Arc_Type())
Insert a capacitated arc with an initial flow.
Definition tpl_net.H:607
void disconnect_arc(Arc *arc) noexcept
Disconnect arc arc from the graph without deleting it.
Definition tpl_net.H:690
ArcT Arc
Arc type.
Definition tpl_net.H:272
typename Arc::Flow_Type Flow_Type
Capacity/flow numeric type.
Definition tpl_net.H:278
void remove_node(Node *p) noexcept override
Remove node p and all its arcs from the network.
Definition tpl_net.H:704
NodeT Node
Node type.
Definition tpl_net.H:275
void reset()
Reset all arc flows to zero.
Definition tpl_net.H:793
Filtered iterator of adjacent arcs of a node.
Definition tpl_graph.H:1120
Functor wrapper for random_preflow_maximum_flow().
Definition tpl_net.H:1842
static int * k
gsl_rng * r
Dynamic set implementations based on balanced binary search trees.
Network flow graph structures.
DynList< int > l