github.com/vench/word_index@v0.3.1/vector_index_test.go (about) 1 package word_index 2 3 import ( 4 "fmt" 5 "math" 6 "sort" 7 "testing" 8 ) 9 10 func TestVector_DistCos(t *testing.T) { 11 tests := []struct { 12 V1 []float64 13 V2 []float64 14 Dist float64 15 }{ 16 {V1: []float64{}, V2: []float64{}, Dist: 0}, 17 {V1: []float64{1}, V2: []float64{1}, Dist: 1}, 18 {V1: []float64{1, 2, 3}, V2: []float64{1, 2, 3}, Dist: 1}, 19 {V1: []float64{1, 1, 0}, V2: []float64{1, 1, 1}, Dist: 2 / math.Sqrt(2*3)}, 20 {V1: []float64{1, 1, 1}, V2: []float64{1, 1, 1}, Dist: 3 / math.Sqrt(3*3)}, // 3/sqrt(9)=1 21 {V1: []float64{1, 1, 1}, V2: []float64{10, 10, 10}, Dist: 30 / math.Sqrt(300*3)}, // 30/sqrt(900)=1 22 } 23 for i, test := range tests { 24 d := distCos(test.V1, test.V2) 25 if fmt.Sprintf(`%.4f`, test.Dist) != fmt.Sprintf(`%.4f`, d) { 26 t.Fatalf(`N: %d, not equal dist: %.4f != %.4f`, i, test.Dist, d) 27 } 28 } 29 30 } 31 32 func TestVector_DistMonteCarlo(t *testing.T) { 33 // TODO 34 } 35 36 func TestNewIndexVector_SearchNeighborhood(t *testing.T) { 37 iv, err := NewIndexVector() 38 if err != nil { 39 t.Fatalf(`%s`, err.Error()) 40 } 41 // dim 1 42 err = iv.Fit([]*vector{ 43 {Id: 1, V: []float64{1}}, 44 {Id: 2, V: []float64{1}}, 45 {Id: 3, V: []float64{2}}, 46 {Id: 4, V: []float64{101}}, 47 {Id: 5, V: []float64{101}}, 48 }) 49 if err != nil { 50 t.Fatalf(`%s`, err.Error()) 51 } 52 list, err := iv.SearchNeighborhood([]float64{1}, []float64{0}) 53 if err != nil { 54 t.Fatalf(`%s`, err.Error()) 55 } 56 if len(list) != 2 { 57 t.Fatalf(`len not equals 2, %d`, len(list)) 58 } 59 60 list, err = iv.SearchNeighborhood([]float64{1}, []float64{math.Sqrt(2)}) 61 if err != nil { 62 t.Fatalf(`%s`, err.Error()) 63 } 64 if len(list) != 3 { 65 t.Fatalf(`len not equals 3, %d`, len(list)) 66 } 67 68 // dim 2 69 err = iv.Fit([]*vector{ 70 {Id: 1, V: []float64{1, 1}}, 71 {Id: 2, V: []float64{1, 2}}, 72 {Id: 3, V: []float64{2, 2}}, 73 {Id: 4, V: []float64{101, 100}}, 74 {Id: 5, V: []float64{101, 102}}, 75 }) 76 if err != nil { 77 t.Fatalf(`%s`, err.Error()) 78 } 79 list, err = iv.SearchNeighborhood([]float64{1, 1}, []float64{}) 80 if err != nil { 81 t.Fatalf(`%s`, err.Error()) 82 } 83 if len(list) != 1 { 84 t.Fatalf(`len not equals 1, %d`, len(list)) 85 } 86 list, err = iv.SearchNeighborhood([]float64{1, 1}, []float64{2, 2}) 87 if err != nil { 88 t.Fatalf(`%s`, err.Error()) 89 } 90 if len(list) != 3 { 91 t.Fatalf(`len not equals 3, %d`, len(list)) 92 } 93 } 94 95 func TestIndexVector_Search(t *testing.T) { 96 97 iv, err := NewIndexVector() 98 if err != nil { 99 t.Fatalf(`%s`, err.Error()) 100 } 101 // dim 1 102 err = iv.Fit([]*vector{ 103 {Id: 1, V: []float64{1}}, 104 {Id: 2, V: []float64{1}}, 105 {Id: 3, V: []float64{2}}, 106 {Id: 4, V: []float64{101}}, 107 {Id: 5, V: []float64{101}}, 108 }) 109 if err != nil { 110 t.Fatalf(`%s`, err.Error()) 111 } 112 list, err := iv.Search([]float64{1}) 113 if err != nil { 114 t.Fatalf(`%s`, err.Error()) 115 } 116 if len(list) != 2 { 117 t.Fatalf(`len not equals 2, %d`, len(list)) 118 } 119 if list[0].Id != 1 { 120 t.Fatalf(`id not equals 1, %d`, list[0].Id) 121 } 122 if list[1].Id != 2 { 123 t.Fatalf(`id not equals 2, %d`, list[1].Id) 124 } 125 list, err = iv.Search([]float64{2}) 126 if err != nil { 127 t.Fatalf(`%s`, err.Error()) 128 } 129 if len(list) != 1 { 130 t.Fatalf(`len not equals 1, %d`, len(list)) 131 } 132 if list[0].Id != 3 { 133 t.Fatalf(`id not equals 3, %d`, list[0].Id) 134 } 135 list, err = iv.Search([]float64{3}) 136 if err != nil { 137 t.Fatalf(`%s`, err.Error()) 138 } 139 if len(list) != 0 { 140 t.Fatalf(`query is not empty`) 141 } 142 } 143 144 func TestVector_DistEuclidean(t *testing.T) { 145 tests := []struct { 146 V1 []float64 147 V2 []float64 148 Dist float64 149 }{ 150 {V1: []float64{}, V2: []float64{}, Dist: 0}, 151 {V1: []float64{1}, V2: []float64{1}, Dist: 0}, 152 {V1: []float64{1, 2, 3}, V2: []float64{1, 2, 3}, Dist: 0}, 153 {V1: []float64{1}, V2: []float64{2}, Dist: 1}, 154 {V1: []float64{1, 1}, V2: []float64{2, 2}, Dist: math.Sqrt(2)}, 155 {V1: []float64{1, 1}, V2: []float64{2, 8}, Dist: math.Sqrt(1 + 49)}, 156 {V1: []float64{1, 1, 0}, V2: []float64{1, 1, 1}, Dist: 1}, 157 {V1: []float64{1, 1, 1}, V2: []float64{1, 1, 1}, Dist: 0}, 158 {V1: []float64{1, 1, 1}, V2: []float64{10, 10, 10}, Dist: 15.5885}, 159 } 160 for i, test := range tests { 161 d := distEuclidean(test.V1, test.V2) 162 //d2 := distCos(test.V1, test.V2) 163 if fmt.Sprintf(`%.4f`, test.Dist) != fmt.Sprintf(`%.4f`, d) { 164 t.Fatalf(`N: %d, not equal dist: %.4f != %.4f`, i, test.Dist, d) 165 } 166 //fmt.Println(i, d,d2) 167 } 168 169 } 170 171 func TestZOrderCurveFloat64_locale(t *testing.T) { 172 type pointZ struct { 173 n int 174 point []float64 175 z uint64 176 } 177 // 64 dim 178 points := []pointZ{ 179 {n: 2, point: []float64{0.11, 0.11, 0.12, 0.13, 0.11, 0.11, 0.12, 0.13, 0.11, 0.11, 0.12, 0.13, 0.11, 0.11, 0.12, 0.13, 0.11, 0.11, 0.12, 0.13, 0.11, 0.11, 0.12, 0.13, 0.11, 0.11, 0.12, 0.13, 0.11, 0.11, 0.12, 0.13, 0.11, 0.11, 0.12, 0.13, 0.11, 0.11, 0.12, 0.13, 0.11, 0.11, 0.12, 0.13, 0.11, 0.11, 0.12, 0.13, 0.11, 0.11, 0.12, 0.13, 0.11, 0.11, 0.12, 0.13, 0.11, 0.11, 0.12, 0.13, 0.11, 0.11, 0.12, 0.13}}, 180 {n: 4, point: []float64{0.000101, 0.000101, 0.0003, 0.000101, 0.000101, 0.000101, 0.0003, 0.000101, 0.000101, 0.000101, 0.0003, 0.000101, 0.000101, 0.000101, 0.0003, 0.000101, 0.000101, 0.000101, 0.0003, 0.000101, 0.000101, 0.000101, 0.0003, 0.000101, 0.000101, 0.000101, 0.0003, 0.000101, 0.000101, 0.000101, 0.0003, 0.000101, 0.000101, 0.000101, 0.0003, 0.000101, 0.000101, 0.000101, 0.0003, 0.000101, 0.000101, 0.000101, 0.0003, 0.000101, 0.000101, 0.000101, 0.0003, 0.000101, 0.000101, 0.000101, 0.0003, 0.000101, 0.000101, 0.000101, 0.0003, 0.000101, 0.000101, 0.000101, 0.0003, 0.000101, 0.000101, 0.000101, 0.0003, 0.000101}}, 181 {n: 1, point: []float64{0.10, 10, 0.10, 0.12, 0.10, 10, 0.10, 0.12, 0.10, 10, 0.10, 0.12, 0.10, 10, 0.10, 0.12, 0.10, 10, 0.10, 0.12, 0.10, 10, 0.10, 0.12, 0.10, 10, 0.10, 0.12, 0.10, 10, 0.10, 0.12, 0.10, 10, 0.10, 0.12, 0.10, 10, 0.10, 0.12, 0.10, 10, 0.10, 0.12, 0.10, 10, 0.10, 0.12, 0.10, 10, 0.10, 0.12, 0.10, 10, 0.10, 0.12, 0.10, 10, 0.10, 0.12, 0.10, 10, 0.10, 0.12}}, 182 {n: 3, point: []float64{0.000100, 0.000100, 0.0003, 0.000100, 0.000100, 0.000100, 0.0003, 0.000100, 0.000100, 0.000100, 0.0003, 0.000100, 0.000100, 0.000100, 0.0003, 0.000100, 0.000100, 0.000100, 0.0003, 0.000100, 0.000100, 0.000100, 0.0003, 0.000100, 0.000100, 0.000100, 0.0003, 0.000100, 0.000100, 0.000100, 0.0003, 0.000100, 0.000100, 0.000100, 0.0003, 0.000100, 0.000100, 0.000100, 0.0003, 0.000100, 0.000100, 0.000100, 0.0003, 0.000100, 0.000100, 0.000100, 0.0003, 0.000100, 0.000100, 0.000100, 0.0003, 0.000100, 0.000100, 0.000100, 0.0003, 0.000100, 0.000100, 0.000100, 0.0003, 0.000100, 0.000100, 0.000100, 0.0003, 0.000100}}, 183 } 184 185 for i, point := range points { 186 points[i].z = ZOrderCurveFloat64(point.point) 187 } 188 189 sort.Slice(points, func(i, j int) bool { 190 return points[i].z < points[j].z 191 }) 192 193 for i := 0; i < len(points); i++ { 194 if points[i].n != i+1 { 195 t.Fatalf(`N_%d != i_%d`, points[i].n, i+1) 196 } 197 } 198 199 } 200 201 func TestZOrderCurveFloat64(t *testing.T) { 202 203 type itemZ struct { 204 index int 205 z uint64 206 } 207 items1 := make([]itemZ, 0) 208 items2 := make([]itemZ, 0) 209 210 for x := 0; x < 8; x++ { 211 for y := 0; y < 8; y++ { 212 v := []uint64{ 213 uint64(x), 214 uint64(y), 215 } 216 z1 := ZOrderCurve(v) 217 items1 = append(items1, itemZ{ 218 index: x*8 + y, 219 z: z1, 220 }) 221 222 vf := []float64{ 223 float64(x), 224 float64(y), 225 } 226 z2 := ZOrderCurveFloat64(vf) 227 items2 = append(items2, itemZ{ 228 index: x*8 + y, 229 z: z2, 230 }) 231 //fmt.Println(z1, ` `, z2, ` i `, x*8+y, x, y) 232 } 233 } 234 235 sort.Slice(items1, func(i, j int) bool { 236 return items1[i].z < items1[j].z 237 }) 238 sort.Slice(items2, func(i, j int) bool { 239 return items2[i].z < items2[j].z 240 }) 241 242 i := 0 243 if items1[i].index != items2[i].index { 244 t.Errorf(`index1(%d) != index2(%d), n: %d`, items1[i].index, items2[i].index, 0) 245 } 246 i = len(items1) - 1 247 if items1[i].index != items2[i].index { 248 t.Errorf(`index1(%d) != index2(%d), n: %d`, items1[i].index, items2[i].index, 0) 249 } 250 }