Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Nearest Neighbor] Code and basic test for nearest neighbor #28

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 1 addition & 36 deletions src/rectangle.ml
Original file line number Diff line number Diff line change
Expand Up @@ -85,39 +85,4 @@ let empty =
Array.Floatarray.unsafe_set arr 1 0.;
Array.Floatarray.unsafe_set arr 2 0.;
Array.Floatarray.unsafe_set arr 3 0.;
arr

let get arr i = List.nth arr i

let mindist p e =
let x0, y0, x1, y1 = (x0 e, y0 e, x1 e, y1 e) in
let gete ind = match ind with 0 -> x0 | 1 -> y0 | 2 -> x1 | _ -> y1 in
let dist i =
if get p i < gete i then (gete i -. get p i) *. (gete i -. get p i)
else if get p i > gete (i + 2) then
(get p i -. gete (i + 2)) *. (get p i -. gete (i + 2))
else 0.
in
dist 0 +. dist 1

let minmaxdist p e =
let x0, y0, x1, y1 = (x0 e, y0 e, x1 e, y1 e) in
let gete ind = match ind with 0 -> x0 | 1 -> y0 | 2 -> x1 | _ -> y1 in
let rm k =
if get p k <= (gete k +. gete (k + 2)) /. 2. then gete k else gete (k + 2)
in

let rM k =
if get p k >= (gete k +. gete (k + 2)) /. 2. then gete k else gete (k + 2)
in

let farthest_distance_axis i = (get p i -. rM i) *. (get p i -. rM i) in
let farthest_distance =
farthest_distance_axis 0 +. farthest_distance_axis 1
in
let max_dist_axis i =
farthest_distance
-. ((get p i -. rM i) *. (get p i -. rM i))
+. ((get p i -. rm i) *. (get p i -. rm i))
in
min (max_dist_axis 0) (max_dist_axis 1)
arr
12 changes: 4 additions & 8 deletions src/rtree.ml
Original file line number Diff line number Diff line change
Expand Up @@ -232,22 +232,21 @@ module Make (E : Envelope) (V : Value with type envelope = E.t) = struct
| Empty -> depth

let depth t = depth' t.tree 0
let comp_dimensions point = E.dimensions == List.length point

let rec nearest_neighbor_helper node elem =
match node with
| Node ns ->
let minminMaxDist =
List.fold_right
(fun (e, _) minminMax ->
if E.minmaxdist elem e < minminMax then E.minmaxdist elem e
if V.minmaxdist elem e < minminMax then V.minmaxdist elem e
else minminMax)
ns max_float
in
let nearest =
List.map
(fun (e, n) ->
let minimum_dist = E.mindist elem e in
let minimum_dist = V.mindist elem e in
if minimum_dist <= minminMaxDist then
nearest_neighbor_helper n elem
else (max_float, None))
Expand All @@ -260,15 +259,12 @@ module Make (E : Envelope) (V : Value with type envelope = E.t) = struct
| Leaf es ->
List.fold_right
(fun (e, v) nearest ->
if E.mindist elem e < fst nearest then (E.mindist elem e, Some v)
if V.mindist elem e < fst nearest then (V.mindist elem e, Some v)
else nearest)
es (max_float, None)
| Empty -> (max_float, None)

let nearest_neighbor rtree elem =
match comp_dimensions elem with
| true -> nearest_neighbor_helper rtree.tree elem
| false -> (max_float, None)
let nearest_neighbor rtree elem = nearest_neighbor_helper rtree.tree elem
end

module Rectangle = Rectangle
19 changes: 3 additions & 16 deletions src/rtree_intf.ml
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,10 @@ module type Value = sig

val envelope : t -> envelope
(** Given a value, calculates the envelope for it. *)
end

module type Point = sig
type t = int array

val t : t Repr.t
val mindist: t -> envelope -> float

(* envelope of the Rtree which allows us to calculate the distances*)
type envelope

val mindist : t -> envelope -> float
val minmaxdist : t -> envelope -> float
val minmaxdist: t -> envelope -> float
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these need to be exposed in the interface?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to test these functions as well. Is that not necessary?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that they're a part of the Value signature then we need them here and can be tested individually. Could we add some documentation strings to them ? minmaxdist is a little opaque I think ?

end

