Added benches, lookup remaining

This commit is contained in:
Olek 2016-12-26 14:47:59 +01:00
parent 7ae4d8fd9d
commit 7a6734cd4d
5 changed files with 157 additions and 27 deletions

View File

@ -3,8 +3,18 @@ name = "kdtree-rust"
version = "0.1.0"
authors = ["Aleksander Fular <ntszar@gmail.com>"]
[lib]
name = "kdtree"
path = "src//lib.rs"
bench = false
[[bench]]
name = "bench"
harness = false
[dependencies]
rand = "*"
bencher = "*"
[dev-dependencies]
quickcheck = "0.3"

46
src/bench.rs Normal file
View File

@ -0,0 +1,46 @@
#[macro_use]
extern crate bencher;
extern crate kdtree;
extern crate rand;
use bencher::Bencher;
#[derive(Copy, Clone, PartialEq)]
pub struct Point2WithId {
dims: [f64; 2],
pub id: i32,
}
impl Point2WithId {
pub fn new(id: i32, x: f64, y: f64) -> Point2WithId {
Point2WithId {
dims: [x, y],
id: id,
}
}
}
impl kdtree::kdtree::KdtreePointTrait for Point2WithId {
fn dims(&self) -> &[f64] {
return &self.dims;
}
}
fn a(b: &mut Bencher) {
let len = 1000usize;
let mut points : Vec<Point2WithId> = vec![];
//let mut kdtree = KdTree::new_with_capacity(3, 16);
for id in 0..len {
let x : f64 = rand::random();
points.push(Point2WithId::new(id as i32, x, x));
// points.push(rand_data());
}
b.iter(|| {
let tree = kdtree::kdtree::Kdtree::new(points.clone());
});
}
benchmark_group!(benches, a);
benchmark_main!(benches);

View File

