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  }