Poindexter/examples_test.go

241 lines
7.1 KiB
Go
Raw Permalink Normal View History

package poindexter_test
import (
"fmt"
poindexter "github.com/Snider/Poindexter"
)
func ExampleNewKDTree() {
pts := []poindexter.KDPoint[string]{
{ID: "A", Coords: []float64{0, 0}, Value: "alpha"},
{ID: "B", Coords: []float64{1, 0}, Value: "bravo"},
}
tr, _ := poindexter.NewKDTree(pts)
p, _, _ := tr.Nearest([]float64{0.2, 0})
fmt.Println(p.ID)
// Output: A
}
func ExampleBuild2D() {
type rec struct{ ping, hops float64 }
items := []rec{{ping: 20, hops: 3}, {ping: 30, hops: 2}, {ping: 15, hops: 4}}
weights := [2]float64{1.0, 1.0}
invert := [2]bool{false, false}
pts, _ := poindexter.Build2D(items,
func(r rec) string { return "" },
func(r rec) float64 { return r.ping },
func(r rec) float64 { return r.hops },
weights, invert,
)
tr, _ := poindexter.NewKDTree(pts, poindexter.WithMetric(poindexter.ManhattanDistance{}))
_, _, _ = tr.Nearest([]float64{0, 0})
fmt.Printf("dim=%d len=%d", tr.Dim(), tr.Len())
// Output: dim=2 len=3
}
func ExampleKDTree_Nearest() {
pts := []poindexter.KDPoint[int]{
{ID: "x", Coords: []float64{0, 0}, Value: 1},
{ID: "y", Coords: []float64{2, 0}, Value: 2},
}
tr, _ := poindexter.NewKDTree(pts, poindexter.WithMetric(poindexter.EuclideanDistance{}))
p, d, ok := tr.Nearest([]float64{1.4, 0})
fmt.Printf("ok=%v id=%s d=%.1f", ok, p.ID, d)
// Output: ok=true id=y d=0.6
}
func ExampleKDTree_KNearest() {
pts := []poindexter.KDPoint[int]{
{ID: "a", Coords: []float64{0}, Value: 0},
{ID: "b", Coords: []float64{1}, Value: 0},
{ID: "c", Coords: []float64{2}, Value: 0},
}
tr, _ := poindexter.NewKDTree(pts)
ns, ds := tr.KNearest([]float64{0.6}, 2)
fmt.Printf("%s %.1f | %s %.1f", ns[0].ID, ds[0], ns[1].ID, ds[1])
// Output: b 0.4 | a 0.6
}
func ExampleKDTree_Radius() {
pts := []poindexter.KDPoint[int]{
{ID: "a", Coords: []float64{0}, Value: 0},
{ID: "b", Coords: []float64{1}, Value: 0},
{ID: "c", Coords: []float64{2}, Value: 0},
}
tr, _ := poindexter.NewKDTree(pts)
within, _ := tr.Radius([]float64{0}, 1.0)
fmt.Printf("%d %s %s", len(within), within[0].ID, within[1].ID)
// Output: 2 a b
}
func ExampleKDTree_DeleteByID() {
pts := []poindexter.KDPoint[string]{
{ID: "A", Coords: []float64{0}, Value: "a"},
}
tr, _ := poindexter.NewKDTree(pts)
tr.Insert(poindexter.KDPoint[string]{ID: "Z", Coords: []float64{0.1}, Value: "z"})
p, _, _ := tr.Nearest([]float64{0.09})
fmt.Println(p.ID)
tr.DeleteByID("Z")
p2, _, _ := tr.Nearest([]float64{0.09})
fmt.Println(p2.ID)
// Output:
// Z
// A
}
func ExampleBuild3D() {
type rec struct{ x, y, z float64 }
items := []rec{{0, 0, 0}, {1, 1, 1}}
weights := [3]float64{1, 1, 1}
invert := [3]bool{false, false, false}
pts, _ := poindexter.Build3D(items,
func(r rec) string { return "" },
func(r rec) float64 { return r.x },
func(r rec) float64 { return r.y },
func(r rec) float64 { return r.z },
weights, invert,
)
tr, _ := poindexter.NewKDTree(pts)
fmt.Println(tr.Dim())
// Output: 3
}
func ExampleBuild4D() {
type rec struct{ a, b, c, d float64 }
items := []rec{{0, 0, 0, 0}, {1, 1, 1, 1}}
weights := [4]float64{1, 1, 1, 1}
invert := [4]bool{false, false, false, false}
pts, _ := poindexter.Build4D(items,
func(r rec) string { return "" },
func(r rec) float64 { return r.a },
func(r rec) float64 { return r.b },
func(r rec) float64 { return r.c },
func(r rec) float64 { return r.d },
weights, invert,
)
tr, _ := poindexter.NewKDTree(pts)
fmt.Println(tr.Dim())
// Output: 4
}
func ExampleBuild2DWithStats() {
type rec struct{ ping, hops float64 }
items := []rec{{20, 3}, {30, 2}, {15, 4}}
weights := [2]float64{1.0, 1.0}
invert := [2]bool{false, false}
stats := poindexter.ComputeNormStats2D(items,
func(r rec) float64 { return r.ping },
func(r rec) float64 { return r.hops },
)
pts, _ := poindexter.Build2DWithStats(items,
func(r rec) string { return "" },
func(r rec) float64 { return r.ping },
func(r rec) float64 { return r.hops },
weights, invert, stats,
)
tr, _ := poindexter.NewKDTree(pts)
fmt.Printf("dim=%d len=%d", tr.Dim(), tr.Len())
// Output: dim=2 len=3
}
func ExampleBuildND() {
type rec struct{ a, b, c float64 }
items := []rec{{0, 0, 0}, {1, 2, 3}, {0.5, 1, 1.5}}
features := []func(rec) float64{
func(r rec) float64 { return r.a },
func(r rec) float64 { return r.b },
func(r rec) float64 { return r.c },
}
weights := []float64{1, 0.5, 2}
invert := []bool{false, false, false}
pts, _ := poindexter.BuildND(items, func(r rec) string { return "" }, features, weights, invert)
tr, _ := poindexter.NewKDTree(pts)
fmt.Printf("dim=%d len=%d", tr.Dim(), tr.Len())
// Output: dim=3 len=3
}
func ExampleBuildNDWithStats() {
type rec struct{ a, b float64 }
items := []rec{{0, 0}, {1, 2}, {0.5, 1}}
features := []func(rec) float64{
func(r rec) float64 { return r.a },
func(r rec) float64 { return r.b },
}
stats, _ := poindexter.ComputeNormStatsND(items, features)
weights := []float64{1, 0.5}
invert := []bool{false, false}
pts, _ := poindexter.BuildNDWithStats(items, func(r rec) string { return "" }, features, weights, invert, stats)
tr, _ := poindexter.NewKDTree(pts, poindexter.WithMetric(poindexter.CosineDistance{}))
fmt.Printf("dim=%d len=%d", tr.Dim(), tr.Len())
// Output: dim=2 len=3
}
func ExampleCosineDistance() {
a := []float64{1, 0}
b := []float64{0, 1}
d := poindexter.CosineDistance{}.Distance(a, b)
fmt.Printf("%.0f", d)
// Output: 1
}
func ExampleBuild4DWithStats() {
type rec struct{ a, b, c, d float64 }
items := []rec{{0, 0, 0, 0}, {1, 1, 1, 1}}
weights := [4]float64{1, 1, 1, 1}
invert := [4]bool{false, false, false, false}
stats := poindexter.ComputeNormStats4D(items,
func(r rec) float64 { return r.a },
func(r rec) float64 { return r.b },
func(r rec) float64 { return r.c },
func(r rec) float64 { return r.d },
)
pts, _ := poindexter.Build4DWithStats(items,
func(r rec) string { return "" },
func(r rec) float64 { return r.a },
func(r rec) float64 { return r.b },
func(r rec) float64 { return r.c },
func(r rec) float64 { return r.d },
weights, invert, stats,
)
tr, _ := poindexter.NewKDTree(pts)
fmt.Println(tr.Dim())
// Output: 4
}
func ExampleNewKDTreeFromDim() {
// Construct an empty 2D tree, insert a point, then query.
tr, _ := poindexter.NewKDTreeFromDim[string](2)
tr.Insert(poindexter.KDPoint[string]{ID: "A", Coords: []float64{0.1, 0.2}, Value: "alpha"})
p, _, ok := tr.Nearest([]float64{0, 0})
fmt.Printf("ok=%v id=%s dim=%d len=%d", ok, p.ID, tr.Dim(), tr.Len())
// Output: ok=true id=A dim=2 len=1
}
func Example_tiesBehavior() {
// Two points equidistant from the query; tie ordering is arbitrary,
// but distances are equal.
pts := []poindexter.KDPoint[int]{
{ID: "L", Coords: []float64{-1}},
{ID: "R", Coords: []float64{+1}},
}
tr, _ := poindexter.NewKDTree(pts)
ns, ds := tr.KNearest([]float64{0}, 2)
_ = ns // neighbor order is unspecified
fmt.Printf("equal=%.1f==%.1f? %v", ds[0], ds[1], ds[0] == ds[1])
// Output: equal=1.0==1.0? true
}
func ExampleKDTree_Radius_none() {
// Radius query that yields no matches.
pts := []poindexter.KDPoint[int]{
{ID: "a", Coords: []float64{10}},
{ID: "b", Coords: []float64{20}},
}
tr, _ := poindexter.NewKDTree(pts)
within, _ := tr.Radius([]float64{0}, 5)
fmt.Println(len(within))
// Output: 0
}