You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by so...@apache.org on 2020/12/10 02:43:37 UTC
[lucene-solr] branch master updated: reindent TestHnsw (was 4
indented spaces)
This is an automated email from the ASF dual-hosted git repository.
sokolov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git
The following commit(s) were added to refs/heads/master by this push:
new 8200f89 reindent TestHnsw (was 4 indented spaces)
8200f89 is described below
commit 8200f895e9757be618acd92f3f824d390f06fd3f
Author: Michael Sokolov <so...@amazon.com>
AuthorDate: Wed Dec 9 21:43:11 2020 -0500
reindent TestHnsw (was 4 indented spaces)
---
.../test/org/apache/lucene/util/hnsw/TestHnsw.java | 722 ++++++++++-----------
1 file changed, 361 insertions(+), 361 deletions(-)
diff --git a/lucene/core/src/test/org/apache/lucene/util/hnsw/TestHnsw.java b/lucene/core/src/test/org/apache/lucene/util/hnsw/TestHnsw.java
index ce6fb5c..f41bc31 100644
--- a/lucene/core/src/test/org/apache/lucene/util/hnsw/TestHnsw.java
+++ b/lucene/core/src/test/org/apache/lucene/util/hnsw/TestHnsw.java
@@ -48,405 +48,405 @@ import static org.apache.lucene.search.DocIdSetIterator.NO_MORE_DOCS;
/** Tests HNSW KNN graphs */
public class TestHnsw extends LuceneTestCase {
- // test writing out and reading in a graph gives the same graph
- public void testReadWrite() throws IOException {
- int dim = random().nextInt(100) + 1;
- int nDoc = random().nextInt(100) + 1;
- RandomVectorValues vectors = new RandomVectorValues(nDoc, dim, random());
- RandomVectorValues v2 = vectors.copy(), v3 = vectors.copy();
- long seed = random().nextLong();
- HnswGraphBuilder.randSeed = seed;
- HnswGraph hnsw = HnswGraphBuilder.build((RandomAccessVectorValuesProducer) vectors);
- // Recreate the graph while indexing with the same random seed and write it out
- HnswGraphBuilder.randSeed = seed;
- try (Directory dir = newDirectory()) {
- int nVec = 0, indexedDoc = 0;
- // Don't merge randomly, create a single segment because we rely on the docid ordering for this test
- IndexWriterConfig iwc = new IndexWriterConfig()
- .setCodec(Codec.forName("Lucene90"));
- try (IndexWriter iw = new IndexWriter(dir, iwc)) {
- while (v2.nextDoc() != NO_MORE_DOCS) {
- while (indexedDoc < v2.docID()) {
- // increment docId in the index by adding empty documents
- iw.addDocument(new Document());
- indexedDoc++;
- }
- Document doc = new Document();
- doc.add(new VectorField("field", v2.vectorValue(), v2.searchStrategy));
- doc.add(new StoredField("id", v2.docID()));
- iw.addDocument(doc);
- nVec++;
- indexedDoc++;
- }
- }
- try (IndexReader reader = DirectoryReader.open(dir)) {
- for (LeafReaderContext ctx : reader.leaves()) {
- VectorValues values = ctx.reader().getVectorValues("field");
- assertEquals(vectors.searchStrategy, values.searchStrategy());
- assertEquals(dim, values.dimension());
- assertEquals(nVec, values.size());
- assertEquals(indexedDoc, ctx.reader().maxDoc());
- assertEquals(indexedDoc, ctx.reader().numDocs());
- assertVectorsEqual(v3, values);
- KnnGraphValues graphValues = ((Lucene90VectorReader) ((CodecReader) ctx.reader()).getVectorReader()).getGraphValues("field");
- assertGraphEqual(hnsw.getGraphValues(), graphValues, nVec);
- }
- }
- }
+ // test writing out and reading in a graph gives the same graph
+ public void testReadWrite() throws IOException {
+ int dim = random().nextInt(100) + 1;
+ int nDoc = random().nextInt(100) + 1;
+ RandomVectorValues vectors = new RandomVectorValues(nDoc, dim, random());
+ RandomVectorValues v2 = vectors.copy(), v3 = vectors.copy();
+ long seed = random().nextLong();
+ HnswGraphBuilder.randSeed = seed;
+ HnswGraph hnsw = HnswGraphBuilder.build((RandomAccessVectorValuesProducer) vectors);
+ // Recreate the graph while indexing with the same random seed and write it out
+ HnswGraphBuilder.randSeed = seed;
+ try (Directory dir = newDirectory()) {
+ int nVec = 0, indexedDoc = 0;
+ // Don't merge randomly, create a single segment because we rely on the docid ordering for this test
+ IndexWriterConfig iwc = new IndexWriterConfig()
+ .setCodec(Codec.forName("Lucene90"));
+ try (IndexWriter iw = new IndexWriter(dir, iwc)) {
+ while (v2.nextDoc() != NO_MORE_DOCS) {
+ while (indexedDoc < v2.docID()) {
+ // increment docId in the index by adding empty documents
+ iw.addDocument(new Document());
+ indexedDoc++;
+ }
+ Document doc = new Document();
+ doc.add(new VectorField("field", v2.vectorValue(), v2.searchStrategy));
+ doc.add(new StoredField("id", v2.docID()));
+ iw.addDocument(doc);
+ nVec++;
+ indexedDoc++;
+ }
+ }
+ try (IndexReader reader = DirectoryReader.open(dir)) {
+ for (LeafReaderContext ctx : reader.leaves()) {
+ VectorValues values = ctx.reader().getVectorValues("field");
+ assertEquals(vectors.searchStrategy, values.searchStrategy());
+ assertEquals(dim, values.dimension());
+ assertEquals(nVec, values.size());
+ assertEquals(indexedDoc, ctx.reader().maxDoc());
+ assertEquals(indexedDoc, ctx.reader().numDocs());
+ assertVectorsEqual(v3, values);
+ KnnGraphValues graphValues = ((Lucene90VectorReader) ((CodecReader) ctx.reader()).getVectorReader()).getGraphValues("field");
+ assertGraphEqual(hnsw.getGraphValues(), graphValues, nVec);
+ }
+ }
+ }
+ }
+
+ // Make sure we actually approximately find the closest k elements. Mostly this is about
+ // ensuring that we have all the distance functions, comparators, priority queues and so on
+ // oriented in the right directions
+ public void testAknn() throws IOException {
+ int nDoc = 100;
+ RandomAccessVectorValuesProducer vectors = new CircularVectorValues(nDoc);
+ HnswGraph hnsw = HnswGraphBuilder.build(vectors);
+ // run some searches
+ Neighbors nn = HnswGraph.search(new float[]{1, 0}, 10, 5, vectors.randomAccess(), hnsw.getGraphValues(), random());
+ int sum = 0;
+ Neighbors.NeighborIterator it = nn.iterator();
+ for (int node = it.next(); node != NO_MORE_DOCS; node = it.next()) {
+ sum += node;
+ }
+ // We expect to get approximately 100% recall; the lowest docIds are closest to zero; sum(0,9) = 45
+ assertTrue("sum(result docs)=" + sum, sum < 75);
+ }
+
+ public void testMaxConnections() {
+ // verify that maxConnections is observed, and that the retained arcs point to the best-scoring neighbors
+ HnswGraph graph = new HnswGraph(1, VectorValues.SearchStrategy.DOT_PRODUCT_HNSW);
+ graph.connectNodes(0, 1, 0);
+ assertArrayEquals(new int[]{1}, graph.getNeighborNodes(0));
+ assertArrayEquals(new int[]{0}, graph.getNeighborNodes(1));
+ graph.connectNodes(0, 2, 0.4f);
+ assertArrayEquals(new int[]{2}, graph.getNeighborNodes(0));
+ assertArrayEquals(new int[]{0}, graph.getNeighborNodes(1));
+ assertArrayEquals(new int[]{0}, graph.getNeighborNodes(2));
+ graph.connectNodes(2, 3, 0);
+ assertArrayEquals(new int[]{2}, graph.getNeighborNodes(0));
+ assertArrayEquals(new int[]{0}, graph.getNeighborNodes(1));
+ assertArrayEquals(new int[]{0}, graph.getNeighborNodes(2));
+ assertArrayEquals(new int[]{2}, graph.getNeighborNodes(3));
+
+ graph = new HnswGraph(1, VectorValues.SearchStrategy.EUCLIDEAN_HNSW);
+ graph.connectNodes(0, 1, 1);
+ assertArrayEquals(new int[]{1}, graph.getNeighborNodes(0));
+ assertArrayEquals(new int[]{0}, graph.getNeighborNodes(1));
+ graph.connectNodes(0, 2, 2);
+ assertArrayEquals(new int[]{1}, graph.getNeighborNodes(0));
+ assertArrayEquals(new int[]{0}, graph.getNeighborNodes(1));
+ assertArrayEquals(new int[]{0}, graph.getNeighborNodes(2));
+ graph.connectNodes(2, 3, 1);
+ assertArrayEquals(new int[]{1}, graph.getNeighborNodes(0));
+ assertArrayEquals(new int[]{0}, graph.getNeighborNodes(1));
+ assertArrayEquals(new int[]{3}, graph.getNeighborNodes(2));
+ assertArrayEquals(new int[]{2}, graph.getNeighborNodes(3));
+ }
+
+ /** Returns vectors evenly distributed around the unit circle.
+ */
+ class CircularVectorValues extends VectorValues implements RandomAccessVectorValues, RandomAccessVectorValuesProducer {
+ private final int size;
+ private final float[] value;
+
+ int doc = -1;
+
+ CircularVectorValues(int size) {
+ this.size = size;
+ value = new float[2];
}
- // Make sure we actually approximately find the closest k elements. Mostly this is about
- // ensuring that we have all the distance functions, comparators, priority queues and so on
- // oriented in the right directions
- public void testAknn() throws IOException {
- int nDoc = 100;
- RandomAccessVectorValuesProducer vectors = new CircularVectorValues(nDoc);
- HnswGraph hnsw = HnswGraphBuilder.build(vectors);
- // run some searches
- Neighbors nn = HnswGraph.search(new float[]{1, 0}, 10, 5, vectors.randomAccess(), hnsw.getGraphValues(), random());
- int sum = 0;
- Neighbors.NeighborIterator it = nn.iterator();
- for (int node = it.next(); node != NO_MORE_DOCS; node = it.next()) {
- sum += node;
- }
- // We expect to get approximately 100% recall; the lowest docIds are closest to zero; sum(0,9) = 45
- assertTrue("sum(result docs)=" + sum, sum < 75);
- }
-
- public void testMaxConnections() {
- // verify that maxConnections is observed, and that the retained arcs point to the best-scoring neighbors
- HnswGraph graph = new HnswGraph(1, VectorValues.SearchStrategy.DOT_PRODUCT_HNSW);
- graph.connectNodes(0, 1, 0);
- assertArrayEquals(new int[]{1}, graph.getNeighborNodes(0));
- assertArrayEquals(new int[]{0}, graph.getNeighborNodes(1));
- graph.connectNodes(0, 2, 0.4f);
- assertArrayEquals(new int[]{2}, graph.getNeighborNodes(0));
- assertArrayEquals(new int[]{0}, graph.getNeighborNodes(1));
- assertArrayEquals(new int[]{0}, graph.getNeighborNodes(2));
- graph.connectNodes(2, 3, 0);
- assertArrayEquals(new int[]{2}, graph.getNeighborNodes(0));
- assertArrayEquals(new int[]{0}, graph.getNeighborNodes(1));
- assertArrayEquals(new int[]{0}, graph.getNeighborNodes(2));
- assertArrayEquals(new int[]{2}, graph.getNeighborNodes(3));
-
- graph = new HnswGraph(1, VectorValues.SearchStrategy.EUCLIDEAN_HNSW);
- graph.connectNodes(0, 1, 1);
- assertArrayEquals(new int[]{1}, graph.getNeighborNodes(0));
- assertArrayEquals(new int[]{0}, graph.getNeighborNodes(1));
- graph.connectNodes(0, 2, 2);
- assertArrayEquals(new int[]{1}, graph.getNeighborNodes(0));
- assertArrayEquals(new int[]{0}, graph.getNeighborNodes(1));
- assertArrayEquals(new int[]{0}, graph.getNeighborNodes(2));
- graph.connectNodes(2, 3, 1);
- assertArrayEquals(new int[]{1}, graph.getNeighborNodes(0));
- assertArrayEquals(new int[]{0}, graph.getNeighborNodes(1));
- assertArrayEquals(new int[]{3}, graph.getNeighborNodes(2));
- assertArrayEquals(new int[]{2}, graph.getNeighborNodes(3));
- }
-
- /** Returns vectors evenly distributed around the unit circle.
- */
- class CircularVectorValues extends VectorValues implements RandomAccessVectorValues, RandomAccessVectorValuesProducer {
- private final int size;
- private final float[] value;
-
- int doc = -1;
-
- CircularVectorValues(int size) {
- this.size = size;
- value = new float[2];
- }
-
- public CircularVectorValues copy() {
- return new CircularVectorValues(size);
- }
-
- @Override
- public SearchStrategy searchStrategy() {
- return SearchStrategy.DOT_PRODUCT_HNSW;
- }
-
- @Override
- public int dimension() {
- return 2;
- }
-
- @Override
- public int size() {
- return size;
- }
-
- @Override
- public float[] vectorValue() {
- return vectorValue(doc);
- }
-
- @Override
- public RandomAccessVectorValues randomAccess() {
- return new CircularVectorValues(size);
- }
+ public CircularVectorValues copy() {
+ return new CircularVectorValues(size);
+ }
- @Override
- public int docID() {
- return doc;
- }
+ @Override
+ public SearchStrategy searchStrategy() {
+ return SearchStrategy.DOT_PRODUCT_HNSW;
+ }
- @Override
- public int nextDoc() {
- return advance(doc + 1);
- }
+ @Override
+ public int dimension() {
+ return 2;
+ }
- @Override
- public int advance(int target) {
- if (target >= 0 && target < size) {
- doc = target;
- } else {
- doc = NO_MORE_DOCS;
- }
- return doc;
- }
+ @Override
+ public int size() {
+ return size;
+ }
- @Override
- public long cost() {
- return size;
- }
+ @Override
+ public float[] vectorValue() {
+ return vectorValue(doc);
+ }
- @Override
- public float[] vectorValue(int ord) {
- value[0] = (float) Math.cos(Math.PI * ord / (double) size);
- value[1] = (float) Math.sin(Math.PI * ord / (double) size);
- return value;
- }
+ @Override
+ public RandomAccessVectorValues randomAccess() {
+ return new CircularVectorValues(size);
+ }
- @Override
- public BytesRef binaryValue(int ord) {
- return null;
- }
+ @Override
+ public int docID() {
+ return doc;
+ }
- @Override
- public TopDocs search(float[] target, int k, int fanout) {
- return null;
- }
+ @Override
+ public int nextDoc() {
+ return advance(doc + 1);
+ }
+ @Override
+ public int advance(int target) {
+ if (target >= 0 && target < size) {
+ doc = target;
+ } else {
+ doc = NO_MORE_DOCS;
+ }
+ return doc;
}
- private void assertGraphEqual(KnnGraphValues g, KnnGraphValues h, int size) throws IOException {
- for (int node = 0; node < size; node ++) {
- g.seek(node);
- h.seek(node);
- assertEquals("arcs differ for node " + node, getNeighborNodes(g), getNeighborNodes(h));
- }
+ @Override
+ public long cost() {
+ return size;
}
- private Set<Integer> getNeighborNodes(KnnGraphValues g) throws IOException {
- Set<Integer> neighbors = new HashSet<>();
- for (int n = g.nextNeighbor(); n != NO_MORE_DOCS; n = g.nextNeighbor()) {
- neighbors.add(n);
- }
- return neighbors;
- }
-
- private void assertVectorsEqual(VectorValues u, VectorValues v) throws IOException {
- int uDoc, vDoc;
- while (true) {
- uDoc = u.nextDoc();
- vDoc = v.nextDoc();
- assertEquals(uDoc, vDoc);
- if (uDoc == NO_MORE_DOCS) {
- break;
- }
- assertArrayEquals("vectors do not match for doc=" + uDoc, u.vectorValue(), v.vectorValue(), 1e-4f);
- }
+ @Override
+ public float[] vectorValue(int ord) {
+ value[0] = (float) Math.cos(Math.PI * ord / (double) size);
+ value[1] = (float) Math.sin(Math.PI * ord / (double) size);
+ return value;
}
- public void testNeighbors() {
- // make sure we have the sign correct
- Neighbors nn = Neighbors.create(2, VectorValues.SearchStrategy.DOT_PRODUCT_HNSW);
- assertTrue(nn.insertWithOverflow(2, 0.5f));
- assertTrue(nn.insertWithOverflow(1, 0.2f));
- assertTrue(nn.insertWithOverflow(3, 1f));
- assertEquals(0.5f, nn.topScore(), 0);
- nn.pop();
- assertEquals(1f, nn.topScore(), 0);
- nn.pop();
-
- Neighbors fn = Neighbors.create(2, VectorValues.SearchStrategy.EUCLIDEAN_HNSW);
- assertTrue(fn.insertWithOverflow(2, 2));
- assertTrue(fn.insertWithOverflow(1, 1));
- assertFalse(fn.insertWithOverflow(3, 3));
- assertEquals(2f, fn.topScore(), 0);
- fn.pop();
- assertEquals(1f, fn.topScore(), 0);
- }
-
- private static float[] randomVector(Random random, int dim) {
- float[] vec = new float[dim];
- for (int i = 0; i < dim; i++) {
- vec[i] = random.nextFloat();
- }
- VectorUtil.l2normalize(vec);
- return vec;
- }
-
- /**
- * Produces random vectors and caches them for random-access.
- */
- class RandomVectorValues extends VectorValues implements RandomAccessVectorValues, RandomAccessVectorValuesProducer {
-
- private final int dimension;
- private final float[][] denseValues;
- private final float[][] values;
- private final float[] scratch;
- private final SearchStrategy searchStrategy;
-
- final int numVectors;
- final int maxDoc;
-
- private int pos = -1;
-
- RandomVectorValues(int size, int dimension, Random random) {
- this.dimension = dimension;
- values = new float[size][];
- denseValues = new float[size][];
- scratch = new float[dimension];
- int sz = 0;
- int md = -1;
- for (int offset = 0; offset < size; offset += random.nextInt(3) + 1) {
- values[offset] = randomVector(random, dimension);
- denseValues[sz++] = values[offset];
- md = offset;
- }
- numVectors = sz;
- maxDoc = md;
- // get a random SearchStrategy other than NONE (0)
- searchStrategy = SearchStrategy.values()[random.nextInt(SearchStrategy.values().length - 1) + 1];
- }
+ @Override
+ public BytesRef binaryValue(int ord) {
+ return null;
+ }
- private RandomVectorValues(int dimension, SearchStrategy searchStrategy, float[][] denseValues, float[][] values, int size) {
- this.dimension = dimension;
- this.searchStrategy = searchStrategy;
- this.values = values;
- this.denseValues = denseValues;
- scratch = new float[dimension];
- numVectors = size;
- maxDoc = values.length - 1;
- }
+ @Override
+ public TopDocs search(float[] target, int k, int fanout) {
+ return null;
+ }
- public RandomVectorValues copy() {
- return new RandomVectorValues(dimension, searchStrategy, denseValues, values, numVectors);
- }
+ }
- @Override
- public int size() {
- return numVectors;
- }
+ private void assertGraphEqual(KnnGraphValues g, KnnGraphValues h, int size) throws IOException {
+ for (int node = 0; node < size; node ++) {
+ g.seek(node);
+ h.seek(node);
+ assertEquals("arcs differ for node " + node, getNeighborNodes(g), getNeighborNodes(h));
+ }
+ }
- @Override
- public SearchStrategy searchStrategy() {
- return searchStrategy;
- }
+ private Set<Integer> getNeighborNodes(KnnGraphValues g) throws IOException {
+ Set<Integer> neighbors = new HashSet<>();
+ for (int n = g.nextNeighbor(); n != NO_MORE_DOCS; n = g.nextNeighbor()) {
+ neighbors.add(n);
+ }
+ return neighbors;
+ }
+
+ private void assertVectorsEqual(VectorValues u, VectorValues v) throws IOException {
+ int uDoc, vDoc;
+ while (true) {
+ uDoc = u.nextDoc();
+ vDoc = v.nextDoc();
+ assertEquals(uDoc, vDoc);
+ if (uDoc == NO_MORE_DOCS) {
+ break;
+ }
+ assertArrayEquals("vectors do not match for doc=" + uDoc, u.vectorValue(), v.vectorValue(), 1e-4f);
+ }
+ }
+
+ public void testNeighbors() {
+ // make sure we have the sign correct
+ Neighbors nn = Neighbors.create(2, VectorValues.SearchStrategy.DOT_PRODUCT_HNSW);
+ assertTrue(nn.insertWithOverflow(2, 0.5f));
+ assertTrue(nn.insertWithOverflow(1, 0.2f));
+ assertTrue(nn.insertWithOverflow(3, 1f));
+ assertEquals(0.5f, nn.topScore(), 0);
+ nn.pop();
+ assertEquals(1f, nn.topScore(), 0);
+ nn.pop();
+
+ Neighbors fn = Neighbors.create(2, VectorValues.SearchStrategy.EUCLIDEAN_HNSW);
+ assertTrue(fn.insertWithOverflow(2, 2));
+ assertTrue(fn.insertWithOverflow(1, 1));
+ assertFalse(fn.insertWithOverflow(3, 3));
+ assertEquals(2f, fn.topScore(), 0);
+ fn.pop();
+ assertEquals(1f, fn.topScore(), 0);
+ }
+
+ private static float[] randomVector(Random random, int dim) {
+ float[] vec = new float[dim];
+ for (int i = 0; i < dim; i++) {
+ vec[i] = random.nextFloat();
+ }
+ VectorUtil.l2normalize(vec);
+ return vec;
+ }
+
+ /**
+ * Produces random vectors and caches them for random-access.
+ */
+ class RandomVectorValues extends VectorValues implements RandomAccessVectorValues, RandomAccessVectorValuesProducer {
+
+ private final int dimension;
+ private final float[][] denseValues;
+ private final float[][] values;
+ private final float[] scratch;
+ private final SearchStrategy searchStrategy;
+
+ final int numVectors;
+ final int maxDoc;
+
+ private int pos = -1;
+
+ RandomVectorValues(int size, int dimension, Random random) {
+ this.dimension = dimension;
+ values = new float[size][];
+ denseValues = new float[size][];
+ scratch = new float[dimension];
+ int sz = 0;
+ int md = -1;
+ for (int offset = 0; offset < size; offset += random.nextInt(3) + 1) {
+ values[offset] = randomVector(random, dimension);
+ denseValues[sz++] = values[offset];
+ md = offset;
+ }
+ numVectors = sz;
+ maxDoc = md;
+ // get a random SearchStrategy other than NONE (0)
+ searchStrategy = SearchStrategy.values()[random.nextInt(SearchStrategy.values().length - 1) + 1];
+ }
- @Override
- public int dimension() {
- return dimension;
- }
+ private RandomVectorValues(int dimension, SearchStrategy searchStrategy, float[][] denseValues, float[][] values, int size) {
+ this.dimension = dimension;
+ this.searchStrategy = searchStrategy;
+ this.values = values;
+ this.denseValues = denseValues;
+ scratch = new float[dimension];
+ numVectors = size;
+ maxDoc = values.length - 1;
+ }
- @Override
- public float[] vectorValue() {
- if(random().nextBoolean()) {
- return values[pos];
- } else {
- // Sometimes use the same scratch array repeatedly, mimicing what the codec will do.
- // This should help us catch cases of aliasing where the same VectorValues source is used twice in a
- // single computation.
- System.arraycopy(values[pos], 0, scratch, 0, dimension);
- return scratch;
- }
- }
+ public RandomVectorValues copy() {
+ return new RandomVectorValues(dimension, searchStrategy, denseValues, values, numVectors);
+ }
- @Override
- public RandomAccessVectorValues randomAccess() {
- return copy();
- }
+ @Override
+ public int size() {
+ return numVectors;
+ }
- @Override
- public float[] vectorValue(int targetOrd) {
- return denseValues[targetOrd];
- }
+ @Override
+ public SearchStrategy searchStrategy() {
+ return searchStrategy;
+ }
- @Override
- public BytesRef binaryValue(int targetOrd) {
- return null;
- }
+ @Override
+ public int dimension() {
+ return dimension;
+ }
- @Override
- public TopDocs search(float[] target, int k, int fanout) {
- return null;
- }
+ @Override
+ public float[] vectorValue() {
+ if(random().nextBoolean()) {
+ return values[pos];
+ } else {
+ // Sometimes use the same scratch array repeatedly, mimicing what the codec will do.
+ // This should help us catch cases of aliasing where the same VectorValues source is used twice in a
+ // single computation.
+ System.arraycopy(values[pos], 0, scratch, 0, dimension);
+ return scratch;
+ }
+ }
- private boolean seek(int target) {
- if (target >= 0 && target < values.length && values[target] != null) {
- pos = target;
- return true;
- } else {
- return false;
- }
- }
+ @Override
+ public RandomAccessVectorValues randomAccess() {
+ return copy();
+ }
- @Override
- public int docID() {
- return pos;
- }
+ @Override
+ public float[] vectorValue(int targetOrd) {
+ return denseValues[targetOrd];
+ }
- @Override
- public int nextDoc() {
- return advance(pos + 1);
- }
+ @Override
+ public BytesRef binaryValue(int targetOrd) {
+ return null;
+ }
- public int advance(int target) {
- while (++pos < values.length) {
- if (seek(pos)) {
- return pos;
- }
- }
- return NO_MORE_DOCS;
- }
+ @Override
+ public TopDocs search(float[] target, int k, int fanout) {
+ return null;
+ }
- @Override
- public long cost() {
- return size();
- }
+ private boolean seek(int target) {
+ if (target >= 0 && target < values.length && values[target] != null) {
+ pos = target;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ @Override
+ public int docID() {
+ return pos;
}
- public void testBoundsCheckerMax() {
- BoundsChecker max = BoundsChecker.create(false);
- float f = random().nextFloat() - 0.5f;
- // any float > -MAX_VALUE is in bounds
- assertFalse(max.check(f));
- // f is now the bound (minus some delta)
- max.update(f);
- assertFalse(max.check(f)); // f is not out of bounds
- assertFalse(max.check(f + 1)); // anything greater than f is in bounds
- assertTrue(max.check(f - 1e-5f)); // delta is zero initially
+ @Override
+ public int nextDoc() {
+ return advance(pos + 1);
}
- public void testBoundsCheckerMin() {
- BoundsChecker min = BoundsChecker.create(true);
- float f = random().nextFloat() - 0.5f;
- // any float < MAX_VALUE is in bounds
- assertFalse(min.check(f));
- // f is now the bound (minus some delta)
- min.update(f);
- assertFalse(min.check(f)); // f is not out of bounds
- assertFalse(min.check(f - 1)); // anything less than f is in bounds
- assertTrue(min.check(f + 1e-5f)); // delta is zero initially
+ public int advance(int target) {
+ while (++pos < values.length) {
+ if (seek(pos)) {
+ return pos;
+ }
+ }
+ return NO_MORE_DOCS;
}
- public void testHnswGraphBuilderInvalid() {
- expectThrows(NullPointerException.class, () -> new HnswGraphBuilder(null, 0, 0, 0));
- expectThrows(IllegalArgumentException.class, () -> new HnswGraphBuilder(new RandomVectorValues(1, 1, random()), 0, 10, 0));
- expectThrows(IllegalArgumentException.class, () -> new HnswGraphBuilder(new RandomVectorValues(1, 1, random()), 10, 0, 0));
+ @Override
+ public long cost() {
+ return size();
}
+ }
+
+ public void testBoundsCheckerMax() {
+ BoundsChecker max = BoundsChecker.create(false);
+ float f = random().nextFloat() - 0.5f;
+ // any float > -MAX_VALUE is in bounds
+ assertFalse(max.check(f));
+ // f is now the bound (minus some delta)
+ max.update(f);
+ assertFalse(max.check(f)); // f is not out of bounds
+ assertFalse(max.check(f + 1)); // anything greater than f is in bounds
+ assertTrue(max.check(f - 1e-5f)); // delta is zero initially
+ }
+
+ public void testBoundsCheckerMin() {
+ BoundsChecker min = BoundsChecker.create(true);
+ float f = random().nextFloat() - 0.5f;
+ // any float < MAX_VALUE is in bounds
+ assertFalse(min.check(f));
+ // f is now the bound (minus some delta)
+ min.update(f);
+ assertFalse(min.check(f)); // f is not out of bounds
+ assertFalse(min.check(f - 1)); // anything less than f is in bounds
+ assertTrue(min.check(f + 1e-5f)); // delta is zero initially
+ }
+
+ public void testHnswGraphBuilderInvalid() {
+ expectThrows(NullPointerException.class, () -> new HnswGraphBuilder(null, 0, 0, 0));
+ expectThrows(IllegalArgumentException.class, () -> new HnswGraphBuilder(new RandomVectorValues(1, 1, random()), 0, 10, 0));
+ expectThrows(IllegalArgumentException.class, () -> new HnswGraphBuilder(new RandomVectorValues(1, 1, random()), 10, 0, 0));
+ }
+
}