From da7e939ee809a88493d9aa43ad6e87d610045981 Mon Sep 17 00:00:00 2001 From: AndreaB330 Date: Sat, 26 Jan 2019 16:30:16 +0200 Subject: [PATCH] Benchmarks --- README.md | 16 +++++++-- benchmark.h | 85 ++++++++++++++++++++++++++++++++++++++++++++ benchmarks/dim10.csv | 2 ++ benchmarks/dim2.csv | 34 ++++++++++++++++++ benchmarks/dim20.csv | 14 ++++++++ benchmarks/dim3.csv | 22 ++++++++++++ benchmarks/dim4.csv | 22 ++++++++++++ benchmarks/dim5.csv | 18 ++++++++++ emst.h | 4 +-- main.cpp | 2 +- 10 files changed, 214 insertions(+), 5 deletions(-) create mode 100644 benchmark.h create mode 100644 benchmarks/dim10.csv create mode 100644 benchmarks/dim2.csv create mode 100644 benchmarks/dim20.csv create mode 100644 benchmarks/dim3.csv create mode 100644 benchmarks/dim4.csv create mode 100644 benchmarks/dim5.csv diff --git a/README.md b/README.md index a527126..6029a90 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,23 @@ Implementations of different algorithms for building Euclidean minimum spanning tree in k-dimensional space. ### Algorithms: - EMST using Kd-tree O(NlogN) - Implementation of algorithm described in "Fast Euclidean Minimum Spanning Tree: Algorithm, Analysis, and Applications. William B. March, Parikshit Ram, Alexander G. Gray" + + Implementation of algorithm described in "Fast Euclidean Minimum Spanning Tree: Algorithm, Analysis, and Applications. William B. March, Parikshit Ram, Alexander G. Gray" - Prim's algorithm O(N^2) + Straightforward MST on fully connected Eclidean graph +### Benchmarks: + +| Dimensions | Number of points | Kd-tree (sec) | Prim (sec) | +| -------------: |-------------:| -----:| ----:| +| 2 | 50000 | 0.24 | 29.0 | +| 3 | 50000 | 0.67 | 32.0 | +| 4 | 50000 | 1.59 | 36.0 | +| 2 | 10000000 | 69.0 | ~1000000 | +| 3 | 10000000 | 186.0 | ~1300000 | +| 4 | 10000000 | 673.9 | ~1500000 | + ### TODO: - Implement EMST using Cover-tree -- Benchmarks - \dots \ No newline at end of file diff --git a/benchmark.h b/benchmark.h new file mode 100644 index 0000000..5448658 --- /dev/null +++ b/benchmark.h @@ -0,0 +1,85 @@ +#pragma once +#include +#include +#include +#include +#include "emst.h" +using namespace std::chrono; + +double uniform() { + return rand() * 1.0 / RAND_MAX; +} + +template +std::vector> generate_points_uniform(size_t num_points, double MAX = 100.0) { + std::vector> points; + for (size_t i = 0; i < num_points; i++) { + Point p; + for (size_t k = 0; k < DIM; k++) { + p[k] = (uniform() * 2.0 - 1.0) * MAX; + } + points.push_back(p); + } + return points; +} + +template +std::vector> generate_points_gauss(size_t num_points, double MAX = 100.0) { + std::vector> points; + for (size_t i = 0; i < num_points; i++) { + Point p; + for (size_t k = 0; k < DIM; k++) { + p[k] = sqrt(-2 * log(uniform())) * cos(2 * 3.141592 * uniform()) * MAX; + } + points.push_back(p); + } + return points; +} + +struct BenchmarkResult { + double answer; + double time; +}; + +template +BenchmarkResult run_benchmark(const std::vector> & points, size_t samples = 1) { + BenchmarkResult result; + auto start = std::chrono::system_clock::now(); + for (size_t i = 0; i < samples; i++) { + EmstSolverType solver(points); + result.answer = solver.get_total_length(); + } + auto end = std::chrono::system_clock::now(); + + std::chrono::duration elapsed_seconds = end - start; + result.time = elapsed_seconds.count() / samples; + return result; +} + +template +void run_becnhmarks(const std::vector> & points, size_t samples, std::ostream & cout, std::string distribution = "none") { + auto result_kd = run_benchmark, DIM>(points, samples); + auto result_prim = (points.size() < 100000 ? run_benchmark, DIM>(points, samples / 50 + 1) : BenchmarkResult{ result_kd.answer, 0 }); + + assert(fabs(result_kd.answer / result_prim.answer - 1.0) < 1e-8); + cout.precision(6); + cout.setf(std::ios::fixed); + cout << "kd-tree" << "," << DIM << "," << points.size() << "," << distribution << "," << result_kd.time << "\n"; + cout << "prim" << "," << DIM << "," << points.size() << "," << distribution << "," << result_prim.time << "\n"; + cout.flush(); +} + +template +void run_becnhmarks(std::ostream & cout) { + run_becnhmarks(generate_points_uniform(10), 100, cout, "uniform"); + run_becnhmarks(generate_points_uniform(50), 100, cout, "uniform"); + run_becnhmarks(generate_points_uniform(100), 1, cout, "uniform"); + run_becnhmarks(generate_points_uniform(500), 1, cout, "uniform"); + run_becnhmarks(generate_points_uniform(1000), 1, cout, "uniform"); + run_becnhmarks(generate_points_uniform(5000), 1, cout, "uniform"); + run_becnhmarks(generate_points_uniform(10000), 1, cout, "uniform"); + run_becnhmarks(generate_points_uniform(50000), 1, cout, "uniform"); + /*run_becnhmarks(generate_points_uniform(100000), 1, cout, "uniform"); + run_becnhmarks(generate_points_uniform(1000000), 1, cout, "uniform"); + run_becnhmarks(generate_points_uniform(10000000), 1, cout, "uniform");*/ +} \ No newline at end of file diff --git a/benchmarks/dim10.csv b/benchmarks/dim10.csv new file mode 100644 index 0000000..1c788ef --- /dev/null +++ b/benchmarks/dim10.csv @@ -0,0 +1,2 @@ +kd-tree,10,50000,uniform,105.451598 +prim,10,50000,uniform,46.172490 diff --git a/benchmarks/dim2.csv b/benchmarks/dim2.csv new file mode 100644 index 0000000..1c09a29 --- /dev/null +++ b/benchmarks/dim2.csv @@ -0,0 +1,34 @@ +kd-tree,2,10,uniform,0.000008 +prim,2,10,uniform,0.000002 +kd-tree,2,50,uniform,0.000066 +prim,2,50,uniform,0.000026 +kd-tree,2,100,uniform,0.000232 +prim,2,100,uniform,0.000140 +kd-tree,2,500,uniform,0.001721 +prim,2,500,uniform,0.002644 +kd-tree,2,1000,uniform,0.003552 +prim,2,1000,uniform,0.009590 +kd-tree,2,5000,uniform,0.020224 +prim,2,5000,uniform,0.252968 +kd-tree,2,10,gauss,0.000006 +prim,2,10,gauss,0.000001 +kd-tree,2,50,gauss,0.000073 +prim,2,50,gauss,0.000023 +kd-tree,2,100,gauss,0.000200 +prim,2,100,gauss,0.000106 +kd-tree,2,500,gauss,0.001533 +prim,2,500,gauss,0.002456 +kd-tree,2,1000,gauss,0.003350 +prim,2,1000,gauss,0.009634 +kd-tree,2,5000,gauss,0.018823 +prim,2,5000,gauss,0.258483 +kd-tree,2,10000,uniform,0.055037 +prim,2,10000,uniform,1.214838 +kd-tree,2,50000,uniform,0.248771 +prim,2,50000,uniform,29.941540 +kd-tree,2,100000,uniform,0.474029 +prim,2,100000,uniform,118.912122 +kd-tree,2,1000000,uniform,6.050678 +prim,2,1000000,uniform,0.000000 +kd-tree,2,10000000,uniform,69.181657 +prim,2,10000000,uniform,0.000000 diff --git a/benchmarks/dim20.csv b/benchmarks/dim20.csv new file mode 100644 index 0000000..f5d699e --- /dev/null +++ b/benchmarks/dim20.csv @@ -0,0 +1,14 @@ +kd-tree,20,10,uniform,0.000020 +prim,20,10,uniform,0.000005 +kd-tree,20,50,uniform,0.000621 +prim,20,50,uniform,0.000076 +kd-tree,20,100,uniform,0.002770 +prim,20,100,uniform,0.000310 +kd-tree,20,500,uniform,0.067044 +prim,20,500,uniform,0.005408 +kd-tree,20,1000,uniform,0.243301 +prim,20,1000,uniform,0.020259 +kd-tree,20,5000,uniform,11.102134 +prim,20,5000,uniform,0.533273 +kd-tree,20,10000,uniform,47.100806 +prim,20,10000,uniform,2.325517 diff --git a/benchmarks/dim3.csv b/benchmarks/dim3.csv new file mode 100644 index 0000000..4d5172e --- /dev/null +++ b/benchmarks/dim3.csv @@ -0,0 +1,22 @@ +kd-tree,3,10,uniform,0.000010 +prim,3,10,uniform,0.000002 +kd-tree,3,50,uniform,0.000118 +prim,3,50,uniform,0.000024 +kd-tree,3,100,uniform,0.000359 +prim,3,100,uniform,0.000107 +kd-tree,3,500,uniform,0.003382 +prim,3,500,uniform,0.002890 +kd-tree,3,1000,uniform,0.006814 +prim,3,1000,uniform,0.010001 +kd-tree,3,5000,uniform,0.051790 +prim,3,5000,uniform,0.281046 +kd-tree,3,10000,uniform,0.110697 +prim,3,10000,uniform,1.263761 +kd-tree,3,50000,uniform,0.676556 +prim,3,50000,uniform,32.236291 +kd-tree,3,100000,uniform,1.322128 +prim,3,100000,uniform,129.617489 +kd-tree,3,1000000,uniform,16.640953 +prim,3,1000000,uniform,0.000000 +kd-tree,3,10000000,uniform,186.681225 +prim,3,10000000,uniform,0.000000 diff --git a/benchmarks/dim4.csv b/benchmarks/dim4.csv new file mode 100644 index 0000000..b31cad8 --- /dev/null +++ b/benchmarks/dim4.csv @@ -0,0 +1,22 @@ +kd-tree,4,10,uniform,0.000009 +prim,4,10,uniform,0.000003 +kd-tree,4,50,uniform,0.000206 +prim,4,50,uniform,0.000031 +kd-tree,4,100,uniform,0.000642 +prim,4,100,uniform,0.000145 +kd-tree,4,500,uniform,0.007234 +prim,4,500,uniform,0.002741 +kd-tree,4,1000,uniform,0.015581 +prim,4,1000,uniform,0.013089 +kd-tree,4,5000,uniform,0.120508 +prim,4,5000,uniform,0.321342 +kd-tree,4,10000,uniform,0.274742 +prim,4,10000,uniform,1.330939 +kd-tree,4,50000,uniform,1.599925 +prim,4,50000,uniform,36.231665 +kd-tree,4,100000,uniform,3.741252 +prim,4,100000,uniform,0.000000 +kd-tree,4,1000000,uniform,54.396733 +prim,4,1000000,uniform,0.000000 +kd-tree,4,10000000,uniform,673.999727 +prim,4,10000000,uniform,0.000000 diff --git a/benchmarks/dim5.csv b/benchmarks/dim5.csv new file mode 100644 index 0000000..8a1ff08 --- /dev/null +++ b/benchmarks/dim5.csv @@ -0,0 +1,18 @@ +kd-tree,5,10,uniform,0.000012 +prim,5,10,uniform,0.000003 +kd-tree,5,50,uniform,0.000273 +prim,5,50,uniform,0.000030 +kd-tree,5,100,uniform,0.001298 +prim,5,100,uniform,0.000210 +kd-tree,5,500,uniform,0.010577 +prim,5,500,uniform,0.002901 +kd-tree,5,1000,uniform,0.028380 +prim,5,1000,uniform,0.012231 +kd-tree,5,5000,uniform,0.210629 +prim,5,5000,uniform,0.302468 +kd-tree,5,10000,uniform,0.572781 +prim,5,10000,uniform,0.000000 +kd-tree,5,50000,uniform,3.905315 +prim,5,50000,uniform,0.000000 +kd-tree,5,100000,uniform,9.507483 +prim,5,100000,uniform,0.000000 diff --git a/emst.h b/emst.h index 31f74c9..88fff47 100644 --- a/emst.h +++ b/emst.h @@ -26,7 +26,7 @@ class EmstSolver { template class KdTreeSolver : public EmstSolver { public: - KdTreeSolver(std::vector> & points) :num_points(points.size()) { + KdTreeSolver(const std::vector> & points) :num_points(points.size()) { dsu.reset(num_points); tree = KdTree(points, static_cast(floor(log2(num_points)) - 1)); is_fully_connected.assign(tree.get_maximal_id() + 1, false); @@ -141,7 +141,7 @@ class KdTreeSolver : public EmstSolver { template class PrimSolver : public EmstSolver { public: - PrimSolver(std::vector> & points) { + PrimSolver(const std::vector> & points) { solve(points); } diff --git a/main.cpp b/main.cpp index 4dfac46..f1c329b 100644 --- a/main.cpp +++ b/main.cpp @@ -7,7 +7,7 @@ #include #include #include "emst.h" - +#include "benchmark.h" using namespace std; template