package vectorgraph import ( "fmt" "math" "reflect" "testing" ) func TestBuildLinksNearbyVectorsWithoutModelDependency(t *testing.T) { entries := []Entry{ {ID: "a", Vector: []float32{1, 0, 0, 0}}, {ID: "b", Vector: []float32{.99, .02, 0, 0}}, {ID: "c", Vector: []float32{.98, -.01, 0, 0}}, {ID: "x", Vector: []float32{0, 1, 0, 0}}, {ID: "y", Vector: []float32{0, .99, .02, 0}}, } cfg := Config{Neighbors: 2, CandidateLimit: 32, HashBits: 16, HashTables: 2, BandBits: 8, MinSimilarity: .8, MinAffinity: .2} result := Build(entries, cfg) if len(result.Links) == 0 { t.Fatal("expected semantic links") } seenAB := false for _, link := range result.Links { if (link.Source == "a" && link.Target == "b") || (link.Source == "b" && link.Target == "a") { seenAB = true } if (link.Source == "a" && link.Target == "x") || (link.Source == "x" && link.Target == "a") { t.Fatalf("orthogonal vectors must not link: %+v", link) } } if !seenAB { t.Fatalf("expected a/b to be linked: %+v", result.Links) } } func TestBuildIsDeterministicAndProducesFiniteLayout(t *testing.T) { entries := []Entry{ {ID: "a", Vector: []float32{1, .2, .1, 0}}, {ID: "b", Vector: []float32{.95, .22, .08, 0}}, {ID: "c", Vector: []float32{0, 1, .1, .2}}, {ID: "d", Vector: []float32{0, .96, .12, .18}}, } cfg := Config{Neighbors: 2, CandidateLimit: 32, HashBits: 16, HashTables: 2, BandBits: 8, MinSimilarity: .7, MinAffinity: .2, Layout: true} a := Build(entries, cfg) b := Build(entries, cfg) if !reflect.DeepEqual(a.Links, b.Links) || !reflect.DeepEqual(a.Positions, b.Positions) { t.Fatal("vector graph must be deterministic") } if len(a.Positions) != len(entries) { t.Fatalf("expected %d positions, got %d", len(entries), len(a.Positions)) } for _, p := range a.Positions { if math.IsNaN(p.X) || math.IsNaN(p.Y) || math.IsNaN(p.Z) || math.IsInf(p.X, 0) || math.IsInf(p.Y, 0) || math.IsInf(p.Z, 0) { t.Fatalf("invalid position: %+v", p) } } } func TestBuildFocusedOnlyAnchorsRequestedOrphansAgainstFullCorpus(t *testing.T) { entries := []Entry{ {ID: "connected-a", Vector: []float32{1, 0, 0, 0}}, {ID: "connected-b", Vector: []float32{.99, .01, 0, 0}}, {ID: "orphan", Vector: []float32{.985, .015, 0, 0}}, {ID: "far", Vector: []float32{0, 1, 0, 0}}, } cfg := Config{Neighbors: 2, CandidateLimit: 32, HashBits: 16, HashTables: 2, BandBits: 8, MinSimilarity: .8, MinAffinity: .2} result := BuildFocused(entries, map[string]bool{"orphan": true}, cfg) if result.Stats.Focused != 1 { t.Fatalf("expected one focused entry, got %+v", result.Stats) } if len(result.Links) == 0 { t.Fatal("expected focused orphan to link into full corpus") } for _, link := range result.Links { if link.Source != "orphan" && link.Target != "orphan" { t.Fatalf("second pass must not invent links between non-focused nodes: %+v", link) } if link.Source == "far" || link.Target == "far" { t.Fatalf("orthogonal candidate must remain unlinked: %+v", link) } } } func TestBuildFocusedIsDeterministic(t *testing.T) { entries := []Entry{ {ID: "a", Vector: []float32{1, .1, 0, 0}}, {ID: "b", Vector: []float32{.99, .11, 0, 0}}, {ID: "c", Vector: []float32{.97, .13, 0, 0}}, } cfg := Config{Neighbors: 2, CandidateLimit: 32, HashBits: 16, HashTables: 2, BandBits: 8, MinSimilarity: .7, MinAffinity: .1} focus := map[string]bool{"c": true} a := BuildFocused(entries, focus, cfg) b := BuildFocused(entries, focus, cfg) if !reflect.DeepEqual(a, b) { t.Fatalf("focused vector graph must be deterministic: a=%+v b=%+v", a, b) } } func TestSpreadDenseLayoutSeparatesDenseCellDeterministically(t *testing.T) { entries := make([]indexedEntry, 24) positions := make([][3]float64, 24) for i := range entries { entries[i] = indexedEntry{Entry: Entry{ID: fmt.Sprintf("node-%02d", i)}} positions[i] = [3]float64{.1, .1, .1} } a := spreadDenseLayout(entries, append([][3]float64(nil), positions...)) b := spreadDenseLayout(entries, append([][3]float64(nil), positions...)) if !reflect.DeepEqual(a, b) { t.Fatal("dense layout relaxation must be deterministic") } unique := map[[3]float64]bool{} for _, p := range a { unique[p] = true } if len(unique) < 8 { t.Fatalf("dense cell was not meaningfully spread, unique positions=%d", len(unique)) } } func TestParallelWorkersMatchSingleWorker(t *testing.T) { entries := make([]Entry, 96) for i := range entries { entries[i] = Entry{ID: fmt.Sprintf("n-%03d", i), Vector: []float32{ float32((i%11)+1) / 11, float32((i%7)+1) / 7, float32((i%5)+1) / 5, float32((i%3)+1) / 3, }} } base := Config{Workers: 1, Neighbors: 4, CandidateLimit: 48, HashBits: 16, HashTables: 2, BandBits: 8, MinSimilarity: .65, MinAffinity: .1, Layout: true} parallel := base parallel.Workers = 8 one := Build(entries, base) many := Build(entries, parallel) if !reflect.DeepEqual(one, many) { t.Fatalf("parallel primary build differs from single-worker build") } focus := map[string]bool{"n-003": true, "n-017": true, "n-044": true, "n-081": true} oneFocused := BuildFocused(entries, focus, base) manyFocused := BuildFocused(entries, focus, parallel) if !reflect.DeepEqual(oneFocused, manyFocused) { t.Fatalf("parallel focused build differs from single-worker build") } }