mayya-sharipova commented on a change in pull request #267:
URL: https://github.com/apache/lucene/pull/267#discussion_r700571247



##########
File path: lucene/core/src/test/org/apache/lucene/util/hnsw/TestHNSWGraph2.java
##########
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.lucene.util.hnsw;
+
+import static org.apache.lucene.index.TestKnnGraph.assertMaxConn;
+import static org.apache.lucene.search.DocIdSetIterator.NO_MORE_DOCS;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+import org.apache.lucene.index.VectorSimilarityFunction;
+import org.apache.lucene.search.DocIdSetIterator;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util.VectorUtil;
+
+public class TestHNSWGraph2 extends LuceneTestCase {
+
+  // Tests that graph is consistent.
+  public void testGraphConsistent() throws IOException {
+    int dim = random().nextInt(100) + 1;
+    int nDoc = random().nextInt(100) + 1;
+    MockVectorValues values = new MockVectorValues(createRandomVectors(nDoc, 
dim, random()));
+    int beamWidth = random().nextInt(10) + 5;
+    int maxConn = random().nextInt(10) + 5;
+    double ml = 1 / Math.log(1.0 * maxConn);
+    long seed = random().nextLong();
+    VectorSimilarityFunction similarityFunction =
+        VectorSimilarityFunction.values()[
+            random().nextInt(VectorSimilarityFunction.values().length - 1) + 
1];
+    HnswGraphBuilder builder =
+        new HnswGraphBuilder(values, similarityFunction, maxConn, beamWidth, 
seed, ml);
+    HnswGraph hnsw = builder.build(values);
+    assertConsistentGraph(hnsw, maxConn);
+  }
+
+  /**
+   * For each level of the graph, test that
+   *
+   * <p>1. There are no orphan nodes without any friends
+   *
+   * <p>2. If orphans are found, than the level must contain only 0 or a 
single node
+   *
+   * <p>3. If the number of nodes on the level doesn't exceed maxConn, assert 
that the graph is
+   * fully connected, i.e. any node is reachable from any other node.
+   *
+   * <p>4. If the number of nodes on the level exceeds maxConn, assert that 
maxConn is respected.
+   *
+   * <p>copy from TestKnnGraph::assertConsistentGraph with parts relevant only 
to in-memory graphs
+   * TODO: remove when hierarchical graph is implemented on disk
+   */
+  private static void assertConsistentGraph(HnswGraph hnsw, int maxConn) {
+    for (int level = hnsw.maxLevel(); level >= 0; level--) {
+      hnsw.seekLevel(level);
+
+      int[][] graph = new int[hnsw.size()][];
+      int nodesCount = 0;
+      boolean foundOrphan = false;
+
+      for (int node = hnsw.nextNodeOnLevel();
+          node != DocIdSetIterator.NO_MORE_DOCS;
+          node = hnsw.nextNodeOnLevel()) {
+        hnsw.seek(level, node);
+        int arc;
+        List<Integer> friends = new ArrayList<>();
+        while ((arc = hnsw.nextNeighbor()) != NO_MORE_DOCS) {
+          friends.add(arc);
+        }
+        if (friends.size() == 0) {
+          foundOrphan = true;
+        } else {
+          int[] friendsCopy = new int[friends.size()];
+          for (int f = 0; f < friends.size(); f++) {
+            friendsCopy[f] = friends.get(f);
+          }
+          graph[node] = friendsCopy;
+        }
+        nodesCount++;
+      }
+      // System.out.println("Level[" + level + "] has [" + nodesCount + "] 
nodes.");
+
+      assertFalse("No nodes on level [" + level + "]", nodesCount == 0);
+      if (nodesCount == 1) {
+        assertTrue(
+            "Graph with 1 node has unexpected neighbors on level [" + level + 
"]", foundOrphan);
+      } else {
+        assertFalse("Graph has orphan nodes with no friends on level [" + 
level + "]", foundOrphan);
+        if (maxConn > nodesCount) {
+          // assert that the graph in fully connected, i.e. any node can be 
reached from any other

Review comment:
       Addressed in 6a05951772cc72a1530f3fd863d906dc0e3bef88




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscr...@lucene.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscr...@lucene.apache.org
For additional commands, e-mail: issues-h...@lucene.apache.org

Reply via email to