Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
min_mean_cycle_example.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
31
43# include <cmath>
44# include <iomanip>
45# include <iostream>
46# include <string>
47
48# include <Min_Mean_Cycle.H>
49# include <tpl_graph.H>
50
51using namespace std;
52using namespace Aleph;
53
54namespace
55{
57 using Arc = Graph::Arc;
58
62 struct Arc_Visible
63 {
64 Arc * blocked = nullptr;
65
72 bool operator()(Arc * arc) const noexcept
73 {
74 return arc != blocked;
75 }
76 };
77
78
94 void print_result(const Graph & g,
95 const string & title,
97 {
98 cout << title << '\n';
99
100 if (not r.has_cycle)
101 {
102 cout << " no directed cycle\n\n";
103 return;
104 }
105
106 cout << fixed << setprecision(6);
107 cout << " minimum mean = " << r.minimum_mean << '\n';
108
109 if (r.cycle_length == 0)
110 {
111 cout << " witness cycle unavailable\n\n";
112 return;
113 }
114
115 // Recomputed from witness cycle cost/length as a sanity check against
116 // r.minimum_mean (they should agree up to numerical precision).
117 // Note: witness_mean is derived from total_cost/length to verify r.minimum_mean.
118 const long double witness_mean = static_cast<long double>(r.cycle_total_cost)
119 / static_cast<long double>(r.cycle_length);
120
121 if (std::abs(witness_mean - static_cast<long double>(r.minimum_mean)) > 1e-9)
122 {
123 cerr << "Sanity check failed: witness mean " << witness_mean
124 << " != minimum mean " << r.minimum_mean << endl;
125 abort();
126 }
127
128 cout << " witness cycle: cost=" << r.cycle_total_cost
129 << ", length=" << r.cycle_length
130 << ", mean=" << witness_mean << '\n';
131
132 cout << " nodes: ";
133 bool first = true;
134 for (auto it = r.cycle_nodes.get_it(); it.has_curr(); it.next_ne())
135 {
136 if (not first)
137 cout << " -> ";
138 first = false;
139 cout << it.get_curr()->get_info();
140 }
141 cout << '\n';
142
143 cout << " arcs: ";
144 first = true;
145 for (auto it = r.cycle_arcs.get_it(); it.has_curr(); it.next_ne())
146 {
147 Arc * arc = it.get_curr();
148 if (not first)
149 cout << ", ";
150 first = false;
151
152 cout << g.get_src_node(arc)->get_info()
153 << "->"
154 << g.get_tgt_node(arc)->get_info()
155 << "(" << arc->get_info() << ")";
156 }
157 cout << "\n\n";
158 }
159} // namespace
160
161
177 int main()
178 {
179 Graph g;
180
181 auto * A = g.insert_node("A");
182 auto * B = g.insert_node("B");
183 auto * C = g.insert_node("C");
184 auto * D = g.insert_node("D");
185 auto * E = g.insert_node("E");
186 auto * F = g.insert_node("F");
187
188 // Cycle A->B->C->A has mean 2.0
189 g.insert_arc(A, B, 4.0);
190 g.insert_arc(B, C, 1.0);
191 g.insert_arc(C, A, 1.0);
192
193 // Cycle B->D->E->B has mean 1.0 (optimal in full graph)
194 g.insert_arc(B, D, 1.0);
195 Arc * blocked = g.insert_arc(D, E, 1.0);
196 g.insert_arc(E, B, 1.0);
197
198 // Extra expensive cycle
199 g.insert_arc(C, F, 6.0);
200 g.insert_arc(F, C, 6.0);
201
202 cout << "Minimum mean cycle with Karp (Aleph graphs)\n";
203 cout << "---------------------------------------------\n\n";
204
205 const auto full = karp_minimum_mean_cycle(g);
206 print_result(g, "Full graph", full);
207
209 cout << "Value-only API (full graph): ";
210 if (value_only.has_cycle)
211 cout << "minimum mean = " << value_only.minimum_mean << "\n\n";
212 else
213 cout << "no directed cycle\n\n";
214
215 const auto filtered =
217 g, Dft_Dist<Graph>(), Arc_Visible{blocked});
218 print_result(g, "Filtered graph (blocking D->E)", filtered);
219
220 return 0;
221 }
222
Minimum mean cycle in directed graphs (Karp algorithm).
WeightedDigraph::Arc Arc
Generic directed graph (digraph) wrapper template.
Definition graph-dry.H:3854
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:524
Arc Arc
The node class type.
Definition tpl_graph.H:433
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:604
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:737
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:743
Min_Mean_Cycle_Value_Result karp_minimum_mean_cycle_value(const GT &g, Distance distance=Distance(), SA sa=SA())
Compute only the minimum mean value (without witness walk).
Min_Mean_Cycle_Result< GT, typename Distance::Distance_Type > karp_minimum_mean_cycle(const GT &g, Distance distance=Distance(), SA sa=SA())
Compute minimum mean cycle by Karp's algorithm.
int main()
Example program demonstrating Karp's minimum mean cycle algorithm on Aleph digraphs.
void print_result(const string &label, const Multipoly &poly)
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
STL namespace.
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
Result of minimum mean cycle computation.
gsl_rng * r
Generic graph and digraph implementations.