Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
hamiltonian.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
80# ifndef HAMILTONIAN_H
81# define HAMILTONIAN_H
82
83# include <ah-graph-concepts.H>
84
85# include <tpl_graph.H>
86
87namespace Aleph
88{
89
129template <AlephGraph GT,
133{
135 SA & sa;
136
145 bool are_adjacent(GT & g, typename GT::Node * src, typename GT::Node * tgt)
146 {
147 (void) g;
148
149 for (Node_Arc_Iterator<GT, SA> it(src, sa); it.has_curr(); it.next_ne())
150 if (it.get_tgt_node_ne() == tgt)
151 return true;
152 return false;
153 }
154
164 bool test_graph(GT & g)
165 {
166 assert(not g.is_digraph());
167
168 const size_t n = g.get_num_nodes();
169
170 // Ore's theorem requires n >= 3
171 if (n < 3)
172 return false;
173
174 // Check all pairs of distinct vertices
175 for (Node_Iterator<GT, SN> i(g, sn); i.has_curr(); i.next_ne())
176 {
177 typename GT::Node * src = i.get_curr();
178 const size_t nsrc = g.get_num_arcs(src);
179
180 // Start j from the node after i to avoid duplicate pairs
182 j.next_ne();
183
184 for (; j.has_curr(); j.next_ne())
185 {
186 typename GT::Node * tgt = j.get_curr();
187
188 // Only check NON-ADJACENT pairs (Ore's theorem condition)
189 if (are_adjacent(g, src, tgt))
190 continue;
191
192 // For non-adjacent pairs, check if deg(u) + deg(v) >= n
193 if (nsrc + g.get_num_arcs(tgt) < n)
194 return false;
195 }
196 }
197
198 return true;
199 }
200
208 bool has_arc(typename GT::Node * src, typename GT::Node * tgt)
209 {
210 for (Node_Arc_Iterator<GT, SA> it(src, sa); it.has_curr(); it.next_ne())
211 if (it.get_tgt_node_ne() == tgt)
212 return true;
213 return false;
214 }
215
227 bool test_digraph(GT & g)
228 {
229 assert(g.is_digraph());
230
231 const size_t n = g.get_num_nodes();
232
233 // Requires n >= 3
234 if (n < 3)
235 return false;
236
238
239 // First pass: count in-degrees using node counters
240 for (Arc_Iterator<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
241 NODE_COUNTER(it.get_tgt_node_ne())++;
242
243 // Check all ordered pairs (src, tgt) where src != tgt
244 for (Node_Iterator<GT, SN> i(g, sn); i.has_curr(); i.next_ne())
245 {
246 typename GT::Node * src = i.get_curr();
247 const size_t out_deg_src = g.get_num_arcs(src);
248
249 for (Node_Iterator<GT, SN> j(g, sn); j.has_curr(); j.next_ne())
250 {
251 typename GT::Node * tgt = j.get_curr();
252
253 if (src == tgt)
254 continue;
255
256 // If condition is satisfied, skip
257 if (out_deg_src + NODE_COUNTER(tgt) >= n)
258 continue;
259
260 // Condition not satisfied; check if arc src→tgt exists
261 // If arc exists, this pair doesn't need to satisfy the condition
262 if (has_arc(src, tgt))
263 continue;
264
265 // Non-adjacent pair that doesn't satisfy the condition
266 return false;
267 }
268 }
269
270 return true;
271 }
272
273public:
274
282 : sn(__sn), sa(__sa)
283 {
284 // empty
285 }
286
299 bool operator () (GT & g)
300 {
301 if (g.is_digraph())
302 return test_digraph(g);
303 else
304 return test_graph(g);
305 }
306};
307
347template <AlephGraph GT,
351{
353 SA & sa;
354
363 bool test_graph(GT & g)
364 {
365 assert(not g.is_digraph());
366
367 const size_t n = g.get_num_nodes();
368
369 // Dirac's theorem requires n >= 3
370 if (n < 3)
371 return false;
372
373 const size_t min_degree = (n + 1) / 2; // Ceiling of n/2
374
375 for (Node_Iterator<GT, SN> it(g, sn); it.has_curr(); it.next_ne())
376 {
377 if (g.get_num_arcs(it.get_curr()) < min_degree)
378 return false;
379 }
380
381 return true;
382 }
383
393 bool test_digraph(GT & g)
394 {
395 assert(g.is_digraph());
396
397 const size_t n = g.get_num_nodes();
398
399 if (n < 3)
400 return false;
401
402 const size_t min_degree = (n + 1) / 2;
403
405
406 // First pass: count in-degrees
407 for (Arc_Iterator<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
408 NODE_COUNTER(it.get_tgt_node_ne())++;
409
410 // Second pass: check both in-degree and out-degree
411 for (Node_Iterator<GT, SN> it(g, sn); it.has_curr(); it.next_ne())
412 {
413 typename GT::Node * p = it.get_curr();
414 const size_t out_deg = g.get_num_arcs(p);
415 const size_t in_deg = NODE_COUNTER(p);
416
417 // Both must be at least n/2
418 if (out_deg < min_degree || in_deg < min_degree)
419 return false;
420 }
421
422 return true;
423 }
424
425public:
426
433 Test_Dirac_Condition(SN && __sn = SN(), SA && __sa = SA())
434 : sn(__sn), sa(__sa)
435 {
436 // empty
437 }
438
447 bool operator () (GT & g)
448 {
449 if (g.is_digraph())
450 return test_digraph(g);
451 else
452 return test_graph(g);
453 }
454
461 size_t min_required_degree(GT & g) const
462 {
463 return (g.get_num_nodes() + 1) / 2;
464 }
465
474 std::pair<size_t, typename GT::Node*> find_min_degree_vertex(GT & g)
475 {
476 size_t min_deg = std::numeric_limits<size_t>::max();
477 typename GT::Node * min_node = nullptr;
478
479 for (Node_Iterator<GT, SN> it(g, sn); it.has_curr(); it.next_ne())
480 {
481 typename GT::Node * p = it.get_curr();
482 size_t deg = g.get_num_arcs(p);
483 if (deg < min_deg)
484 {
485 min_deg = deg;
486 min_node = p;
487 }
488 }
489
490 return {min_deg, min_node};
491 }
492};
493
494} // end namespace Aleph
495
496# endif // HAMILTONIAN_H
C++20 concepts for the protocol shared by graph algorithms.
List_Graph< Graph_Node< Node_Info >, Graph_Arc< Arc_Info > > GT
void next_ne() noexcept
Advances the iterator to the next filtered element (noexcept version).
Filtered iterator on the nodes of a graph.
Definition tpl_graph.H:1207
Tests Dirac's sufficient condition for Hamiltonian graphs.
bool test_graph(GT &g)
Test Dirac's condition for undirected graphs.
size_t min_required_degree(GT &g) const
Get the minimum degree required by Dirac's condition.
bool test_digraph(GT &g)
Test Dirac-like condition for directed graphs.
std::pair< size_t, typename GT::Node * > find_min_degree_vertex(GT &g)
Find the vertex with minimum degree.
Test_Dirac_Condition(SN &&__sn=SN(), SA &&__sa=SA())
Construct a Dirac condition tester.
bool operator()(GT &g)
Test if a graph satisfies Dirac's Hamiltonian condition.
Tests Ore's sufficient condition for Hamiltonian graphs.
bool are_adjacent(GT &g, typename GT::Node *src, typename GT::Node *tgt)
Check if two nodes are adjacent in an undirected graph.
bool test_graph(GT &g)
Test Ore's condition for undirected graphs.
bool operator()(GT &g)
Test if a graph satisfies Ore's Hamiltonian condition.
Test_Hamiltonian_Sufficiency(SN &&__sn=SN(), SA &&__sa=SA())
Construct a Hamiltonian sufficiency tester.
bool has_arc(typename GT::Node *src, typename GT::Node *tgt)
Check if arc src→tgt exists in a digraph.
bool test_digraph(GT &g)
Test Ore-like condition for directed graphs.
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
void reset_counter_nodes() const noexcept
Reset all the counters to zero for all the nodes of graph.
Definition graph-dry.H:1112
constexpr size_t get_num_arcs() const noexcept
Definition graph-dry.H:826
#define NODE_COUNTER(p)
Get the counter of a node.
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
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
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
Default filter for the graph nodes.
Definition tpl_graph.H:1193
Filtered iterator of adjacent arcs of a node.
Definition tpl_graph.H:1120
void test_graph()
Generic graph and digraph implementations.