K-dimensional tree in Rust for fast geospatial indexing and lookup

Overview

kdtree Build Status

K-dimensional tree in Rust for fast geospatial indexing and nearest neighbors lookup

Usage

Add kdtree to Cargo.toml

[dependencies]
kdtree = "0.5.1"

Add points to kdtree and query nearest n points with distance function

use kdtree::KdTree;
use kdtree::ErrorKind;
use kdtree::distance::squared_euclidean;

let a: ([f64; 2], usize) = ([0f64, 0f64], 0);
let b: ([f64; 2], usize) = ([1f64, 1f64], 1);
let c: ([f64; 2], usize) = ([2f64, 2f64], 2);
let d: ([f64; 2], usize) = ([3f64, 3f64], 3);

let dimensions = 2;
let mut kdtree = KdTree::new(dimensions);

kdtree.add(&a.0, a.1).unwrap();
kdtree.add(&b.0, b.1).unwrap();
kdtree.add(&c.0, c.1).unwrap();
kdtree.add(&d.0, d.1).unwrap();

assert_eq!(kdtree.size(), 4);
assert_eq!(
    kdtree.nearest(&a.0, 0, &squared_euclidean).unwrap(),
    vec![]
);
assert_eq!(
    kdtree.nearest(&a.0, 1, &squared_euclidean).unwrap(),
    vec![(0f64, &0)]
);
assert_eq!(
    kdtree.nearest(&a.0, 2, &squared_euclidean).unwrap(),
    vec![(0f64, &0), (2f64, &1)]
);
assert_eq!(
    kdtree.nearest(&a.0, 3, &squared_euclidean).unwrap(),
    vec![(0f64, &0), (2f64, &1), (8f64, &2)]
);
assert_eq!(
    kdtree.nearest(&a.0, 4, &squared_euclidean).unwrap(),
    vec![(0f64, &0), (2f64, &1), (8f64, &2), (18f64, &3)]
);
assert_eq!(
    kdtree.nearest(&a.0, 5, &squared_euclidean).unwrap(),
    vec![(0f64, &0), (2f64, &1), (8f64, &2), (18f64, &3)]
);
assert_eq!(
    kdtree.nearest(&b.0, 4, &squared_euclidean).unwrap(),
    vec![(0f64, &1), (2f64, &0), (2f64, &2), (8f64, &3)]
);

Benchmark

cargo bench with 2.3 GHz Intel i5-7360U:

cargo bench
     Running target/release/deps/bench-9e622e6a4ed9b92a

running 2 tests
test bench_add_to_kdtree_with_1k_3d_points       ... bench:         106 ns/iter (+/- 25)
test bench_nearest_from_kdtree_with_1k_3d_points ... bench:       1,237 ns/iter (+/- 266)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out