module type Envelope = sig
Expand Down Expand Up @@ -89,9 +81,6 @@ module type Envelope = sig

val contains : t -> t -> bool
(** [contains a b] asks whether [b] is contained by [a]. *)

val minmaxdist : float list -> t -> float
val mindist : float list -> t -> float
end

module type S = sig
Expand Down Expand Up @@ -141,7 +130,7 @@ module type S = sig
val depth : t -> int
(** [depth tree] returns the depth of the tree. *)

val nearest_neighbor : t -> float list -> float * Value.t option
val nearest_neighbor : t -> Value.t -> float * Value.t option
end

module type Maker = functor
Expand All @@ -160,8 +149,6 @@ module type Intf = sig

module Make : Maker

module type Point = Point

module Rectangle : sig
include Envelope

Expand Down
66 changes: 58 additions & 8 deletions test/basic.ml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ module V = struct
type envelope = Rtree.Rectangle.t

let envelope i = List.assoc i !pre_made_envelopes

let mindist _a _b= 0.
let minmaxdist _a _b= 0.
end

module R = Rtree.Make (Rtree.Rectangle) (V)
Expand Down Expand Up @@ -64,6 +67,9 @@ let test_functor _ =
type envelope = Rtree.Rectangle.t

let envelope i = List.assoc i elems

let mindist _a _b= 0.
let minmaxdist _a _b= 0.
end)
in
let r =
Expand Down Expand Up @@ -101,6 +107,41 @@ module Vp = struct
type envelope = Rtree.Rectangle.t

let envelope { p = x, y } = Rtree.Rectangle.v ~x0:x ~y0:y ~x1:x ~y1:y

let mindist point rect =
let x0, x1, y0, y1 = Rtree.Rectangle.coords rect in
let gete ind = match ind with 0 -> x0 | 1 -> y0 | 2 -> x1 | _ -> y1 in
let get point i = match i with 0 -> fst point.p | _ -> snd point.p in
let dist i =
if get point i < gete i then (gete i -. get point i) *. (gete i -. get point i)
else if get point i > gete (i + 2) then
(get point i -. gete (i + 2)) *. (get point i -. gete (i + 2))
else 0.
in
dist 0 +. dist 1

let minmaxdist point rect =
let x0, x1, y0, y1 = Rtree.Rectangle.coords rect in
let gete ind = match ind with 0 -> x0 | 1 -> y0 | 2 -> x1 | _ -> y1 in
let get point i = match i with 0 -> fst point.p | _ -> snd point.p in
let rm k =
if get point k <= (gete k +. gete (k + 2)) /. 2. then gete k else gete (k + 2)
in

let rM k =
if get point k >= (gete k +. gete (k + 2)) /. 2. then gete k else gete (k + 2)
in

let farthest_distance_axis i = (get point i -. rM i) *. (get point i -. rM i) in
let farthest_distance =
farthest_distance_axis 0 +. farthest_distance_axis 1
in
let max_dist_axis i =
farthest_distance
-. ((get point i -. rM i) *. (get point i -. rM i))
+. ((get point i -. rm i) *. (get point i -. rm i))
in
min (max_dist_axis 0) (max_dist_axis 1)
end

module Rp = Rtree.Make (Rtree.Rectangle) (Vp)
Expand All @@ -122,6 +163,9 @@ let test_lines () =
let y0 = Float.min y1 y2 in
let y1 = Float.max y1 y2 in
Rtree.Rectangle.v ~x0 ~y0 ~x1 ~y1

let mindist _a _b= 0.
let minmaxdist _a _b= 0.
end)
in
let l1 = { p1 = (1., 2.); p2 = (2., 3.) } in
Expand Down Expand Up @@ -156,6 +200,9 @@ let omt_loader () =
let y0 = Float.min y1 y2 in
let y1 = Float.max y1 y2 in
Rtree.Rectangle.v ~x0 ~y0 ~x1 ~y1

let mindist _a _b= 0.
let minmaxdist _a _b= 0.
end)
in
let lines =
Expand All @@ -180,20 +227,20 @@ let rectangle () =

let test_min_dist () =
let envelope = Rtree.Rectangle.v ~x0:0. ~x1:1. ~y0:0. ~y1:1. in
let point = [ 0.0; 2.0 ] in
let a = Rtree.Rectangle.mindist point envelope in
assert_equal ~printer:string_of_float ~msg:"Test description" 1. a
let point = {p = (0.0, 2.0)} in
let a = Vp.mindist point envelope in
assert_equal ~printer:string_of_float 1. a
(* above distance is the square of actual distance *)

