Skip to content

Commit

Permalink
Merge pull request #8 from azizkayumov/develop
Browse files Browse the repository at this point in the history
reverse knn (preinsert + batchnn)
  • Loading branch information
azizkayumov authored Aug 28, 2024
2 parents 5e8557b + c256f20 commit e1f138a
Show file tree
Hide file tree
Showing 18 changed files with 1,427 additions and 568 deletions.
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
[workspace]

members = [
"lib",
"bench",
"demo",
"lib",
]
resolver = "2"

[patch.crates-io]
rindex = { path = "lib" }
16 changes: 16 additions & 0 deletions bench/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "bench"
version = "0.1.0"
edition = "2021"
authors = ["Kayumov A.I. <[email protected]>"]

[dev-dependencies]
rindex = { path = "../lib" }
rand = "0.8.5"
rstar = "0.12.0"
ordered-float = "3.4.0"
criterion = "0.5.1"

[[bench]]
name = "main"
harness = false
10 changes: 10 additions & 0 deletions bench/benches/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use criterion::{criterion_group, criterion_main};
mod uniform;

criterion_group!(
benches,
uniform::build,
uniform::query,
uniform::query_radius
);
criterion_main!(benches);
67 changes: 67 additions & 0 deletions bench/benches/uniform/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use crate::uniform::{DELETION_PROB, DIMENSION as D, K, NUM_OPERATIONS};
use core::f64;
use criterion::Criterion;
use rand::{rngs::StdRng, Rng, SeedableRng};
use rindex::Rindex;
use rstar::RTree;

pub fn benchmark(criterion: &mut Criterion) {
let mut group = criterion.benchmark_group("build");
//group.sample_size(10);

group.bench_function("rindex", |b| {
b.iter(|| {
build_rindex();
});
});

group.bench_function("rstar", |b| {
b.iter(|| {
build_rstar();
});
});
}

pub fn build_rindex() -> (Rindex<D>, Vec<(usize, [f64; D])>) {
let mut rng = StdRng::seed_from_u64(0);
let mut index = Rindex::new(10, K).expect("Failed to create Rindex");
let mut points = Vec::new();
for _ in 0..NUM_OPERATIONS {
let should_delete = rng.gen_bool(DELETION_PROB);
if should_delete && !points.is_empty() {
let idx = rng.gen_range(0..points.len());
let (point_id, _) = points.swap_remove(idx);
index.delete(point_id);
} else {
let mut point = [0.0; D];
for i in 0..D {
point[i] = rng.gen_range(-100.0..100.0);
}
let point_id = index.insert(point);
points.push((point_id, point));
}
}
(index, points)
}

pub fn build_rstar() -> (RTree<[f64; D]>, Vec<[f64; D]>) {
let mut rng = StdRng::seed_from_u64(0);
let mut rstar = rstar::RTree::new();
let mut points = Vec::new();
for _ in 0..NUM_OPERATIONS {
let should_delete = rng.gen_bool(DELETION_PROB);
if should_delete && !points.is_empty() {
let idx = rng.gen_range(0..points.len());
let point = points.swap_remove(idx);
rstar.remove(&point);
} else {
let mut point = [0.0; D];
for i in 0..D {
point[i] = rng.gen_range(-100.0..100.0);
}
rstar.insert(point);
points.push(point);
}
}
(rstar, points)
}
15 changes: 15 additions & 0 deletions bench/benches/uniform/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
mod build;
mod query;
mod query_radius;

// Benchmark parameters:
pub const DIMENSION: usize = 2;
pub const NUM_OPERATIONS: usize = 10000; // Number of operations to perform (insertions and deletions)
pub const DELETION_PROB: f64 = 0.2; // Probability of deleting a point for simulating dynamic data
pub const K: usize = 10; // Number of neighbors to query
pub const RADIUS: f64 = 5.0; // Radius for range queries
pub const RADIUS_SQUARED: f64 = RADIUS * RADIUS;

