Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
bench_r_tree.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 https://github.com/lrleon/Aleph-w
6
7 This file is part of Aleph-w library
8
9 Copyright (c) 2002-2026 Leandro Rabindranath Leon
10*/
11
23#include <algorithm>
24#include <charconv>
25#include <chrono>
26#include <cstdio>
27#include <cstdlib>
28#include <random>
29#include <string_view>
30#include <vector>
31
32#include <geom_algorithms.H>
33#include <tpl_r_star_tree.H>
34#include <tpl_r_tree.H>
35
36using namespace Aleph;
37
38namespace
39{
40
41volatile size_t sink = 0;
42
43Rectangle rect(const int x1, const int y1, const int x2, const int y2)
44{
46 Geom_Number(x2), Geom_Number(y2));
47}
48
49template <class Fn>
50double best_ms(Fn fn, const int repeats = 3)
51{
52 double best = 1e300;
53 for (int r = 0; r < repeats; ++r)
54 {
55 const auto t0 = std::chrono::steady_clock::now();
56 fn();
57 const auto t1 = std::chrono::steady_clock::now();
58 const double ms = std::chrono::duration<double, std::milli>(t1 - t0).count();
59 best = std::min(best, ms);
60 }
61 return best;
62}
63
64void row(const char *index, const char *op, const double ms)
65{
66 std::printf(" %-12s %-28s %10.2f ms\n", index, op, ms);
67}
68
69std::vector<Rectangle> make_rectangles(const size_t n, const unsigned seed)
70{
71 std::mt19937 rng(seed);
72 std::uniform_int_distribution<int> coord(0, 20000);
73 std::uniform_int_distribution<int> extent(1, 80);
74
75 std::vector<Rectangle> out;
76 out.reserve(n);
77 for (size_t i = 0; i < n; ++i)
78 {
79 const int x = coord(rng);
80 const int y = coord(rng);
81 out.push_back(rect(x, y, x + extent(rng), y + extent(rng)));
82 }
83 return out;
84}
85
86RTree<size_t> build_rtree(const std::vector<Rectangle> &rects)
87{
88 RTree<size_t> tree;
89 for (size_t i = 0; i < rects.size(); ++i)
90 tree.insert(rects[i], i);
91 return tree;
92}
93
94RStarTree<size_t> build_rstar(const std::vector<Rectangle> &rects)
95{
97 for (size_t i = 0; i < rects.size(); ++i)
98 tree.insert(rects[i], i);
99 return tree;
100}
101
102AABBTree build_aabb(const std::vector<Rectangle> &rects)
103{
105 entries.reserve(rects.size());
106 for (size_t i = 0; i < rects.size(); ++i)
107 entries.append(AABBTree::Entry{rects[i], i});
108
109 AABBTree tree;
110 tree.build(entries);
111 return tree;
112}
113
118bool parse_size(const char *text, size_t &out)
119{
120 if (text == nullptr)
121 return false;
122 const std::string_view sv{text};
123 if (sv.empty() or sv.front() == '+' or sv.front() == '-')
124 return false;
125 const auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), out, 10);
126 return ec == std::errc{} and ptr == sv.data() + sv.size();
127}
128
129size_t brute_query_count(const std::vector<Rectangle> &rects,
130 const std::vector<Rectangle> &queries)
131{
132 size_t total = 0;
133 for (const Rectangle &q : queries)
134 for (const Rectangle &b : rects)
135 total += b.intersects(q);
136 return total;
137}
138
139template <class Tree>
140size_t rtree_query_count(const Tree &tree, const std::vector<Rectangle> &queries)
141{
142 size_t total = 0;
143 for (const Rectangle &q : queries)
144 tree.for_each_intersecting(q,
145 [&total](const Rectangle &, const size_t &) { ++total; });
146 return total;
147}
148
149size_t aabb_query_count(const AABBTree &tree, const std::vector<Rectangle> &queries)
150{
151 size_t total = 0;
152 for (const Rectangle &q : queries)
153 total += tree.query(q).size();
154 return total;
155}
156
157void validate_counts(const std::vector<Rectangle> &rects,
158 const std::vector<Rectangle> &queries,
159 const RTree<size_t> &rtree,
161 const AABBTree &aabb)
162{
163 const size_t brute = brute_query_count(rects, queries);
164 const size_t rt = rtree_query_count(rtree, queries);
165 const size_t rs = rtree_query_count(rstar, queries);
166 const size_t ab = aabb_query_count(aabb, queries);
167 if (brute != rt or brute != rs or brute != ab)
168 {
169 std::fprintf(stderr,
170 "validation failed: brute=%zu rtree=%zu rstar=%zu aabb=%zu\n",
171 brute, rt, rs, ab);
172 std::exit(2);
173 }
174 sink += brute + rt + rs + ab;
175}
176
177} // namespace
178
179int main(int argc, char *argv[])
180{
181 size_t entry_count = 10000;
182 size_t query_count = 2000;
183
184 if (argc > 1 and not parse_size(argv[1], entry_count))
185 {
186 std::fprintf(stderr, "invalid entry_count: '%s'\n", argv[1]);
187 return 1;
188 }
189 if (argc > 2 and not parse_size(argv[2], query_count))
190 {
191 std::fprintf(stderr, "invalid query_count: '%s'\n", argv[2]);
192 return 1;
193 }
194
195 const std::vector<Rectangle> rects = make_rectangles(entry_count, 0xA1E9u);
196 const std::vector<Rectangle> queries = make_rectangles(query_count, 0xBEEFu);
197
200 const AABBTree aabb = build_aabb(rects);
202
203 std::printf("Spatial index benchmark (best of 3 runs, %zu entries, %zu queries)\n",
204 entry_count, query_count);
205 row("RTree", "incremental insert",
206 best_ms([&] { const RTree<size_t> t = build_rtree(rects); sink += t.size(); }));
207 row("RStarTree", "incremental insert",
208 best_ms([&] { const RStarTree<size_t> t = build_rstar(rects); sink += t.size(); }));
209 row("AABBTree", "static build",
210 best_ms([&] { const AABBTree t = build_aabb(rects); sink += t.size(); }));
211
212 row("brute", "intersect queries",
213 best_ms([&] { sink += brute_query_count(rects, queries); }));
214 row("RTree", "intersect queries",
215 best_ms([&] { sink += rtree_query_count(rtree, queries); }));
216 row("RStarTree", "intersect queries",
217 best_ms([&] { sink += rtree_query_count(rstar, queries); }));
218 row("AABBTree", "intersect queries",
219 best_ms([&] { sink += aabb_query_count(aabb, queries); }));
220
221 std::printf("\n(sink=%zu)\n", static_cast<size_t>(sink));
222 return 0;
223}
int main()
size_t size_t int32_t * out
Definition ca-c-api.h:120
size_t row
Definition ca-c-api.h:115
Axis-aligned bounding box tree for spatial queries.
size_t build(Array< size_t > &idx, const size_t lo, const size_t hi)
size_t size() const
Number of entries.
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:138
T & append(const T &data)
Append a copy of data
Definition tpl_array.H:250
void reserve(size_t cap)
Reserves cap cells into the array.
Definition tpl_array.H:320
Dynamic R-tree indexing axis-aligned rectangles by payload.
Definition tpl_r_tree.H:118
void insert(const Rectangle &bbox, const Payload &value)
Insert a (bbox, value) entry, copying value.
Definition tpl_r_tree.H:969
size_t size() const noexcept
Return the number of stored entries.
Definition tpl_r_tree.H:937
An axis-aligned rectangle.
Definition point.H:1789
QuadTree - Hierarchical spatial index for 2D points.
Definition quadtree.H:126
static mt19937 rng
Computational geometry algorithms.
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_y1_function > > y1(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4114
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
static mpfr_t y
Definition mpfr_mul_d.c:3
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
size_t size(Node *root) noexcept
and
Check uniqueness with explicit hash + equality functors.
mpq_class Geom_Number
Numeric type used by the geometry module.
Definition point.H:113
An entry in the tree, consisting of a bounding box and a user-defined index.
ValueArg< size_t > seed
Definition testHash.C:53
gsl_rng * r
R*-tree: an R-tree tuned with the Beckmann-Kriegel-Schneider-Seeger heuristics.
Dynamic R-tree spatial index over axis-aligned rectangles.