@ -1,4 +1,3 @@
use ::kdtree::*;
pub struct Bounds {
@ -11,7 +10,7 @@ impl Bounds {
bounds: vec![],
};
bounds.bounds.resize(points[0].dims().len(), (0.,0.));
bounds.bounds.resize(points[0].dims().len(), (0., 0.));
for i in 0..points[0].dims().len() {
bounds.bounds[i].0 = points[0].dims()[i];
@ -43,6 +42,28 @@ impl Bounds {
widest_dimension
}
pub fn get_midvalue_of_widest_dim(&self) -> f64 {
(self.bounds[self.get_widest_dim()].0 + self.bounds[self.get_widest_dim()].1) / 2.0
}
pub fn clone_moving_max(&self, value: f64, dimension: usize) -> Bounds {
let mut cloned = Bounds {
bounds: self.bounds.clone()
};
cloned.bounds[dimension].1 = value;
cloned
}
pub fn clone_moving_min(&self, value: f64, dimension: usize) -> Bounds {
let mut cloned = Bounds {
bounds: self.bounds.clone()
};
cloned.bounds[dimension].0 = value;
cloned
}
}
@ -53,9 +74,10 @@ mod tests {
#[test]
fn bounds_test() {
let p1 = Point2WithId::new(1,1.0,0.5);
let p2 = Point2WithId::new(1,3.0,4.0);
let v = vec![p1,p2];
let p1 = Point2WithId::new(1, 1.0, 0.5);
let p2 = Point2WithId::new(1, 3.0, 4.0);
let v = vec![p1, p2];
let bounds = Bounds::new_from_points(&v);
@ -63,6 +85,5 @@ mod tests {
assert_eq!((0.5, 4.0), bounds.bounds[1]);
assert_eq!(1, bounds.get_widest_dim());
}
}

View File

@ -13,32 +13,50 @@ pub struct Kdtree<T> {
nodes: Vec<KdtreeNode<T>>,
}
impl<T: KdtreePointTrait> Kdtree<T> {
pub fn new(points: Vec<T>) -> Kdtree<T> {
impl<T: KdtreePointTrait + Copy> Kdtree<T> {
pub fn new(mut points: Vec<T>) -> Kdtree<T> {
if points.len() == 0 {
panic!("empty vector point not allowed");
}
let rect = Bounds::new_from_points(&points);
Kdtree {
let mut tree = Kdtree {
nodes: vec![],
}
};
tree.build_tree(&mut points, &rect);
tree
}
fn add_node(&mut self, p: T) {
fn add_node(&mut self, p: T) -> usize {
let node = KdtreeNode::new(p);
self.nodes.push(node);
self.nodes.len() - 1
}
fn add_left_node(&mut self, for_node: usize, ) {
{
let len = self.nodes.len();
let node = self.nodes.get_mut(for_node).unwrap();
node.left_node = Some(len);
fn build_tree(&mut self, nodes: &mut [T], bounds: &Bounds) -> usize {
let (splitting_index, pivot_value) = partition::partition_sliding_midpoint(nodes, bounds.get_midvalue_of_widest_dim(), bounds.get_widest_dim());
let node_id = self.add_node(nodes[splitting_index]);
let nodes_len = nodes.len();
if splitting_index > 0 {
let left_rect = bounds.clone_moving_max(bounds.get_midvalue_of_widest_dim(), bounds.get_widest_dim());
let left_child_id = self.build_tree(&mut nodes[0..splitting_index], &left_rect);
self.nodes[node_id].left_node = Some(left_child_id);
}
//self.nodes.push(KdtreeNode::new());
if splitting_index < nodes.len() - 1 {
let right_rect = bounds.clone_moving_min(bounds.get_midvalue_of_widest_dim(), bounds.get_widest_dim());
let right_child_id = self.build_tree(&mut nodes[splitting_index + 1..nodes_len], &right_rect);
self.nodes[node_id].right_node = Some(right_child_id);
}
node_id
}
}
@ -74,12 +92,44 @@ mod tests {
Kdtree::new(empty_vec);
}
#[test]
fn test2() {
let p1 = Point2WithId::new(1, 1., 2.);
let p2 = Point2WithId::new(1, 1., 2.);
let vec = vec![p1, p2];
quickcheck! {
fn tree_build_creates_tree_with_as_many_leafs_as_there_is_points(xs : Vec<f64>) -> bool {
if(xs.len() == 0) {
return true;
}
let mut vec : Vec<Point2WithId> = vec![];
for i in 0 .. xs.len() {
let p = Point2WithId::new(i as i32, xs[i], xs[i]);
Kdtree::new(vec);
vec.push(p);
}
let tree = Kdtree::new(vec);
let mut to_iterate : Vec<usize> = vec![];
to_iterate.push(0);
let mut str = String::new();
while to_iterate.len() > 0 {
let last_index = to_iterate.last().unwrap().clone();
let ref x = tree.nodes.get(last_index).unwrap();
to_iterate.pop();
if x.left_node.is_some() {
to_iterate.push(x.left_node.unwrap());
}
if x.right_node.is_some() {
to_iterate.push(x.right_node.unwrap());
}
str.push_str(&format!("Index: {} has ln {} has rn {} \n", last_index, x.left_node.is_some(), x.right_node.is_some()));
}
// println!("str is: {}", str);
xs.len() == tree.nodes.len()
}
}
}

View File

@ -12,7 +12,7 @@ struct PartitionPointHelper {
index_of_splitter: usize,
}
fn partition_sliding_midpoint_helper<T: KdtreePointTrait>(vec: &mut Vec<T>, midpoint_value: f64, partition_on_dimension: usize) -> PartitionPointHelper {
fn partition_sliding_midpoint_helper<T: KdtreePointTrait>(vec: &mut [T], midpoint_value: f64, partition_on_dimension: usize) -> PartitionPointHelper {
let mut closest_index = 0;
let mut closest_distance = (vec[0].dims()[partition_on_dimension] - midpoint_value).abs();
@ -51,10 +51,13 @@ fn partition_sliding_midpoint_helper<T: KdtreePointTrait>(vec: &mut Vec<T>, midp
}
}
pub fn partition_sliding_midpoint<T: KdtreePointTrait>(vec: &mut Vec<T>, midpoint_value: f64, partition_on_dimension: usize) -> (usize, f64) {
pub fn partition_sliding_midpoint<T: KdtreePointTrait>(vec: &mut [T], midpoint_value: f64, partition_on_dimension: usize) -> (usize, f64) {
let vec_len = vec.len();
debug_assert!(vec[0].dims().len() > partition_on_dimension);
debug_assert!(vec.len() > 1);
if vec.len() == 1 {
return (0, vec[0].dims()[partition_on_dimension]);
}
let partition_point_data = partition_sliding_midpoint_helper(vec, midpoint_value, partition_on_dimension);
@ -74,7 +77,7 @@ pub fn partition_sliding_midpoint<T: KdtreePointTrait>(vec: &mut Vec<T>, midpoin
}
}
fn partition_kdtree<T: KdtreePointTrait>(vec: &mut Vec<T>, index_of_splitting_point: usize, partition_on_dimension: usize) -> usize {
fn partition_kdtree<T: KdtreePointTrait>(vec: &mut [T], index_of_splitting_point: usize, partition_on_dimension: usize) -> usize {
if vec.len() == 1 {
return 0;
}