diff --git a/diskann-providers/src/index/diskann_async.rs b/diskann-providers/src/index/diskann_async.rs index 560fb13fa..56d3d4436 100644 --- a/diskann-providers/src/index/diskann_async.rs +++ b/diskann-providers/src/index/diskann_async.rs @@ -174,7 +174,7 @@ pub(crate) mod tests { DefaultSearchStrategy, InplaceDeleteStrategy, InsertStrategy, MultiInsertStrategy, SearchStrategy, }, - index::{PartitionedNeighbors, QueryLabelProvider, QueryVisitDecision}, + index::{QueryLabelProvider, QueryVisitDecision}, search::{Knn, Range}, search_output_buffer, }, @@ -1531,353 +1531,6 @@ pub(crate) mod tests { // Deletion // ////////////// - async fn setup_inplace_delete_test() -> Arc { - let dim = 1; - let (config, parameters) = simplified_builder( - 10, // l_search - 3, // max_degree - Metric::L2, // metric - dim, // dim - 5, // max_points - no_modify, - ) - .unwrap(); - - let pqtable = model::pq::FixedChunkPQTable::new( - dim, - Box::new([0.0]), - Box::new([0.0]), - Box::new([0, 1]), - ) - .unwrap(); - - let index = - new_quant_index::(config, parameters, pqtable, TableBasedDeletes).unwrap(); - let mut neighbor_accessor = index.provider().neighbors(); - // build graph - let adjacency_lists = [ - AdjacencyList::from_iter_untrusted([2, 3]), - AdjacencyList::from_iter_untrusted([2, 3]), - AdjacencyList::from_iter_untrusted([1, 4]), - AdjacencyList::from_iter_untrusted([2, 4]), - AdjacencyList::from_iter_untrusted([1, 3]), - ]; - populate_graph(&mut neighbor_accessor, &adjacency_lists).await; - - index - } - - #[tokio::test] - async fn test_return_refs_to_deleted_vertex() { - let index = setup_inplace_delete_test().await; - - // Expected outcome: - // * Index 0 is unchanged because it doesn't contain an edge to 1 - // * Index 2's adjacency list should be changed to remove index 1. - // * Index 4's adjacency list should be changed to remove index 1. - // - // Indices 2 and 4 should be returned. - - let candidates: Vec = vec![0, 2, 4]; - - let ret_list = index - .return_refs_to_deleted_vertex(&mut index.provider().neighbors(), 1, &candidates) - .await - .unwrap(); - - // Check that the return list contains only candidates 2 and 4. - assert_eq!(&ret_list, &[2, 4]); - } - - #[tokio::test] - async fn test_is_any_neighbor_deleted() { - let dim = 1; - let (config, parameters) = simplified_builder( - 10, // l_search - 3, // max_degree - Metric::L2, // metric - dim, // dim - 5, // max_points - no_modify, - ) - .unwrap(); - - let pqtable = model::pq::FixedChunkPQTable::new( - dim, - Box::new([0.0]), - Box::new([0.0]), - Box::new([0, 1]), - ) - .unwrap(); - - let index = - new_quant_index::(config, parameters, pqtable, TableBasedDeletes).unwrap(); - let mut neighbor_accessor = index.provider().neighbors(); - //build graph - let adjacency_lists = [ - AdjacencyList::from_iter_untrusted([2, 3, 1]), - AdjacencyList::from_iter_untrusted([2, 3, 4]), - AdjacencyList::from_iter_untrusted([0, 1, 4]), - AdjacencyList::from_iter_untrusted([2, 4, 0]), - AdjacencyList::from_iter_untrusted([0, 3, 2]), - ]; - - let ctx = DefaultContext; - populate_graph(&mut neighbor_accessor, &adjacency_lists).await; - - // delete id number 3 - // FIXME: Provider an interface at the index level!. - index - .data_provider - .delete(&ctx, &3_u32) - .await - .expect("Error in delete"); - - // expected outcome: adjacency lists 0, 1, 4 should return true - // adjacency lists 2, 3 should return false - - let neighbor_accessor = &mut index.provider().neighbors(); - let msg = "Error in is_any_neighbor_deleted"; - assert!( - (index.is_any_neighbor_deleted(&ctx, neighbor_accessor, 0)) - .await - .expect(msg) - ); - assert!( - (index.is_any_neighbor_deleted(&ctx, neighbor_accessor, 1)) - .await - .expect(msg) - ); - assert!( - !(index.is_any_neighbor_deleted(&ctx, neighbor_accessor, 2)) - .await - .expect(msg) - ); - assert!( - !(index.is_any_neighbor_deleted(&ctx, neighbor_accessor, 3)) - .await - .expect(msg) - ); - assert!( - (index.is_any_neighbor_deleted(&ctx, neighbor_accessor, 4)) - .await - .expect(msg) - ); - } - - #[tokio::test] - async fn test_drop_deleted_neighbors() { - let dim = 1; - let (config, parameters) = simplified_builder( - 10, // l_search - 3, // max_degree - Metric::L2, // metric - dim, // dim - 5, // max_points - no_modify, - ) - .unwrap(); - - let pqtable = model::pq::FixedChunkPQTable::new( - dim, - Box::new([0.0]), - Box::new([0.0]), - Box::new([0, 1]), - ) - .unwrap(); - - let index = - new_quant_index::(config, parameters, pqtable, TableBasedDeletes).unwrap(); - - //build graph - let adjacency_lists = [ - AdjacencyList::from_iter_untrusted([2, 3, 1]), - AdjacencyList::from_iter_untrusted([2, 3, 4]), - AdjacencyList::from_iter_untrusted([0, 1, 4]), - AdjacencyList::from_iter_untrusted([2, 4, 0]), - AdjacencyList::from_iter_untrusted([0, 3, 2]), - ]; - - let neighbor_accessor = &mut index.provider().neighbors(); - let ctx = DefaultContext; - populate_graph(neighbor_accessor, &adjacency_lists).await; - - // delete id number 3 - // FIXME: Provider an interface at the index level!. - index - .data_provider - .delete(&ctx, &3_u32) - .await - .expect("Error in delete"); - - let drop_msg = "Error in drop_deleted_neighbors"; - let adj_msg = "Error in get_neighbors"; - - // call drop_deleted_neighbors on vertex 0 with check_delete = false - // expected outcome: deleted neighbor is dropped - - index - .drop_deleted_neighbors(&ctx, neighbor_accessor, 0, false) - .await - .expect(drop_msg); - - let mut list0 = AdjacencyList::new(); - neighbor_accessor - .get_neighbors(0, &mut list0) - .await - .expect(adj_msg); - list0.sort(); - assert_eq!(&*list0, &[1, 2]); - - // call drop_deleted_neighbors on vertex 1 with check_delete = true - // expected outcome: deleted neighbor is not dropped - - index - .drop_deleted_neighbors(&ctx, neighbor_accessor, 1, true) - .await - .expect(drop_msg); - - let mut list1_before_drop = AdjacencyList::new(); - neighbor_accessor - .get_neighbors(1, &mut list1_before_drop) - .await - .expect(adj_msg); - list1_before_drop.sort(); - assert_eq!(&*list1_before_drop, &[2, 3, 4]); - - // drop vertex 3's adjacency list - - index - .drop_adj_list(neighbor_accessor, 3) - .await - .expect("Error in drop_adj_list"); - - // call drop_deleted_neighbors on vertex 1 with check_delete = true - // expected outcome: deleted neighbor is dropped - - index - .drop_deleted_neighbors(&ctx, neighbor_accessor, 1, true) - .await - .expect(drop_msg); - - let mut list1_after_drop = AdjacencyList::new(); - neighbor_accessor - .get_neighbors(1, &mut list1_after_drop) - .await - .expect(adj_msg); - list1_after_drop.sort(); - assert_eq!(&*list1_after_drop, &[2, 4]); - } - - #[tokio::test] - async fn test_get_undeleted_neighbors() { - // create small index instance - let dim = 1; - let (config, parameters) = simplified_builder( - 10, // l_search - 3, // max_degree - Metric::L2, // metric - dim, // dim - 5, // max_points - no_modify, - ) - .unwrap(); - - let pqtable = model::pq::FixedChunkPQTable::new( - dim, - Box::new([0.0]), - Box::new([0.0]), - Box::new([0, 1]), - ) - .unwrap(); - - let index = - new_quant_index::(config, parameters, pqtable, TableBasedDeletes).unwrap(); - - // build graph - let adjacency_lists = [ - AdjacencyList::from_iter_untrusted([2, 3, 1]), - AdjacencyList::from_iter_untrusted([2, 3, 4]), - AdjacencyList::from_iter_untrusted([0, 1, 4]), - AdjacencyList::from_iter_untrusted([2, 4, 0]), - AdjacencyList::from_iter_untrusted([0, 3, 2]), - ]; - - let neighbor_accessor = &mut index.provider().neighbors(); - let ctx = DefaultContext; - populate_graph(neighbor_accessor, &adjacency_lists).await; - - // delete id number 3 - index - .data_provider - .delete(&DefaultContext, &3_u32) - .await - .expect("Error in delete"); - - // we'll check vertices 0 and 2 - { - let PartitionedNeighbors { - mut undeleted, - mut deleted, - } = index - .get_undeleted_neighbors(&ctx, neighbor_accessor, 0) - .await - .expect("Error in get_undeleted_neighbors"); - undeleted.sort(); - assert_eq!(&undeleted, &[1, 2]); - deleted.sort(); - assert_eq!(&deleted, &[3]); - - let PartitionedNeighbors { undeleted, deleted } = index - .get_undeleted_neighbors(&ctx, neighbor_accessor, 2) - .await - .expect("Error in deleted"); - assert!(undeleted.len() == 3); - assert!(deleted.is_empty()); - } - - // delete id number 2 - index - .data_provider - .delete(&DefaultContext, &2_u32) - .await - .expect("Error in delete"); - - // we'll check vertices 0, 2, and 3 - { - let PartitionedNeighbors { - mut undeleted, - mut deleted, - } = index - .get_undeleted_neighbors(&ctx, neighbor_accessor, 0) - .await - .expect("Error in get_undeleted_neighbors"); - undeleted.sort(); - assert_eq!(&undeleted, &[1]); - deleted.sort(); - assert_eq!(&deleted, &[2, 3]); - - let PartitionedNeighbors { undeleted, deleted } = index - .get_undeleted_neighbors(&ctx, neighbor_accessor, 2) - .await - .expect("Error in get_undeleted_neighbors"); - assert!(undeleted.len() == 3); - assert!(deleted.is_empty()); - - let PartitionedNeighbors { - mut undeleted, - mut deleted, - } = index - .get_undeleted_neighbors(&ctx, neighbor_accessor, 3) - .await - .expect("Error in get_undeleted_neighbors"); - undeleted.sort(); - assert_eq!(&undeleted, &[0, 4]); - deleted.sort(); - assert_eq!(&deleted, &[2]); - } - } - #[tokio::test] async fn test_inplace_delete_2d() { test_inplace_delete_2d_impl(FullPrecision).await;