github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/vector/hnsw/distancer/cosine_dist_test.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package distancer 13 14 import ( 15 "testing" 16 17 "github.com/stretchr/testify/assert" 18 "github.com/stretchr/testify/require" 19 ) 20 21 func TestCosineDistancer(t *testing.T) { 22 t.Run("identical vectors", func(t *testing.T) { 23 vec1 := Normalize([]float32{0.1, 0.3, 0.7}) 24 vec2 := Normalize([]float32{0.1, 0.3, 0.7}) 25 expectedDistance := float32(0.0) 26 27 dist, ok, err := NewCosineDistanceProvider().New(vec1).Distance(vec2) 28 require.Nil(t, err) 29 require.True(t, ok) 30 control, ok, err := NewCosineDistanceProvider().SingleDist(vec1, vec2) 31 require.True(t, ok) 32 require.Nil(t, err) 33 assert.Equal(t, control, dist) 34 assert.Equal(t, expectedDistance, dist) 35 }) 36 37 t.Run("different vectors, but identical angle", func(t *testing.T) { 38 vec1 := Normalize([]float32{0.1, 0.3, 0.7}) 39 vec2 := Normalize([]float32{0.2, 0.6, 1.4}) 40 expectedDistance := float32(0.0) 41 42 dist, ok, err := NewCosineDistanceProvider().New(vec1).Distance(vec2) 43 require.Nil(t, err) 44 require.True(t, ok) 45 control, ok, err := NewCosineDistanceProvider().SingleDist(vec1, vec2) 46 require.True(t, ok) 47 require.Nil(t, err) 48 assert.Equal(t, control, dist) 49 assert.Equal(t, expectedDistance, dist) 50 }) 51 52 t.Run("different vectors", func(t *testing.T) { 53 vec1 := Normalize([]float32{0.1, 0.3, 0.7}) 54 vec2 := Normalize([]float32{0.2, 0.2, 0.2}) 55 expectedDistance := float32(0.173) 56 57 dist, ok, err := NewCosineDistanceProvider().New(vec1).Distance(vec2) 58 require.Nil(t, err) 59 require.True(t, ok) 60 control, ok, err := NewCosineDistanceProvider().SingleDist(vec1, vec2) 61 require.True(t, ok) 62 require.Nil(t, err) 63 assert.Equal(t, control, dist) 64 assert.InDelta(t, expectedDistance, dist, 0.01) 65 }) 66 67 t.Run("opposite vectors", func(t *testing.T) { 68 // This is unique to cosine/angular distance. 69 vec1 := Normalize([]float32{0.1, 0.3, 0.7}) 70 vec2 := Normalize([]float32{-0.1, -0.3, -0.7}) 71 expectedDistance := float32(2) 72 73 dist, ok, err := NewCosineDistanceProvider().New(vec1).Distance(vec2) 74 require.Nil(t, err) 75 require.True(t, ok) 76 control, ok, err := NewCosineDistanceProvider().SingleDist(vec1, vec2) 77 require.True(t, ok) 78 require.Nil(t, err) 79 assert.Equal(t, control, dist) 80 assert.InDelta(t, expectedDistance, dist, 0.01) 81 }) 82 } 83 84 func TestCosineDistancerStepbyStep(t *testing.T) { 85 t.Run("step by step equals SingleDist", func(t *testing.T) { 86 vec1 := Normalize([]float32{3, 4, 5}) 87 vec2 := Normalize([]float32{-3, -4, -5}) 88 89 expectedDistance, ok, err := NewCosineDistanceProvider().New(vec1).Distance(vec2) 90 require.Nil(t, err) 91 require.True(t, ok) 92 93 distanceProvider := NewCosineDistanceProvider() 94 sum := float32(0.0) 95 for i := range vec1 { 96 sum += distanceProvider.Step([]float32{vec1[i]}, []float32{vec2[i]}) 97 } 98 control := distanceProvider.Wrap(sum) 99 100 assert.Equal(t, control, expectedDistance) 101 }) 102 }