1
+ import unittest
2
+
3
+ import numpy as np
4
+
5
+ import hnswlib
6
+
7
+
8
+ class RandomSelfTestCase (unittest .TestCase ):
9
+ def testRandomSelf (self ):
10
+ dim = 16
11
+ num_elements = 1_000
12
+ max_num_elements = 2 * num_elements
13
+
14
+ # Generating sample data
15
+ # batch 1
16
+ first_id = 0
17
+ last_id = num_elements
18
+ labels1 = np .arange (first_id , last_id )
19
+ data1 = np .float32 (np .random .random ((num_elements , dim )))
20
+ # batch 2
21
+ first_id += num_elements
22
+ last_id += num_elements
23
+ labels2 = np .arange (first_id , last_id )
24
+ data2 = np .float32 (np .random .random ((num_elements , dim )))
25
+ # batch 3
26
+ first_id += num_elements
27
+ last_id += num_elements
28
+ labels3 = np .arange (first_id , last_id )
29
+ data3 = np .float32 (np .random .random ((num_elements , dim )))
30
+
31
+ # Declaring index
32
+ for _ in range (100 ):
33
+ hnsw_index = hnswlib .Index (space = 'l2' , dim = dim )
34
+ hnsw_index .init_index (max_elements = max_num_elements , ef_construction = 200 , M = 16 , replace_deleted = True )
35
+
36
+ hnsw_index .set_ef (100 )
37
+ hnsw_index .set_num_threads (50 )
38
+
39
+ # Add batch 1 and 2
40
+ hnsw_index .add_items (data1 , labels1 )
41
+ hnsw_index .add_items (data2 , labels2 ) # maximum number of elements is reached
42
+
43
+ # Delete nearest neighbors of batch 2
44
+ labels2_deleted , _ = hnsw_index .knn_query (data2 , k = 1 )
45
+ for l in labels2_deleted :
46
+ hnsw_index .mark_deleted (l [0 ])
47
+ labels1_found , _ = hnsw_index .knn_query (data1 , k = 1 )
48
+ items = hnsw_index .get_items (labels1_found )
49
+ diff_with_gt_labels = np .mean (np .abs (data1 - items ))
50
+ self .assertAlmostEqual (diff_with_gt_labels , 0 , delta = 1e-3 )
51
+
52
+ labels2_after , _ = hnsw_index .knn_query (data2 , k = 1 )
53
+ labels2_after_flat = labels2_after .flatten ()
54
+ labels2_deleted_flat = labels2_deleted .flatten ()
55
+ common = np .intersect1d (labels2_after_flat , labels2_deleted_flat )
56
+ self .assertTrue (common .size == 0 )
57
+
58
+ # Replace deleted elements
59
+ # Maximum number of elements is reached therefore we cannot add new items
60
+ # but we can replace the deleted ones
61
+ labels_replaced = hnsw_index .add_items_to_vacant_place (data3 , labels3 )
62
+
0 commit comments