Skip to content

Commit

Permalink
Benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewB330 committed Jan 26, 2019
1 parent bbbfda3 commit da7e939
Show file tree
Hide file tree
Showing 10 changed files with 214 additions and 5 deletions.
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
85 changes: 85 additions & 0 deletions benchmark.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#pragma once
#include <iostream>
#include <iomanip>
#include <cassert>
#include <chrono>
#include "emst.h"
using namespace std::chrono;

double uniform() {
return rand() * 1.0 / RAND_MAX;
}

template<size_t DIM>
std::vector<Point<DIM>> generate_points_uniform(size_t num_points, double MAX = 100.0) {
std::vector<Point<DIM>> points;
for (size_t i = 0; i < num_points; i++) {
Point<DIM> p;
for (size_t k = 0; k < DIM; k++) {
p[k] = (uniform() * 2.0 - 1.0) * MAX;
}
points.push_back(p);
}
return points;
}

template<size_t DIM>
std::vector<Point<DIM>> generate_points_gauss(size_t num_points, double MAX = 100.0) {
std::vector<Point<DIM>> points;
for (size_t i = 0; i < num_points; i++) {
Point<DIM> 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<typename EmstSolverType, size_t DIM>
BenchmarkResult run_benchmark(const std::vector<Point<DIM>> & 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<double> elapsed_seconds = end - start;
result.time = elapsed_seconds.count() / samples;
return result;
}

template<size_t DIM>
void run_becnhmarks(const std::vector<Point<DIM>> & points, size_t samples, std::ostream & cout, std::string distribution = "none") {
auto result_kd = run_benchmark<KdTreeSolver<DIM>, DIM>(points, samples);
auto result_prim = (points.size() < 100000 ? run_benchmark<PrimSolver<DIM>, 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<size_t DIM>
void run_becnhmarks(std::ostream & cout) {
run_becnhmarks<DIM>(generate_points_uniform<DIM>(10), 100, cout, "uniform");
run_becnhmarks<DIM>(generate_points_uniform<DIM>(50), 100, cout, "uniform");
run_becnhmarks<DIM>(generate_points_uniform<DIM>(100), 1, cout, "uniform");
run_becnhmarks<DIM>(generate_points_uniform<DIM>(500), 1, cout, "uniform");
run_becnhmarks<DIM>(generate_points_uniform<DIM>(1000), 1, cout, "uniform");
run_becnhmarks<DIM>(generate_points_uniform<DIM>(5000), 1, cout, "uniform");
run_becnhmarks<DIM>(generate_points_uniform<DIM>(10000), 1, cout, "uniform");
run_becnhmarks<DIM>(generate_points_uniform<DIM>(50000), 1, cout, "uniform");
/*run_becnhmarks<DIM>(generate_points_uniform<DIM>(100000), 1, cout, "uniform");
run_becnhmarks<DIM>(generate_points_uniform<DIM>(1000000), 1, cout, "uniform");
run_becnhmarks<DIM>(generate_points_uniform<DIM>(10000000), 1, cout, "uniform");*/
}
2 changes: 2 additions & 0 deletions benchmarks/dim10.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
kd-tree,10,50000,uniform,105.451598
prim,10,50000,uniform,46.172490
34 changes: 34 additions & 0 deletions benchmarks/dim2.csv
Original file line number Diff line number Diff line change
@@ -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
14 changes: 14 additions & 0 deletions benchmarks/dim20.csv
Original file line number Diff line number Diff line change
@@ -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
22 changes: 22 additions & 0 deletions benchmarks/dim3.csv
Original file line number Diff line number Diff line change
@@ -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
22 changes: 22 additions & 0 deletions benchmarks/dim4.csv
Original file line number Diff line number Diff line change
@@ -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
18 changes: 18 additions & 0 deletions benchmarks/dim5.csv
Original file line number Diff line number Diff line change
@@ -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
4 changes: 2 additions & 2 deletions emst.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class EmstSolver {
template<size_t DIM>
class KdTreeSolver : public EmstSolver<DIM> {
public:
KdTreeSolver(std::vector<Point<DIM>> & points) :num_points(points.size()) {
KdTreeSolver(const std::vector<Point<DIM>> & points) :num_points(points.size()) {
dsu.reset(num_points);
tree = KdTree<DIM>(points, static_cast<size_t>(floor(log2(num_points)) - 1));
is_fully_connected.assign(tree.get_maximal_id() + 1, false);
Expand Down Expand Up @@ -141,7 +141,7 @@ class KdTreeSolver : public EmstSolver<DIM> {
template<size_t DIM>
class PrimSolver : public EmstSolver<DIM> {
public:
PrimSolver(std::vector<Point<DIM>> & points) {
PrimSolver(const std::vector<Point<DIM>> & points) {
solve(points);
}

Expand Down
2 changes: 1 addition & 1 deletion main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include <memory>
#include <string>
#include "emst.h"

#include "benchmark.h"
using namespace std;

template<size_t DIM>
Expand Down

0 comments on commit da7e939

Please sign in to comment.