Thanks Eh2406 for various fixes and perf improvements.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Comments
  • add ability to remove item

    add ability to remove item

    From limited testing this seems to work well. Had to add a partialeq constraint to filter data and points. I don't rebalance the tree, just remove the items, not sure if that would be helpful. Fixes #30

    opened by etrombly 4
  • Is it possible to have a function nearest_radius that includes the maximum radius?

    Is it possible to have a function nearest_radius that includes the maximum radius?

    I think that everything is ready to allow users to pass the maximum radius when searching for nearest points. Unfortunately rust does not support optional arguments yet, so something like this could be trivial to implement:

    pub fn nearest_radius<F>(
            &self,
            point: &[A],
            num: usize,
            radius: A,
            distance: &F,
        )
    

    The current function

    pub fn nearest<F>(
            &self,
            point: &[A],
            num: usize,
            distance: &F,
        )
    

    calls to

    self.nearest_step(
                    point,
                    num,
                    A::infinity(),
                    distance,
                    &mut pending,
                    &mut evaluated,
                );
    

    which already has the maximum radius as A::infinity().

    opened by exepulveda 4
  • Bug: distance_to_space on wrong thing. Massive performance wins.

    Bug: distance_to_space on wrong thing. Massive performance wins.

    This is big! I stumbled on this experimenting with a refactoring.

    New bench:

    running 2 tests
    test bench_add_to_kdtree_with_1k_3d_points       ... bench:         156 ns/iter (+/- 44)
    test bench_nearest_from_kdtree_with_1k_3d_points ... bench:       3,603 ns/iter (+/- 3,217)
    

    Old bench:

    running 2 tests
    test bench_add_to_kdtree_with_1k_3d_points       ... bench:         139 ns/iter (+/- 61)
    test bench_nearest_from_kdtree_with_1k_3d_points ... bench:       6,677 ns/iter (+/- 6,613)
    

    Maby evan "0.3.1"?

    opened by Eh2406 4
  • Stack overflow in add_to_bucket

    Stack overflow in add_to_bucket

        I get the same error when I use this crate.
    

    And I figured out the reason.

    The avg will be equal to a, under the limit of f64's accuracy. As a result, the fn split() can't split this node successfully. In this situation, fn add_to_bucket() and fn split() will call each other infinitely.

        let a = 0.47945351705599926f64;
        let b = 0.47945351705599931f64;
        
        let avg = (a + b) / 2.0;
    
        println!("{:.20E}", a);
        println!("{:.20E}", b);
        println!("{:.20E}", avg);
    

    And the resolution is extremely easy. Just modify fn belongs_in_left() like this

    fn belongs_in_left(&self, point: &[A]) -> bool {
            // before
            // point[self.split_dimension.unwrap()] < self.split_value.unwrap()
            // after
            point[self.split_dimension.unwrap()] <= self.split_value.unwrap()
    }
    

    Originally posted by @TYPEmber in https://github.com/mrhooray/kdtree-rs/issues/20#issuecomment-1344093398

    opened by TYPEmber 2
  • What is a computational complexity of queuing nearest point?

    What is a computational complexity of queuing nearest point?

    For unknown reason the kdtree-rs library takes about 1000x more time than Python's sklearn.neighbors.KDTree for very large datasets (like several millions of points). Can you confirm we have O(log(n)) for the nearest point query?

    opened by ababo 2
  • Some cleanups

    Some cleanups

    • Run cargo fmt
    • Run cargo +nightly clippy and fixed warnings
    • Run cargo fix --edition
    • Fixed docs in src/distance.rs, and other cosmetic changes
    • Replaced assert!(x == y) with assert_eq!(x, y)
    opened by ordovicia 2
  • Stack overflow in add_to_bucket

    Stack overflow in add_to_bucket

    I haven't minimised yet, but in some circumstances, add_to_bucket results in a stack overflow. Without looking too closely, I think there's an infinite (or exponential) loop where add_to_bucket calls split, which in turn calls add_to_bucket, etc.

    Edit: If I create a KdTree with sufficient capacity to begin with, the stack overflow doesn't occur, so the problem is with it dynamically resizing.

    opened by varkor 2
  • Add serde to support serialization

    Add serde to support serialization

    I have a project encoding location data into a kdtree. Because all the fields are private it is a hassle to add getters for all of them. Supporting serde here would be a lot more convenient.

    opened by etrombly 2
  • Question about U on kdtre.rs

    Question about U on kdtre.rs

    Hi,

    I'm interested in space aware datastructures and just learning rust, I was wondering what does the U: AsRef<f64> means in the kdtree.rs file. Does it mean that there should be a generic parameter U that defaults to a slice of f64 items that are default implemented and functions like:

        pub fn nearest<F>(&self,
                          point: &[f64],
                          num: usize,
                          distance: &F)
                          -> Result<Vec<(f64, &T)>, ErrorKind>
    

    can be implemented to use a type U rather than f64?

    opened by odarbelaeze 2
  • Release a new Version

    Release a new Version

    It seems like a lot has changed since the last release (the documentation doesn't even match anymore). So it would be cool if you could release a new version. I'll have to use the git version directly till then I guess.

    opened by CryZe 2
  • Do you have a plan to upgrade the version of crate ?

    Do you have a plan to upgrade the version of crate ?

    Hello ,
    First of all, thank you for your work. I'm planning to use your kdtree crate in rust. In my checking, the latest crate version is 0.6.0 , which is almost 3 years ago. But it seems that git hub has more commits after it. Do you have a plan to upgrade the version of crate ?

    opened by cdragon-choi 1
Owner
Rui Hu
Rui Hu
Ternary search tree collection in rust

tst Ternary search tree collection in rust with similar API to std::collections as it possible. Ternary search tree is a type of trie (sometimes calle

Alexey Pervushin 20 Dec 7, 2022
A tree structure in Rust optimized for looking up domain names, with wildcard support

domain-lookup-tree Overview DomainLookupTree is a data structure which provides efficient domain name lookup matching with support for wildcard entrie

null 18 Nov 28, 2022
Recursive & Iterative Binary Search Tree Implementations within Rust

bst-rs Recursive & Iterative Binary Search Tree Implementations within Rust Table of Contents Personal Goals About Quick Start License Contributing In

Hamothy 6 Oct 1, 2022
TreeFlat - the simplest way to build & traverse a pre-order Tree in Rust

TreeFlat is the simplest way to build & traverse a pre-order Tree for Rust. Alpha-relase! If you build a Tree in pre-order, and display in pre-order,

Mario Montoya 22 Dec 16, 2022
Bw-Tree for Rust

Bw-Tree for Rust This is a work-in-progress implementation of Bw-Trees for Rust. Nothing works, this is mostly for my own education right now. Design

Pekka Enberg 11 May 25, 2023
Redis Tree(Ploytree) Structure Module

RedisTree is a Redis module that implements Polytree as a native data type. It allows creating,locating,pushing and detaching tree from Redi

Bonsai 63 Dec 25, 2022
B-Tree map for pub/sub services

submap B-tree map for pub/sub services. Create a new subscription map let mut smap: SubMap<Client> = SubMap::new(); where "Client" is a pub/sub client

Altertech 6 Sep 21, 2022
A prefix tree (trie) is a data structure that allows you to store an associative array whose keys are strings

RadixTrie A prefix tree (trie) is a data structure that allows you to store an associative array whose keys are strings. It is a root tree, each edge

null 2 Jan 28, 2022
Fast, efficient, and robust memory reclamation for concurrent data structures

Seize Fast, efficient, and robust memory reclamation for concurrent data structures. Introduction Concurrent data structures are faced with the proble

Ibraheem Ahmed 240 Dec 23, 2022
Blazing fast immutable collection datatypes for Rust.

imbl Blazing fast immutable collection datatypes for Rust. This is a fork of the im crate, which appears to be unmaintained. (This fork is not current

null 38 Jul 11, 2022
Serde is a framework for serializing and deserializing Rust data structures efficiently and generically.

Serde is a framework for serializing and deserializing Rust data structures efficiently and generically.

null 6.5k Dec 31, 2022
Coding-challenge - Algorithms and Data-structures, problems and solutions in Rust language using cargo-workspaces

Coding Challenge LeetCode/Hackerrank e.t.c Using this as an opportunity to improve my knowledge of rust lang If you found this repo useful to you, add

Tolumide Shopein 17 Apr 24, 2022
Rust-algorithm-club - Learn algorithms and data structures with Rust

Rust Algorithm Club ?? ?? This repo is under construction. Most materials are written in Chinese. Check it out here if you are able to read Chinese. W

Weihang Lo 360 Dec 28, 2022
Array helpers for Rust's Vector and String types

array_tool Array helpers for Rust. Some of the most common methods you would use on Arrays made available on Vectors. Polymorphic implementations for

Daniel P. Clark 69 Dec 9, 2022
Algorithms and Data Structures of all kinds written in Rust.

Classic Algorithms in Rust This repo contains the implementation of various classic algorithms for educational purposes in Rust. Right now, it is in i

Alexander González 49 Dec 14, 2022
A simple rust library to help create octrees and quadtrees for chunked level of detail

LodTree LodTree, a simple tree data structure for doing chunk-based level of detail. Goals The aim of this crate is to provide a generic, easy to use

Dimev 14 Dec 29, 2022
Serialize/DeSerialize for Rust built-in types and user defined types (complex struct types)

Serialize/DeSerialize for Rust built-in types and user defined types (complex struct types)

null 2 May 3, 2022
Common data structures and algorithms in Rust

Contest Algorithms in Rust A collection of classic data structures and algorithms, emphasizing usability, beauty and clarity over full generality. As

Aram Ebtekar 3.3k Dec 27, 2022
Rust data structures and client for the PubChem REST API

pubchem.rs Rust data structures and client for the PubChem REST API. ?? Usage ?? Compound Create a Compound to query the PubChem API for a single comp

Martin Larralde 2 Jan 18, 2022