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 <tpl_graph.H>
84
85namespace Aleph
86{
87
127template <class GT,
128 class SN = Dft_Show_Node<GT>,
129 class SA = Dft_Show_Arc<GT> >
131{
134
143 bool are_adjacent(GT & g, typename GT::Node * src, typename GT::Node * tgt)
144 {
145 (void) g;
146
147 for (Node_Arc_Iterator<GT, SA> it(src, sa); it.has_curr(); it.next_ne())
148 if (it.get_tgt_node_ne() == tgt)
149 return true;
150 return false;
151 }
152
162 bool test_graph(GT & g)
163 {
164 assert(not g.is_digraph());
165
166 const size_t n = g.get_num_nodes();
167
168 // Ore's theorem requires n >= 3
169 if (n < 3)
170 return false;
171
172 // Check all pairs of distinct vertices
173 for (Node_Iterator<GT, SN> i(g, sn); i.has_curr(); i.next_ne())
174 {
175 typename GT::Node * src = i.get_curr();
176 const size_t nsrc = g.get_num_arcs(src);
177
178 // Start j from the node after i to avoid duplicate pairs
180 j.next_ne();
181
182 for (; j.has_curr(); j.next_ne())
183 {
184 typename GT::Node * tgt = j.get_curr();
185
186 // Only check NON-ADJACENT pairs (Ore's theorem condition)
187 if (are_adjacent(g, src, tgt))
188 continue;
189
190 // For non-adjacent pairs, check if deg(u) + deg(v) >= n
191 if (nsrc + g.get_num_arcs(tgt) < n)
192 return false;
193 }
194 }
195
196 return true;
197 }
198
206 bool has_arc(typename GT::Node * src, typename GT::Node * tgt)
207 {
208 for (Node_Arc_Iterator<GT, SA> it(src, sa); it.has_curr(); it.next_ne())
209 if (it.get_tgt_node_ne() == tgt)
210 return true;
211 return false;
212 }
213
225 bool test_digraph(GT & g)
226 {
227 assert(g.is_digraph());
228
229 const size_t n = g.get_num_nodes();
230
231 // Requires n >= 3
232 if (n < 3)
233 return false;
234
236
237 // First pass: count in-degrees using node counters
238 for (Arc_Iterator<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
239 NODE_COUNTER(it.get_tgt_node_ne())++;
240
241 // Check all ordered pairs (src, tgt) where src != tgt
242 for (Node_Iterator<GT, SN> i(g, sn); i.has_curr(); i.next_ne())
243 {
244 typename GT::Node * src = i.get_curr();
245 const size_t out_deg_src = g.get_num_arcs(src);
246
247 for (Node_Iterator<GT, SN> j(g, sn); j.has_curr(); j.next_ne())
248 {
249 typename GT::Node * tgt = j.get_curr();
250
251 if (src == tgt)
252 continue;
253
254 // If condition is satisfied, skip
255 if (out_deg_src + NODE_COUNTER(tgt) >= n)
256 continue;
257
258 // Condition not satisfied; check if arc src→tgt exists
259 // If arc exists, this pair doesn't need to satisfy the condition
260 if (has_arc(src, tgt))
261 continue;
262
263 // Non-adjacent pair that doesn't satisfy the condition
264 return false;
265 }
266 }
267
268 return true;
269 }
270
271public:
272
280 : sn(__sn), sa(__sa)
281 {
282 // empty
283 }
284
297 bool operator () (GT & g)
298 {
299 if (g.is_digraph())
300 return test_digraph(g);
301 else
302 return test_graph(g);
303 }
304};
305
345template <class GT,
346 class SN = Dft_Show_Node<GT>,
347 class SA = Dft_Show_Arc<GT> >
349{
352
361 bool test_graph(GT & g)
362 {
363 assert(not g.is_digraph());
364
365 const size_t n = g.get_num_nodes();
366
367 // Dirac's theorem requires n >= 3
368 if (n < 3)
369 return false;
370
371 const size_t min_degree = (n + 1) / 2; // Ceiling of n/2
372
373 for (Node_Iterator<GT, SN> it(g, sn); it.has_curr(); it.next_ne())
374 {
375 if (g.get_num_arcs(it.get_curr()) < min_degree)
376 return false;
377 }
378
379 return true;
380 }
381
391 bool test_digraph(GT & g)
392 {
393 assert(g.is_digraph());
394
395 const size_t n = g.get_num_nodes();
396
397 if (n < 3)
398 return false;
399
400 const size_t min_degree = (n + 1) / 2;
401
403
404 // First pass: count in-degrees
405 for (Arc_Iterator<GT, SA> it(g, sa); it.has_curr(); it.next_ne())
406 NODE_COUNTER(it.get_tgt_node_ne())++;
407
408 // Second pass: check both in-degree and out-degree
409 for (Node_Iterator<GT, SN> it(g, sn); it.has_curr(); it.next_ne())
410 {
411 typename GT::Node * p = it.get_curr();
412 const size_t out_deg = g.get_num_arcs(p);
413 const size_t in_deg = NODE_COUNTER(p);
414
415 // Both must be at least n/2
417 return false;
418 }
419
420 return true;
421 }
422
423public:
424
432 : sn(__sn), sa(__sa)
433 {
434 // empty
435 }
436
445 bool operator () (GT & g)
446 {
447 if (g.is_digraph())
448 return test_digraph(g);
449 else
450 return test_graph(g);
451 }
452
459 size_t min_required_degree(GT & g) const
460 {
461 return (g.get_num_nodes() + 1) / 2;
462 }
463
472 std::pair<size_t, typename GT::Node*> find_min_degree_vertex(GT & g)
473 {
474 size_t min_deg = std::numeric_limits<size_t>::max();
475 typename GT::Node * min_node = nullptr;
476
477 for (Node_Iterator<GT, SN> it(g, sn); it.has_curr(); it.next_ne())
478 {
479 typename GT::Node * p = it.get_curr();
480 size_t deg = g.get_num_arcs(p);
481 if (deg < min_deg)
482 {
483 min_deg = deg;
484 min_node = p;
485 }
486 }
487
488 return {min_deg, min_node};
489 }
490};
491
492} // end namespace Aleph
493
494# endif // HAMILTONIAN_H
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:1206
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:695
bool is_digraph() const noexcept
Return true if the graph this is directed.
Definition graph-dry.H:657
void reset_counter_nodes() const noexcept
Reset all the counters to zero for all the nodes of graph.
Definition graph-dry.H:1064
constexpr size_t get_num_arcs() const noexcept
Definition graph-dry.H:778
List_Graph< Graph_Node< int >, Graph_Arc< int > > GT
#define NODE_COUNTER(p)
Get the counter of a node.
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
Default filter for the graph nodes.
Definition tpl_graph.H:1192
Filtered iterator of adjacent arcs of a node.
Definition tpl_graph.H:1119
Generic graph and digraph implementations.