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 <limits>
74# include <tpl_dynSetTree.H>
75# include <tpl_net.H>
76# include <cookie_guard.H>
77
78namespace Aleph
79{
107 template <class GT,
108 template <class> class Max_Flow = Random_Preflow_Maximum_Flow,
109 class SA = Dft_Show_Arc<GT>>
111 {
112 const SA sa;
114 << "edge_connectivity() does not work on digraphs";
115
116 const auto num_nodes = g.get_num_nodes();
117 if (num_nodes == 0)
118 return 0;
119
120 typename GT::Node *source_node = nullptr;
121 long min_degree = std::numeric_limits<long>::max();
122 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
123 {
124 auto p = it.get_curr();
125 long degree = 0;
126 for (Node_Arc_Iterator<GT, SA> it_arc(p, sa); it_arc.has_curr();
127 it_arc.next_ne())
128 ++degree;
129 if (degree < min_degree)
130 {
131 min_degree = degree;
132 source_node = p;
133 }
134 }
135
137 if (dfs(g, source_node) != num_nodes)
138 return 0;
139
140 if (min_degree <= 1)
141 return min_degree;
142
144 Net net;
145
146 // Cookie_Guard clears cookies when function exits (prevents dangling pointers)
147 Cookie_Guard<GT> cookie_guard(g, true, false);
148
149 typename Net::Node *source = nullptr;
150 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
151 {
152 auto p = it.get_curr();
153 auto q = net.insert_node();
154 NODE_COOKIE(p) = q;
155 if (p == source_node)
156 source = q;
157 }
158
159 for (Arc_Iterator<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
160 {
161 auto a = it.get_curr();
162 auto src = mapped_node<GT, Net>(g.get_src_node(a));
163 auto tgt = mapped_node<GT, Net>(g.get_tgt_node(a));
164 net.insert_arc(tgt, src, typename Net::Flow_Type(1));
165 net.insert_arc(src, tgt, typename Net::Flow_Type(1));
166 }
167
168 long min_k = min_degree;
169 const typename Net::Flow_Type super_cap =
170 static_cast<typename Net::Flow_Type>(min_degree) + 1;
171
173 for (Node_Iterator<Net> it(net); it.has_curr(); it.next_ne())
174 {
175 auto node = it.get_curr();
176 if (node != source)
177 sinks.append(node);
178 }
179
181 it.has_curr(); it.next_ne())
182 {
183 const auto sink = it.get_curr();
184 const auto super_source = net.insert_node();
185 const auto super_sink = net.insert_node();
186 net.insert_arc(super_source, source, super_cap);
187 net.insert_arc(sink, super_sink, super_cap);
188
189 if (const typename Net::Flow_Type flow = Max_Flow<Net>()(net); flow < min_k)
190 min_k = flow;
191
192 net.remove_node(super_source);
193 net.remove_node(super_sink);
194 net.reset(); // reset flow to zero
195 }
196
197 return min_k;
198 }
199
207 template <class GT,
208 template <class> class Max_Flow = Heap_Preflow_Maximum_Flow>
210 {
211 public:
220 };
221
222
260 template <class GT,
261 template <class> class Max_Flow = Heap_Preflow_Maximum_Flow,
262 class SA = Dft_Show_Arc<GT>>
267 {
268 const SA sa;
269 l.empty();
270 r.empty();
271 cut.empty();
272
274 << "compute_min_cut() does not work on digraphs";
275
276 const auto num_nodes = g.get_num_nodes();
277 if (num_nodes == 0)
278 return 0;
279
280 typename GT::Node *source_node = nullptr;
281 long min_degree = std::numeric_limits<long>::max();
282 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
283 {
284 auto p = it.get_curr();
285 long degree = 0;
286 for (Node_Arc_Iterator<GT, SA> it_arc(p, sa); it_arc.has_curr();
287 it_arc.next_ne())
288 ++degree;
289 if (degree < min_degree)
290 {
291 min_degree = degree;
292 source_node = p;
293 }
294 }
295
297 if (dfs(g, source_node) != num_nodes)
298 {
299 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
300 {
301 auto p = it.get_curr();
303 l.insert(p);
304 else
305 r.insert(p);
306 }
307 return 0;
308 }
309
310 if (min_degree <= 1)
311 {
312 if (source_node != nullptr)
314
315 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
316 {
317 auto p = it.get_curr();
318 if (p != source_node)
319 r.insert(p);
320 }
321
323 it.has_curr(); it.next_ne())
324 {
325 auto arc = it.get_curr();
326 auto other = g.get_connected_node(arc, source_node);
327 if (other != source_node)
328 cut.append(arc);
329 }
330
331 return min_degree;
332 }
333
335 Net net;
338 typename Net::Node *source = nullptr;
339 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
340 {
341 auto p = it.get_curr();
342 auto q = net.insert_node();
343 NODE_COOKIE(p) = nullptr;
344 GT::map_nodes(p, q);
345 net_node_map.insert(q, p);
346 if (p == source_node)
347 source = q;
348 }
349
350 for (Arc_Iterator<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
351 {
352 auto a = it.get_curr();
353 auto src = mapped_node<GT, Net>(g.get_src_node(a));
354 auto tgt = mapped_node<GT, Net>(g.get_tgt_node(a));
355 auto arc = net.insert_arc(tgt, src, static_cast<typename Net::Flow_Type>(1));
356 ARC_COOKIE(arc) = a;
357 net_arc_map.insert(arc, a);
358
359 arc = net.insert_arc(src, tgt, static_cast<typename Net::Flow_Type>(1));
360 ARC_COOKIE(arc) = a;
361 net_arc_map.insert(arc, a);
362 }
363
366 long min_k = std::numeric_limits<long>::max();
367 const typename Net::Flow_Type super_cap =
368 static_cast<typename Net::Flow_Type>(min_degree) + 1;
369
371 for (Node_Iterator<Net> it(net); it.has_curr(); it.next_ne())
372 if (auto node = it.get_curr(); node != source)
373 sinks.append(node);
374
376 it.has_curr(); it.next_ne())
377 {
378 auto sink = it.get_curr();
379 auto super_source = net.insert_node();
380 auto super_sink = net.insert_node();
381 net.insert_arc(super_source, source, super_cap);
382 net.insert_arc(sink, super_sink, super_cap);
383
386 const auto flow = Min_Cut<Net, Max_Flow>()(net, vs, vt, cuts, cutt);
387
388 if (flow < min_k)
389 {
392
394 it.has_curr(); it.next_ne())
395 if (auto node = it.get_curr(); net_node_map.contains(node))
396 vs_filtered.insert(node);
397
399 it.has_curr(); it.next_ne())
400 if (auto node = it.get_curr(); net_node_map.contains(node))
401 vt_filtered.insert(node);
402
404 it.has_curr(); it.next_ne())
405 if (auto arc = it.get_curr(); net_arc_map.contains(arc))
407
409 it.has_curr(); it.next_ne())
410 if (auto arc = it.get_curr(); net_arc_map.contains(arc))
412
413 min_k = flow;
418 }
419
420 net.remove_node(super_source);
421 net.remove_node(super_sink);
422 net.reset(); // reset flow to zero
423 }
424
426 it.has_curr(); it.next_ne())
427 l.insert(net_node_map.find(it.get_curr()));
428
430 it.has_curr(); it.next_ne())
431 r.insert(net_node_map.find(it.get_curr()));
432
434 it.has_curr(); it.next_ne())
435 {
436 typename Net::Arc *arc = it.get_curr();
437 cut.append(net_arc_map.find(arc));
438 }
439
440 return min_k;
441 }
442
451 template <class GT,
452 template <class> class Max_Flow = Heap_Preflow_Maximum_Flow,
453 class SA = Dft_Show_Arc<GT>>
455 {
456 public:
465 };
466
467
494 template <class GT,
495 template <class> class Max_Flow = Random_Preflow_Maximum_Flow,
496 class SA = Dft_Show_Arc<GT>>
498 {
499 const SA sa;
501 << "vertex_connectivity() does not work on digraphs";
502
503 const auto num_nodes = g.get_num_nodes();
504 if (num_nodes <= 1)
505 return 0;
506
507 typename GT::Node *source_node = nullptr;
508 long min_degree = std::numeric_limits<long>::max();
509 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
510 {
511 auto p = it.get_curr();
512 long degree = 0;
513 for (Node_Arc_Iterator<GT, SA> it_arc(p, sa); it_arc.has_curr();
514 it_arc.next_ne())
515 ++degree;
516 if (degree < min_degree)
517 {
518 min_degree = degree;
519 source_node = p;
520 }
521 }
522
524 if (dfs(g, source_node) != num_nodes)
525 return 0;
526
527 if (min_degree <= 1)
528 return min_degree;
529
531 Net net;
532
533 // Cookie_Guard clears cookies when function exits (prevents dangling pointers)
534 Cookie_Guard<GT> cookie_guard(g, true, false);
535
536 for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
537 {
538 auto p = it.get_curr();
539 NODE_COOKIE(p) = net.insert_node();
540 }
541
542 for (Arc_Iterator<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
543 {
544 auto a = it.get_curr();
545 auto src = mapped_node<GT, Net>(g.get_src_node(a));
546 auto tgt = mapped_node<GT, Net>(g.get_tgt_node(a));
547 net.insert_arc(tgt, src, static_cast<typename Net::Flow_Type>(1));
548 net.insert_arc(src, tgt, static_cast<typename Net::Flow_Type>(1));
549 }
550
551 long min_k = min_degree;
552
553 for (Node_Iterator<Net> k(net); k.has_curr() and min_k > 1; k.next_ne())
554 {
555 auto source = k.get_curr();
557 for (_In_Iterator<Net> it(source); it.has_curr(); it.next_ne())
558 to_source_list.append(it.get_curr());
559
561 it.has_curr(); it.next_ne())
562 net.disconnect_arc(it.get_curr());
563
564 {
566 for (j.next(); j.has_curr(); j.next_ne())
567 {
568 auto sink = j.get_curr();
569 if (search_arc<Net>(net, source, sink) != nullptr)
570 continue; // adjacent nodes: skip to next sink
571
573
574 for (_Out_Iterator<Net> it(sink); it.has_curr(); it.next_ne())
575 from_sink_arcs.append(it.get_curr());
576
578 it(from_sink_arcs); it.has_curr(); it.next_ne())
579 net.disconnect_arc(it.get_curr());
580
581 {
582 // Build node-splitting network to model vertex capacities.
583 Net aux_net;
584 {
586 for (Node_Iterator<Net> it(net); it.has_curr(); it.next_ne())
587 {
588 auto p = it.get_curr();
589 if (p == source or p == sink)
590 {
591 NODE_COOKIE(p) = aux_net.insert_node();
592 continue;
593 }
594
595 auto ps = aux_net.insert_node(p->get_info());
596 auto pt = aux_net.insert_node(p->get_info());
597 map.insert(p, aux_net.insert_arc(ps, pt, typename Net::Flow_Type(1)));
598 }
599
600 for (Arc_Iterator<Net> it(net); it.has_curr(); it.next_ne())
601 {
602 auto a = it.get_curr();
603 auto nsrc = net.get_src_node(a);
604 auto ntgt = net.get_tgt_node(a);
605 typename Net::Node *asrc = nullptr;
606 typename Net::Node *atgt = nullptr;
607
608 if (nsrc == source)
609 asrc = static_cast<typename Net::Node *>(NODE_COOKIE(nsrc));
610 else
611 {
612 auto arc = map.find(nsrc);
613 asrc = aux_net.get_tgt_node(arc);
614 }
615
616 if (ntgt == sink)
617 atgt = static_cast<typename Net::Node *>(NODE_COOKIE(ntgt));
618 else
619 {
620 auto arc = map.find(ntgt);
621 atgt = aux_net.get_src_node(arc);
622 }
623 aux_net.insert_arc(asrc, atgt, typename Net::Flow_Type(1));
624 }
625 } // end mapping block
626
627 const auto flow = Max_Flow<Net>()(aux_net);
628 if (flow < min_k)
629 min_k = flow;
630 }
631
632 while (not from_sink_arcs.is_empty())
634
635 net.reset(); // reset flow to zero
636 }
637
638 while (not to_source_list.is_empty())
640 }
641 }
642
643 return min_k;
644 }
645} // end namespace Aleph
646
647# endif // TPL_KGRAPH_H
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
int num_nodes
Definition btreepic.C:410
bool has_curr() const noexcept
Return true the iterator has current node.
Functor wrapper for compute_min_cut().
Definition tpl_kgraph.H:455
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:458
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:1645
Iterator dynamic list.
Dynamic doubly linked list with O(1) size and bidirectional access.
void empty() noexcept
Empty the list.
T & append(const T &item)
Append a copied item at the end of the list.
Iterator on the items of list.
Definition htlist.H:1714
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
void empty() noexcept
empty the list
Definition htlist.H:1689
DynList & swap(DynList &l) noexcept
Swap this with l.
Definition htlist.H:1448
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.
Key * insert(const Key &key)
Inserts a key into the dynamic set.
void empty()
remove all elements from the set
Functor wrapper for edge_connectivity().
Definition tpl_kgraph.H:210
long operator()(GT &g)
Compute edge connectivity of g.
Definition tpl_kgraph.H:219
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
Return true if iterator has current item.
Definition htlist.H:1150
constexpr bool is_empty() const noexcept
Return true if list is empty.
Definition htlist.H:523
Filtered iterator on the nodes of a graph.
Definition tpl_graph.H:1206
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:731
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
bool is_digraph() const noexcept
Return true if the graph this is directed.
Definition graph-dry.H:657
Node * get_connected_node(Arc *arc, Node *node) const noexcept
Return the adjacent node to node through arc.
Definition graph-dry.H:772
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:737
static void map_nodes(N1 *p, N2 *q) noexcept
Map the nodes through their cookies.
Definition graph-dry.H:995
RAII guards for graph node/arc cookies.
List_Graph< Graph_Node< int >, Graph_Arc< int > > GT
long edge_connectivity(GT &g)
Compute edge connectivity (arc connectivity) of an undirected graph.
Definition tpl_kgraph.H:110
#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:263
#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:497
@ 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
DynList< T > maps(const C &c, Op op)
Classic map operation.
Filtered iterator on all the arcs of a graph.
Definition tpl_graph.H:1164
Default filter for filtered iterators on arcs.
Definition tpl_graph.H:1000
Functor wrapper for heap_preflow_maximum_flow().
Definition tpl_net.H:1813
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:691
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:705
NodeT Node
Node type.
Definition tpl_net.H:275
void reset()
Reset all arc flows to zero.
Definition tpl_net.H:794
Filtered iterator of adjacent arcs of a node.
Definition tpl_graph.H:1119
Functor wrapper for random_preflow_maximum_flow().
Definition tpl_net.H:1843
Dynamic set implementations based on balanced binary search trees.
Network flow graph structures.
DynList< int > l