pub use build::benchmark as build;
pub use query::benchmark as query;
pub use query_radius::benchmark as query_radius;
67 changes: 67 additions & 0 deletions bench/benches/uniform/query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use crate::uniform::build::{build_rindex, build_rstar};
use crate::uniform::{DIMENSION as D, K};
use core::f64;
use criterion::Criterion;
use ordered_float::OrderedFloat;
use rindex::Rindex;
use rstar::RTree;
use std::collections::BinaryHeap;

pub fn benchmark(criterion: &mut Criterion) {
let mut group = criterion.benchmark_group("query");
//group.sample_size(10);

let (rindex, pts) = build_rindex();
group.bench_function("rindex", |b| {
b.iter(|| {
query_rindex(&rindex, &pts);
});
});

let (rstar, pts) = build_rstar();
group.bench_function("rstar", |b| {
b.iter(|| {
query_rstar(&rstar, &pts);
});
});

group.bench_function("list", |b| {
b.iter(|| {
query_list(&pts);
});
});
}

fn query_rindex(rindex: &Rindex<D>, points: &Vec<(usize, [f64; D])>) {
for (query_id, _) in points {
let (neighbors, _) = rindex.neighbors_of(*query_id);
assert_eq!(neighbors.len(), 10);
}
}

fn query_rstar(rstar: &RTree<[f64; D]>, points: &Vec<[f64; D]>) {
for query in points {
let mut iter = rstar.nearest_neighbor_iter(&query);
let results = iter.by_ref().take(K).collect::<Vec<_>>();
assert_eq!(results.len(), K);
}
}

fn query_list(points: &Vec<[f64; D]>) {
for query in points {
let mut results = BinaryHeap::from(vec![OrderedFloat(f64::INFINITY); K]);
for point in points {
let dist = query
.iter()
.zip(point.iter())
.map(|(a, b)| (a - b).powi(2))
.sum::<f64>()
.sqrt();
if dist < results.peek().unwrap().0 {
results.push(OrderedFloat(dist));
results.pop();
}
}
assert_eq!(results.len(), K);
}
}
65 changes: 65 additions & 0 deletions bench/benches/uniform/query_radius.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use crate::uniform::build::{build_rindex, build_rstar};
use crate::uniform::{DIMENSION as D, RADIUS, RADIUS_SQUARED};
use core::f64;
use criterion::Criterion;
use rindex::Rindex;
use rstar::RTree;

pub fn benchmark(criterion: &mut Criterion) {
let mut group = criterion.benchmark_group("query_radius");
//group.sample_size(10);

let (rindex, pts) = build_rindex();
group.bench_function("rindex", |b| {
b.iter(|| {
query_range_rindex(&rindex, &pts);
});
});

let (rstar, pts) = build_rstar();
group.bench_function("rstar", |b| {
b.iter(|| {
query_range_rstar(&rstar, &pts);
});
});

group.bench_function("list", |b| {
b.iter(|| {
query_range_list(&pts);
});
});
}

fn query_range_rindex(rindex: &Rindex<D>, points: &Vec<(usize, [f64; D])>) {
for (query_id, query) in points {
let (neighbors, _) = rindex.query(&query, RADIUS);
assert!(neighbors.contains(query_id));
}
}

fn query_range_rstar(rstar: &RTree<[f64; D]>, points: &Vec<[f64; D]>) {
for query in points {
let result = rstar
.locate_within_distance(*query, RADIUS_SQUARED)
.collect::<Vec<_>>();
assert!(result.contains(&query));
}
}

fn query_range_list(points: &Vec<[f64; D]>) {
for query in points {
let mut results = Vec::new();
for point in points {
let dist = query
.iter()
.zip(point.iter())
.map(|(a, b)| (a - b).powi(2))
.sum::<f64>()
.sqrt();
if dist <= RADIUS {
results.push(dist);
}
}
assert!(results.contains(&0.0));
}
}
Loading

0 comments on commit e1f138a

Please sign in to comment.