Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
hld_test.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
49#include <gtest/gtest.h>
50
51#include <algorithm>
52#include <cstddef>
53#include <functional>
54#include <limits>
55#include <numeric>
56#include <random>
57#include <stdexcept>
58#include <utility>
59#include <vector>
60
61#include <HLD.H>
62#include <LCA.H>
63#include <tpl_agraph.H>
64#include <tpl_graph.H>
65#include <tpl_sgraph.H>
66
67#include "test_graph_helpers.h"
68
69using namespace Aleph;
73
74namespace
75{
76 // Naive oracle that computes path queries by walking to LCA
77 class Naive_Path_Oracle
78 {
79 static constexpr size_t NONE = std::numeric_limits<size_t>::max();
80
81 size_t n_ = 0;
82 size_t root_ = 0;
83 std::vector<std::vector<size_t>> adj_;
84 std::vector<size_t> parent_;
85 std::vector<size_t> depth_;
86 std::vector<int> values_;
87
88 void dfs(const size_t u, const size_t p, const size_t d)
89 {
90 parent_[u] = p;
91 depth_[u] = d;
92
93 for (const auto v : adj_[u])
94 if (v != p)
95 dfs(v, u, d + 1);
96 }
97
98 public:
99 Naive_Path_Oracle(const size_t n,
100 const std::vector<std::pair<size_t, size_t>> & edges,
101 const size_t root,
102 const std::vector<int> & vals)
103 : n_(n), root_(root), adj_(n), parent_(n, NONE),
104 depth_(n, 0), values_(vals)
105 {
106 for (const auto & [u, v] : edges)
107 {
108 adj_[u].push_back(v);
109 adj_[v].push_back(u);
110 }
111 dfs(root_, NONE, 0);
112 }
113
114 [[nodiscard]] size_t lca(size_t u, size_t v) const
115 {
116 if (depth_[u] < depth_[v])
117 std::swap(u, v);
118
119 while (depth_[u] > depth_[v])
120 u = parent_[u];
121
122 while (u != v)
123 {
124 u = parent_[u];
125 v = parent_[v];
126 }
127 return u;
128 }
129
130 [[nodiscard]] int path_sum(size_t u, size_t v) const
131 {
132 const size_t a = lca(u, v);
133 int result = 0;
134 size_t x = u;
135 while (x != a)
136 {
137 result += values_[x];
138 x = parent_[x];
139 }
140 x = v;
141 while (x != a)
142 {
143 result += values_[x];
144 x = parent_[x];
145 }
146 result += values_[a];
147 return result;
148 }
149
150 [[nodiscard]] int path_max(size_t u, size_t v) const
151 {
152 const size_t a = lca(u, v);
153 int result = std::numeric_limits<int>::lowest();
154 size_t x = u;
155 while (x != a)
156 {
157 result = std::max(result, values_[x]);
158 x = parent_[x];
159 }
160 x = v;
161 while (x != a)
162 {
163 result = std::max(result, values_[x]);
164 x = parent_[x];
165 }
166 result = std::max(result, values_[a]);
167 return result;
168 }
169
170 [[nodiscard]] int path_min(size_t u, size_t v) const
171 {
172 const size_t a = lca(u, v);
173 int result = std::numeric_limits<int>::max();
174 size_t x = u;
175 while (x != a)
176 {
177 result = std::min(result, values_[x]);
178 x = parent_[x];
179 }
180 x = v;
181 while (x != a)
182 {
183 result = std::min(result, values_[x]);
184 x = parent_[x];
185 }
186 result = std::min(result, values_[a]);
187 return result;
188 }
189
190 [[nodiscard]] int subtree_sum(size_t v) const
191 {
192 int result = values_[v];
193 std::vector<size_t> stack = {v};
194 while (not stack.empty())
195 {
196 const size_t u = stack.back();
197 stack.pop_back();
198 for (const auto c : adj_[u])
199 if (c != parent_[u])
200 {
201 result += values_[c];
202 stack.push_back(c);
203 }
204 }
205 return result;
206 }
207
208 [[nodiscard]] size_t distance(size_t u, size_t v) const
209 {
210 const size_t a = lca(u, v);
211 return depth_[u] + depth_[v] - 2 * depth_[a];
212 }
213
214 void set_value(size_t u, int val) { values_[u] = val; }
215 [[nodiscard]] int value(size_t u) const { return values_[u]; }
216 [[nodiscard]] size_t depth(size_t u) const { return depth_[u]; }
217 };
218
219 template <class GT>
220 class HldTypedTest : public ::testing::Test
221 {
222 };
223
224 using GraphBackends = ::testing::Types<
228
229 TYPED_TEST_SUITE(HldTypedTest, GraphBackends);
230}
231
232
233TYPED_TEST(HldTypedTest, EmptyTree)
234{
235 using Graph = TypeParam;
236
237 Graph g;
238
239 auto nv = [](typename Graph::Node * p) { return p->get_info(); };
241
242 EXPECT_TRUE(hld.is_empty());
243 EXPECT_EQ(hld.size(), 0u);
244 EXPECT_THROW(hld.path_query_id(0, 0), std::domain_error);
245 EXPECT_THROW(hld.subtree_query_id(0), std::domain_error);
246 EXPECT_THROW(hld.lca_id(0, 0), std::domain_error);
247}
248
249TYPED_TEST(HldTypedTest, SingleNode)
250{
251 using Graph = TypeParam;
252 using Node = typename Graph::Node;
253
254 Graph g;
255 Node * n0 = g.insert_node(42);
256
257 auto nv = [](Node * p) { return p->get_info(); };
258 HLD_Sum<Graph, int> hld(g, n0, nv);
259
260 EXPECT_EQ(hld.size(), 1u);
261 EXPECT_EQ(hld.root(), n0);
262
263 EXPECT_EQ(hld.path_query(n0, n0), 42);
264 EXPECT_EQ(hld.subtree_query(n0), 42);
265 EXPECT_EQ(hld.lca(n0, n0), n0);
266 EXPECT_EQ(hld.distance(n0, n0), 0u);
267 EXPECT_EQ(hld.depth_of(n0), 0u);
268 EXPECT_EQ(hld.parent_of(n0), nullptr);
269 EXPECT_EQ(hld.num_chains(), 1u);
270}
271
273{
274 using Graph = TypeParam;
275 using Node = typename Graph::Node;
276
277 // Node values: node_id * 10
278 // 0 (val=0)
279 // / |
280 // 1(10) 2(20)
281 // / | / |
282 // 3(30)4(40) 5(50)6(60)
283 // / |
284 // 7(70)8(80)
285
286 const std::vector<std::pair<size_t, size_t>> edges = {
287 {0, 1}, {0, 2},
288 {1, 3}, {1, 4},
289 {2, 5}, {2, 6},
290 {5, 7}, {5, 8}};
291
292 Graph g;
293 auto nodes = build_graph_with_unit_arcs(g, 9, edges);
294
295 auto nv = [](Node * p) { return p->get_info() * 10; };
297
298 // path(3, 4) = 30 + 10 + 40 = 80
299 EXPECT_EQ(hld.path_query(nodes(3), nodes(4)), 80);
300
301 // path(3, 6) = 30 + 10 + 0 + 20 + 60 = 120
302 EXPECT_EQ(hld.path_query(nodes(3), nodes(6)), 120);
303
304 // path(7, 8) = 70 + 50 + 80 = 200
305 EXPECT_EQ(hld.path_query(nodes(7), nodes(8)), 200);
306
307 // path(7, 6) = 70 + 50 + 20 + 60 = 200
308 EXPECT_EQ(hld.path_query(nodes(7), nodes(6)), 200);
309
310 // path(0, 8) = 0 + 20 + 50 + 80 = 150
311 EXPECT_EQ(hld.path_query(nodes(0), nodes(8)), 150);
312
313 // path(3, 8) = 30 + 10 + 0 + 20 + 50 + 80 = 190
314 EXPECT_EQ(hld.path_query(nodes(3), nodes(8)), 190);
315
316 // Self path
317 EXPECT_EQ(hld.path_query(nodes(5), nodes(5)), 50);
318}
319
321{
322 using Graph = TypeParam;
323 using Node = typename Graph::Node;
324
325 const std::vector<std::pair<size_t, size_t>> edges = {
326 {0, 1}, {0, 2},
327 {1, 3}, {1, 4},
328 {2, 5}, {2, 6},
329 {5, 7}, {5, 8}};
330
331 Graph g;
332 auto nodes = build_graph_with_unit_arcs(g, 9, edges);
333
334 // Values: [5, 3, 8, 1, 9, 2, 7, 4, 6]
335 const int vals[] = {5, 3, 8, 1, 9, 2, 7, 4, 6};
336 auto nv = [&vals](Node * p) { return vals[p->get_info()]; };
338
339 // path(3, 4) = max(1, 3, 9) = 9
340 EXPECT_EQ(hld.path_query(nodes(3), nodes(4)), 9);
341
342 // path(7, 6) = max(4, 2, 8, 7) = 8
343 EXPECT_EQ(hld.path_query(nodes(7), nodes(6)), 8);
344
345 // path(3, 8) = max(1, 3, 5, 8, 2, 6) = 8
346 EXPECT_EQ(hld.path_query(nodes(3), nodes(8)), 8);
347}
348
350{
351 using Graph = TypeParam;
352 using Node = typename Graph::Node;
353
354 const std::vector<std::pair<size_t, size_t>> edges = {
355 {0, 1}, {0, 2},
356 {1, 3}, {1, 4},
357 {2, 5}, {2, 6},
358 {5, 7}, {5, 8}};
359
360 Graph g;
361 auto nodes = build_graph_with_unit_arcs(g, 9, edges);
362
363 auto nv = [](Node * p) { return p->get_info() + 1; }; // val = id + 1
365
366 // subtree(5) = 6 + 8 + 9 = 23
367 EXPECT_EQ(hld.subtree_query(nodes(5)), 23);
368
369 // subtree(2) = 3 + 6 + 7 + 8 + 9 = 33
370 EXPECT_EQ(hld.subtree_query(nodes(2)), 33);
371
372 // subtree(1) = 2 + 4 + 5 = 11
373 EXPECT_EQ(hld.subtree_query(nodes(1)), 11);
374
375 // subtree(0) = 1+2+3+4+5+6+7+8+9 = 45
376 EXPECT_EQ(hld.subtree_query(nodes(0)), 45);
377
378 // Leaf subtree
379 EXPECT_EQ(hld.subtree_query(nodes(7)), 8);
380}
381
383{
384 using Graph = TypeParam;
385 using Node = typename Graph::Node;
386
387 const std::vector<std::pair<size_t, size_t>> edges = {
388 {0, 1}, {0, 2}, {1, 3}, {1, 4}};
389
390 Graph g;
391 auto nodes = build_graph_with_unit_arcs(g, 5, edges);
392
393 // Values: all 10
394 auto nv = [](Node *) { return 10; };
396
397 // path(3,4) = 10 + 10 + 10 = 30
398 EXPECT_EQ(hld.path_query(nodes(3), nodes(4)), 30);
399
400 // Update node 1 to 100
401 hld.point_update(nodes(1), 100);
402
403 // path(3,4) = 10 + 100 + 10 = 120
404 EXPECT_EQ(hld.path_query(nodes(3), nodes(4)), 120);
405
406 // subtree(1) = 100 + 10 + 10 = 120
407 EXPECT_EQ(hld.subtree_query(nodes(1)), 120);
408
409 // Verify get_value
410 EXPECT_EQ(hld.get_value(nodes(1)), 100);
411 EXPECT_EQ(hld.get_value(nodes(0)), 10);
412}
413
415{
416 using Graph = TypeParam;
417 using Node = typename Graph::Node;
418
419 // Edge-weighted tree: store edge weight on child node, root = 0
420 // 0 (val=0, root)
421 // / |
422 // 1 2 (edge 0-1 has weight 5, edge 0-2 has weight 3)
423 // /
424 // 3 (edge 1-3 has weight 7)
425 const std::vector<std::pair<size_t, size_t>> edges = {
426 {0, 1}, {0, 2}, {1, 3}};
427
428 Graph g;
429 auto nodes = build_graph_with_unit_arcs(g, 4, edges);
430
431 // Values on children represent edge weights: root=0, 1=5, 2=3, 3=7
432 const int edge_vals[] = {0, 5, 3, 7};
433 auto nv = [&edge_vals](Node * p) { return edge_vals[p->get_info()]; };
435
436 // path_query_edges(3, 2): path is 3-1-0-2, edges are 7+5+3 = 15
437 // (skip LCA which is 0 with value 0)
438 EXPECT_EQ(hld.path_query_edges(nodes(3), nodes(2)), 15);
439
440 // path_query_edges(1, 3): path is 1-3, edge is 7
441 EXPECT_EQ(hld.path_query_edges(nodes(1), nodes(3)), 7);
442
443 // path_query_edges(1, 2): path is 1-0-2, edges are 5+3 = 8
444 EXPECT_EQ(hld.path_query_edges(nodes(1), nodes(2)), 8);
445
446 // path_query_edges(v, v) should be identity (0) since no edges
447 EXPECT_EQ(hld.path_query_edges(nodes(1), nodes(1)), 0);
448}
449
450TYPED_TEST(HldTypedTest, LcaFromHLD)
451{
452 using Graph = TypeParam;
453 using Node = typename Graph::Node;
454
455 const std::vector<std::pair<size_t, size_t>> edges = {
456 {0, 1}, {0, 2},
457 {1, 3}, {1, 4},
458 {2, 5}, {2, 6},
459 {5, 7}, {5, 8}};
460
461 Graph g;
462 auto nodes = build_graph_with_unit_arcs(g, 9, edges);
463
464 auto nv = [](Node * p) { return p->get_info(); };
467
468 // Cross-validate all pairs
469 for (size_t u = 0; u < 9; ++u)
470 for (size_t v = u; v < 9; ++v)
471 {
472 auto * hld_lca = hld.lca(nodes(u), nodes(v));
473 auto * bl_lca = bl.lca(nodes(u), nodes(v));
475 << "u=" << u << " v=" << v;
476
477 EXPECT_EQ(hld.distance(nodes(u), nodes(v)),
478 bl.distance(nodes(u), nodes(v)));
479 }
480}
481
483{
484 using Graph = TypeParam;
485 using Node = typename Graph::Node;
486
487 const std::vector<std::pair<size_t, size_t>> edges = {
488 {0, 1}, {0, 2},
489 {1, 3}, {1, 4},
490 {2, 5}, {2, 6},
491 {5, 7}, {5, 8}};
492
493 Graph g;
494 auto nodes = build_graph_with_unit_arcs(g, 9, edges);
495
496 auto nv = [](Node * p) { return p->get_info(); };
498
499 EXPECT_EQ(hld.size(), 9u);
500 EXPECT_GE(hld.num_chains(), 1u);
501 EXPECT_LE(hld.num_chains(), 9u);
502
503 // Every position is unique and in [0, n)
504 std::vector<bool> seen(9, false);
505 for (size_t i = 0; i < 9; ++i)
506 {
507 const size_t pos = hld.position(i);
508 EXPECT_LT(pos, 9u);
509 EXPECT_FALSE(seen[pos]) << "Duplicate position at node " << i;
510 seen[pos] = true;
511 }
512
513 // Chain head of root is root
514 EXPECT_EQ(hld.chain_head_id(hld.root_id()), hld.root_id());
515
516 // Root depth is 0
517 EXPECT_EQ(hld.depth_of_id(hld.root_id()), 0u);
518
519 // Subtree size of root = n
520 EXPECT_EQ(hld.subtree_size_of_id(hld.root_id()), 9u);
521
522 // For each node, chain_head has depth <= node depth
523 for (size_t i = 0; i < 9; ++i)
524 {
525 const size_t head = hld.chain_head_id(i);
526 EXPECT_LE(hld.depth_of_id(head), hld.depth_of_id(i));
527 }
528}
529
531{
532 using Graph = TypeParam;
533 using Node = typename Graph::Node;
534
535 auto nv = [](Node * p) { return p->get_info(); };
536
537 // Cycle
538 {
539 Graph g;
540 auto nodes = build_graph_with_unit_arcs(g, 3, {{0, 1}, {1, 2}, {2, 0}});
541 EXPECT_THROW((HLD_Sum<Graph, int>(g, nodes(0), nv)), std::domain_error);
542 }
543
544 // Disconnected
545 {
546 Graph g;
547 auto nodes = build_graph_with_unit_arcs(g, 4, {{0, 1}, {2, 3}});
548 EXPECT_THROW((HLD_Sum<Graph, int>(g, nodes(0), nv)), std::domain_error);
549 }
550
551 // Self-loop
552 {
553 Graph g;
554 auto nodes = build_graph_with_unit_arcs(g, 3, {{0, 1}, {1, 2}, {2, 2}});
555 EXPECT_THROW((HLD_Sum<Graph, int>(g, nodes(0), nv)), std::domain_error);
556 }
557
558 // Parallel edge
559 {
560 Graph g;
561 auto nodes = build_graph_with_unit_arcs(g, 2, {{0, 1}, {0, 1}});
562 EXPECT_THROW((HLD_Sum<Graph, int>(g, nodes(0), nv)), std::domain_error);
563 }
564}
565
566TYPED_TEST(HldTypedTest, ArcFilter)
567{
568 using Graph = TypeParam;
569 using Node = typename Graph::Node;
570
571 Graph g;
573 for (size_t i = 0; i < 6; ++i)
574 nodes(i) = g.insert_node(static_cast<int>(i));
575
576 // Tree edges (kept by filter)
577 g.insert_arc(nodes(0), nodes(1), 1);
578 g.insert_arc(nodes(0), nodes(2), 1);
579 g.insert_arc(nodes(1), nodes(3), 1);
580 g.insert_arc(nodes(1), nodes(4), 1);
581 g.insert_arc(nodes(2), nodes(5), 1);
582
583 // Non-tree edges (filtered out)
584 g.insert_arc(nodes(3), nodes(5), -1);
585 g.insert_arc(nodes(4), nodes(2), -1);
586
587 // Without filter: should fail (not a tree)
588 auto nv = [](Node * p) { return p->get_info(); };
589 EXPECT_THROW((HLD_Sum<Graph, int>(g, nodes(0), nv)), std::domain_error);
590
591 // With filter: should work
593 hld(g, nodes(0), nv, Positive_Arc_Filter());
594
595 EXPECT_EQ(hld.size(), 6u);
596
597 auto * l = hld.lca(nodes(3), nodes(5));
598 EXPECT_EQ(static_cast<size_t>(l->get_info()), 0u);
599
600 l = hld.lca(nodes(3), nodes(4));
601 EXPECT_EQ(static_cast<size_t>(l->get_info()), 1u);
602}
603
605{
606 using Graph = TypeParam;
607 using Node = typename Graph::Node;
608
609 std::mt19937 rng(0x41d2026u);
610
611 for (size_t sample = 0; sample < 20; ++sample)
612 {
613 std::uniform_int_distribution<size_t> n_pick(2, 80);
614 const size_t n = n_pick(rng);
616
617 std::uniform_int_distribution<int> val_pick(-100, 100);
618 std::vector<int> vals(n);
619 for (size_t i = 0; i < n; ++i)
620 vals[i] = val_pick(rng);
621
622 std::uniform_int_distribution<size_t> root_pick(0, n - 1);
623 const size_t root = root_pick(rng);
624
625 Graph g;
626 auto nodes = build_graph_with_unit_arcs(g, n, edges);
627
628 auto nv_sum = [&vals](Node * p) { return vals[p->get_info()]; };
629 auto nv_max = [&vals](Node * p) { return vals[p->get_info()]; };
630 auto nv_min = [&vals](Node * p) { return vals[p->get_info()]; };
631
635
636 Naive_Path_Oracle oracle(n, edges, root, vals);
637
638 std::uniform_int_distribution<size_t> node_pick(0, n - 1);
639
640 // Test path queries
641 for (size_t q = 0; q < 200; ++q)
642 {
643 const size_t u = node_pick(rng);
644 const size_t v = node_pick(rng);
645
646 EXPECT_EQ(hld_sum.path_query(nodes(u), nodes(v)),
647 oracle.path_sum(u, v))
648 << "sample=" << sample << " u=" << u << " v=" << v;
649
650 EXPECT_EQ(hld_max.path_query(nodes(u), nodes(v)),
651 oracle.path_max(u, v))
652 << "sample=" << sample << " u=" << u << " v=" << v;
653
654 EXPECT_EQ(hld_min.path_query(nodes(u), nodes(v)),
655 oracle.path_min(u, v))
656 << "sample=" << sample << " u=" << u << " v=" << v;
657
658 // LCA
659 EXPECT_EQ(static_cast<size_t>(hld_sum.lca(nodes(u), nodes(v))->get_info()),
660 oracle.lca(u, v))
661 << "sample=" << sample << " u=" << u << " v=" << v;
662
663 // Distance
664 EXPECT_EQ(hld_sum.distance(nodes(u), nodes(v)),
665 oracle.distance(u, v))
666 << "sample=" << sample << " u=" << u << " v=" << v;
667 }
668
669 // Test subtree queries (sum only)
670 for (size_t q = 0; q < 50; ++q)
671 {
672 const size_t v = node_pick(rng);
673 EXPECT_EQ(hld_sum.subtree_query(nodes(v)),
674 oracle.subtree_sum(v))
675 << "sample=" << sample << " v=" << v;
676 }
677
678 // Test point updates
679 for (size_t q = 0; q < 20; ++q)
680 {
681 const size_t v = node_pick(rng);
682 const int new_val = val_pick(rng);
683
684 hld_sum.point_update(nodes(v), new_val);
685 oracle.set_value(v, new_val);
686
687 // Verify a few queries after update
688 const size_t u1 = node_pick(rng);
689 const size_t v1 = node_pick(rng);
690 EXPECT_EQ(hld_sum.path_query(nodes(u1), nodes(v1)),
691 oracle.path_sum(u1, v1))
692 << "sample=" << sample << " after update";
693 }
694 }
695}
Heavy-Light Decomposition for tree path queries on Aleph graphs.
Lowest Common Ancestor (LCA) on rooted trees represented as Aleph graphs.
TYPED_TEST_SUITE(AStarHeapTest, HeapTypes)
WeightedDigraph::Node Node
static Array create(size_t n)
Create an array with n logical elements.
Definition tpl_array.H:194
LCA via binary lifting on a rooted tree.
Definition LCA.H:440
Arc for graphs implemented with simple adjacency lists.
Definition tpl_sgraph.H:197
Graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:428
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:524
Node Node
The graph type.
Definition tpl_graph.H:432
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:604
Graph class implemented with singly-linked adjacency lists.
Definition tpl_sgraph.H:274
static mt19937 rng
__gmp_expr< T, __gmp_binary_expr< __gmp_expr< T, U >, unsigned long int, __gmp_root_function > > root(const __gmp_expr< T, U > &expr, unsigned long int l)
Definition gmpfrxx.h:4060
DynArray< Graph::Node * > nodes
Definition graphpic.C:406
TYPED_TEST(HldTypedTest, EmptyTree)
Definition hld_test.cc:233
DFSResult< typename Domain::Distance > dfs(Domain &domain, typename Domain::State &state, SearchPath< typename Domain::Move > &path, const typename Domain::Distance g, const typename Domain::Distance threshold, const size_t depth, IDAStarResult< Solution, typename Domain::Distance > &result, OnSolution &on_solution)
Core recursive DFS used by IDA* for a single threshold pass.
Aleph::Array< typename GT::Node * > build_graph_with_unit_arcs(GT &g, const size_t n, const std::vector< std::pair< size_t, size_t > > &edges)
EdgeContainer make_random_tree_edges(const size_t n, std::mt19937 &rng)
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.
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
HLD with path/subtree max queries.
Definition HLD.H:969
HLD with path/subtree min queries.
Definition HLD.H:996
HLD with path/subtree sum queries.
Definition HLD.H:942
Array-based graph implementation.
Generic graph and digraph implementations.
Simple graph implementation with adjacency lists.
DynList< int > l