let test_min_max_dist () =
let envelope = Rtree.Rectangle.v ~x0:0. ~x1:1. ~y0:0. ~y1:1. in
let point = [ 0.; 2.0 ] in
let a = Rtree.Rectangle.minmaxdist point envelope in
assert_equal ~printer:string_of_float 2. a
(* above distance is the square of actual distance *)
let point = {p = (0.0, 2.0)} in
let a = Vp.minmaxdist point envelope in
assert_equal ~printer:string_of_float 2. a
(* above distance is the square of actual distance*)

let test_nearest_neighbor () =
let point = [ 1.0; 2.0 ] in
let point = {p = (1.0, 2.0)} in
let tree_points =
[ { p = (5.0, 5.0) }; { p = (6.0, 6.0) }; { p = (3.0, 4.0) } ]
in
Expand Down Expand Up @@ -222,6 +269,9 @@ let test_depth () =
let y0 = Float.min y1 y2 in
let y1 = Float.max y1 y2 in
Rtree.Rectangle.v ~x0 ~y0 ~x1 ~y1

let mindist _a _b= 0.
let minmaxdist _a _b= 0.
end)
in
let lines =
Expand Down
32 changes: 32 additions & 0 deletions test/distance
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
let mindist p e =
let x0, y0, x1, y1 = (x0 e, y0 e, x1 e, y1 e) in
let gete ind = match ind with 0 -> x0 | 1 -> y0 | 2 -> x1 | _ -> y1 in
let dist i =
if get p i < gete i then (gete i -. get p i) *. (gete i -. get p i)
else if get p i > gete (i + 2) then
(get p i -. gete (i + 2)) *. (get p i -. gete (i + 2))
else 0.
in
dist 0 +. dist 1

let minmaxdist p e =
let x0, y0, x1, y1 = (x0 e, y0 e, x1 e, y1 e) in
let gete ind = match ind with 0 -> x0 | 1 -> y0 | 2 -> x1 | _ -> y1 in
let rm k =
if get p k <= (gete k +. gete (k + 2)) /. 2. then gete k else gete (k + 2)
in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this file committed by mistake? If so can it be removed ?


let rM k =
if get p k >= (gete k +. gete (k + 2)) /. 2. then gete k else gete (k + 2)
in

let farthest_distance_axis i = (get p i -. rM i) *. (get p i -. rM i) in
let farthest_distance =
farthest_distance_axis 0 +. farthest_distance_axis 1
in
let max_dist_axis i =
farthest_distance
-. ((get p i -. rM i) *. (get p i -. rM i))
+. ((get p i -. rm i) *. (get p i -. rm i))
in
min (max_dist_axis 0) (max_dist_axis 1)
6 changes: 6 additions & 0 deletions test/image.ml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ module Line = struct
let y0 = min (Gg.P2.y p1) (Gg.P2.y p2) in
let y1 = max (Gg.P2.y p1) (Gg.P2.y p2) in
Rtree.Rectangle.v ~x0 ~x1 ~y0 ~y1

let mindist _a _b= 0.
let minmaxdist _a _b= 0.
end

module Point = struct
Expand All @@ -38,6 +41,9 @@ module Point = struct
let x0 = Gg.P2.x p1 in
let y0 = Gg.P2.y p1 in
Rtree.Rectangle.v ~x0 ~x1:x0 ~y0 ~y1:y0

let mindist _a _b= 0.
let minmaxdist _a _b= 0.
end

module R = Rtree.Make (Rtree.Rectangle) (Line)
Expand Down
3 changes: 3 additions & 0 deletions test/persist.ml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ module Line = struct
let y0 = Float.min arr.(1) arr.(3) in
let y1 = Float.max arr.(1) arr.(3) in
Rtree.Rectangle.v ~x0 ~y0 ~x1 ~y1

let mindist _a _b= 0.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do run a dune build @fmt --auto to run the formatter as currently the CI will not like the _b= part I think

let minmaxdist _a _b= 0.
end

module R = Rtree.Make (Rtree.Rectangle) (Line)
Expand Down