@Test(expectedExceptions = RuntimeException.class) public void testGetNearesWithWrongDim() throws IOException { ANNIndex index = new ANNIndex(8, Paths.get(DIR, "points.angular.annoy").toString(), IndexType.ANGULAR); double[] u = {0f, 1.0f, 0.2f, 0.1f, 0f, 1.0f, 0.2f, 0.1f, 1f}; index.getNearest(u, 10); }
@Override public final List<Integer> getNearest(final double[] queryVector, final int nResults) { if (queryVector.length != DIMENSION) { throw new RuntimeException(String.format("queryVector must be size of %d, but was %d", DIMENSION, queryVector.length)); } PriorityQueue<PQEntry> pq = new PriorityQueue<>( roots.size() * FLOAT_SIZE); final float kMaxPriority = 1e30f; for (long r : roots) { pq.add(new PQEntry(kMaxPriority, r)); } Set<Integer> nearestNeighbors = new HashSet<Integer>(); while (nearestNeighbors.size() < roots.size() * nResults && !pq.isEmpty()) { PQEntry top = pq.poll(); long topNodeOffset = top.nodeOffset; int nDescendants = getIntInAnnBuf(topNodeOffset); double[] v = getNodeVector(topNodeOffset); if (nDescendants == 1) { if (isZeroVec(v)) continue; nearestNeighbors.add((int) (topNodeOffset / NODE_SIZE)); } else if (nDescendants <= MIN_LEAF_SIZE) { for (int i = 0; i < nDescendants; i++) { int j = getIntInAnnBuf(topNodeOffset + INDEX_TYPE_OFFSET + i * INT_SIZE); if (isZeroVec(getNodeVector(j * NODE_SIZE))) continue; nearestNeighbors.add(j); } } else { float margin = (INDEX_TYPE == IndexType.ANGULAR) ? cosineMargin(v, queryVector) : euclideanMargin(v, queryVector, getNodeBias(topNodeOffset)); long childrenMemOffset = topNodeOffset + INDEX_TYPE_OFFSET; long lChild = NODE_SIZE * getIntInAnnBuf(childrenMemOffset); long rChild = NODE_SIZE * getIntInAnnBuf(childrenMemOffset + 4); pq.add(new PQEntry(-margin, lChild)); pq.add(new PQEntry(margin, rChild)); } } ArrayList<PQEntry> sortedNNs = new ArrayList<PQEntry>(); for (int nn : nearestNeighbors) { double[] v = getItemVector(nn); if (!isZeroVec(v)) { sortedNNs.add( new PQEntry((INDEX_TYPE == IndexType.ANGULAR) ? cosineMargin(v, queryVector) : -euclideanDistance(v, queryVector), nn)); } } Collections.sort(sortedNNs); ArrayList<Integer> result = new ArrayList<>(nResults); for (int i = 0; i < nResults && i < sortedNNs.size(); i++) { result.add((int) sortedNNs.get(i).nodeOffset); } return result; }
ANNIndex implements AnnoyIndex { @Override public final List<Integer> getNearest(final double[] queryVector, final int nResults) { if (queryVector.length != DIMENSION) { throw new RuntimeException(String.format("queryVector must be size of %d, but was %d", DIMENSION, queryVector.length)); } PriorityQueue<PQEntry> pq = new PriorityQueue<>( roots.size() * FLOAT_SIZE); final float kMaxPriority = 1e30f; for (long r : roots) { pq.add(new PQEntry(kMaxPriority, r)); } Set<Integer> nearestNeighbors = new HashSet<Integer>(); while (nearestNeighbors.size() < roots.size() * nResults && !pq.isEmpty()) { PQEntry top = pq.poll(); long topNodeOffset = top.nodeOffset; int nDescendants = getIntInAnnBuf(topNodeOffset); double[] v = getNodeVector(topNodeOffset); if (nDescendants == 1) { if (isZeroVec(v)) continue; nearestNeighbors.add((int) (topNodeOffset / NODE_SIZE)); } else if (nDescendants <= MIN_LEAF_SIZE) { for (int i = 0; i < nDescendants; i++) { int j = getIntInAnnBuf(topNodeOffset + INDEX_TYPE_OFFSET + i * INT_SIZE); if (isZeroVec(getNodeVector(j * NODE_SIZE))) continue; nearestNeighbors.add(j); } } else { float margin = (INDEX_TYPE == IndexType.ANGULAR) ? cosineMargin(v, queryVector) : euclideanMargin(v, queryVector, getNodeBias(topNodeOffset)); long childrenMemOffset = topNodeOffset + INDEX_TYPE_OFFSET; long lChild = NODE_SIZE * getIntInAnnBuf(childrenMemOffset); long rChild = NODE_SIZE * getIntInAnnBuf(childrenMemOffset + 4); pq.add(new PQEntry(-margin, lChild)); pq.add(new PQEntry(margin, rChild)); } } ArrayList<PQEntry> sortedNNs = new ArrayList<PQEntry>(); for (int nn : nearestNeighbors) { double[] v = getItemVector(nn); if (!isZeroVec(v)) { sortedNNs.add( new PQEntry((INDEX_TYPE == IndexType.ANGULAR) ? cosineMargin(v, queryVector) : -euclideanDistance(v, queryVector), nn)); } } Collections.sort(sortedNNs); ArrayList<Integer> result = new ArrayList<>(nResults); for (int i = 0; i < nResults && i < sortedNNs.size(); i++) { result.add((int) sortedNNs.get(i).nodeOffset); } return result; } }
ANNIndex implements AnnoyIndex { @Override public final List<Integer> getNearest(final double[] queryVector, final int nResults) { if (queryVector.length != DIMENSION) { throw new RuntimeException(String.format("queryVector must be size of %d, but was %d", DIMENSION, queryVector.length)); } PriorityQueue<PQEntry> pq = new PriorityQueue<>( roots.size() * FLOAT_SIZE); final float kMaxPriority = 1e30f; for (long r : roots) { pq.add(new PQEntry(kMaxPriority, r)); } Set<Integer> nearestNeighbors = new HashSet<Integer>(); while (nearestNeighbors.size() < roots.size() * nResults && !pq.isEmpty()) { PQEntry top = pq.poll(); long topNodeOffset = top.nodeOffset; int nDescendants = getIntInAnnBuf(topNodeOffset); double[] v = getNodeVector(topNodeOffset); if (nDescendants == 1) { if (isZeroVec(v)) continue; nearestNeighbors.add((int) (topNodeOffset / NODE_SIZE)); } else if (nDescendants <= MIN_LEAF_SIZE) { for (int i = 0; i < nDescendants; i++) { int j = getIntInAnnBuf(topNodeOffset + INDEX_TYPE_OFFSET + i * INT_SIZE); if (isZeroVec(getNodeVector(j * NODE_SIZE))) continue; nearestNeighbors.add(j); } } else { float margin = (INDEX_TYPE == IndexType.ANGULAR) ? cosineMargin(v, queryVector) : euclideanMargin(v, queryVector, getNodeBias(topNodeOffset)); long childrenMemOffset = topNodeOffset + INDEX_TYPE_OFFSET; long lChild = NODE_SIZE * getIntInAnnBuf(childrenMemOffset); long rChild = NODE_SIZE * getIntInAnnBuf(childrenMemOffset + 4); pq.add(new PQEntry(-margin, lChild)); pq.add(new PQEntry(margin, rChild)); } } ArrayList<PQEntry> sortedNNs = new ArrayList<PQEntry>(); for (int nn : nearestNeighbors) { double[] v = getItemVector(nn); if (!isZeroVec(v)) { sortedNNs.add( new PQEntry((INDEX_TYPE == IndexType.ANGULAR) ? cosineMargin(v, queryVector) : -euclideanDistance(v, queryVector), nn)); } } Collections.sort(sortedNNs); ArrayList<Integer> result = new ArrayList<>(nResults); for (int i = 0; i < nResults && i < sortedNNs.size(); i++) { result.add((int) sortedNNs.get(i).nodeOffset); } return result; } ANNIndex(final int dimension,
                    final String filename,
                    IndexType indexType);  ANNIndex(final int dimension,
                    final String filename);   ANNIndex(final int dimension,
             final String filename,
             IndexType indexType,
             final int blockSize); }
ANNIndex implements AnnoyIndex { @Override public final List<Integer> getNearest(final double[] queryVector, final int nResults) { if (queryVector.length != DIMENSION) { throw new RuntimeException(String.format("queryVector must be size of %d, but was %d", DIMENSION, queryVector.length)); } PriorityQueue<PQEntry> pq = new PriorityQueue<>( roots.size() * FLOAT_SIZE); final float kMaxPriority = 1e30f; for (long r : roots) { pq.add(new PQEntry(kMaxPriority, r)); } Set<Integer> nearestNeighbors = new HashSet<Integer>(); while (nearestNeighbors.size() < roots.size() * nResults && !pq.isEmpty()) { PQEntry top = pq.poll(); long topNodeOffset = top.nodeOffset; int nDescendants = getIntInAnnBuf(topNodeOffset); double[] v = getNodeVector(topNodeOffset); if (nDescendants == 1) { if (isZeroVec(v)) continue; nearestNeighbors.add((int) (topNodeOffset / NODE_SIZE)); } else if (nDescendants <= MIN_LEAF_SIZE) { for (int i = 0; i < nDescendants; i++) { int j = getIntInAnnBuf(topNodeOffset + INDEX_TYPE_OFFSET + i * INT_SIZE); if (isZeroVec(getNodeVector(j * NODE_SIZE))) continue; nearestNeighbors.add(j); } } else { float margin = (INDEX_TYPE == IndexType.ANGULAR) ? cosineMargin(v, queryVector) : euclideanMargin(v, queryVector, getNodeBias(topNodeOffset)); long childrenMemOffset = topNodeOffset + INDEX_TYPE_OFFSET; long lChild = NODE_SIZE * getIntInAnnBuf(childrenMemOffset); long rChild = NODE_SIZE * getIntInAnnBuf(childrenMemOffset + 4); pq.add(new PQEntry(-margin, lChild)); pq.add(new PQEntry(margin, rChild)); } } ArrayList<PQEntry> sortedNNs = new ArrayList<PQEntry>(); for (int nn : nearestNeighbors) { double[] v = getItemVector(nn); if (!isZeroVec(v)) { sortedNNs.add( new PQEntry((INDEX_TYPE == IndexType.ANGULAR) ? cosineMargin(v, queryVector) : -euclideanDistance(v, queryVector), nn)); } } Collections.sort(sortedNNs); ArrayList<Integer> result = new ArrayList<>(nResults); for (int i = 0; i < nResults && i < sortedNNs.size(); i++) { result.add((int) sortedNNs.get(i).nodeOffset); } return result; } ANNIndex(final int dimension,
                    final String filename,
                    IndexType indexType);  ANNIndex(final int dimension,
                    final String filename);   ANNIndex(final int dimension,
             final String filename,
             IndexType indexType,
             final int blockSize); @Override @SuppressWarnings("deprecation") void getNodeVector(final long nodeOffset, double[] v); @Override @SuppressWarnings("deprecation") void getItemVector(int itemIndex, double[] v); final double[] getItemVector(final int itemIndex); double[] getNodeVector(final long nodeOffset); static float cosineMargin(final double[] u, final double[] v); static float euclideanMargin(final double[] u,
                                        final double[] v,
                                        final float bias); @Override void close(); @Override final List<Integer> getNearest(final double[] queryVector,
                                          final int nResults); static void main(final String[] args); }
ANNIndex implements AnnoyIndex { @Override public final List<Integer> getNearest(final double[] queryVector, final int nResults) { if (queryVector.length != DIMENSION) { throw new RuntimeException(String.format("queryVector must be size of %d, but was %d", DIMENSION, queryVector.length)); } PriorityQueue<PQEntry> pq = new PriorityQueue<>( roots.size() * FLOAT_SIZE); final float kMaxPriority = 1e30f; for (long r : roots) { pq.add(new PQEntry(kMaxPriority, r)); } Set<Integer> nearestNeighbors = new HashSet<Integer>(); while (nearestNeighbors.size() < roots.size() * nResults && !pq.isEmpty()) { PQEntry top = pq.poll(); long topNodeOffset = top.nodeOffset; int nDescendants = getIntInAnnBuf(topNodeOffset); double[] v = getNodeVector(topNodeOffset); if (nDescendants == 1) { if (isZeroVec(v)) continue; nearestNeighbors.add((int) (topNodeOffset / NODE_SIZE)); } else if (nDescendants <= MIN_LEAF_SIZE) { for (int i = 0; i < nDescendants; i++) { int j = getIntInAnnBuf(topNodeOffset + INDEX_TYPE_OFFSET + i * INT_SIZE); if (isZeroVec(getNodeVector(j * NODE_SIZE))) continue; nearestNeighbors.add(j); } } else { float margin = (INDEX_TYPE == IndexType.ANGULAR) ? cosineMargin(v, queryVector) : euclideanMargin(v, queryVector, getNodeBias(topNodeOffset)); long childrenMemOffset = topNodeOffset + INDEX_TYPE_OFFSET; long lChild = NODE_SIZE * getIntInAnnBuf(childrenMemOffset); long rChild = NODE_SIZE * getIntInAnnBuf(childrenMemOffset + 4); pq.add(new PQEntry(-margin, lChild)); pq.add(new PQEntry(margin, rChild)); } } ArrayList<PQEntry> sortedNNs = new ArrayList<PQEntry>(); for (int nn : nearestNeighbors) { double[] v = getItemVector(nn); if (!isZeroVec(v)) { sortedNNs.add( new PQEntry((INDEX_TYPE == IndexType.ANGULAR) ? cosineMargin(v, queryVector) : -euclideanDistance(v, queryVector), nn)); } } Collections.sort(sortedNNs); ArrayList<Integer> result = new ArrayList<>(nResults); for (int i = 0; i < nResults && i < sortedNNs.size(); i++) { result.add((int) sortedNNs.get(i).nodeOffset); } return result; } ANNIndex(final int dimension,
                    final String filename,
                    IndexType indexType);  ANNIndex(final int dimension,
                    final String filename);   ANNIndex(final int dimension,
             final String filename,
             IndexType indexType,
             final int blockSize); @Override @SuppressWarnings("deprecation") void getNodeVector(final long nodeOffset, double[] v); @Override @SuppressWarnings("deprecation") void getItemVector(int itemIndex, double[] v); final double[] getItemVector(final int itemIndex); double[] getNodeVector(final long nodeOffset); static float cosineMargin(final double[] u, final double[] v); static float euclideanMargin(final double[] u,
                                        final double[] v,
                                        final float bias); @Override void close(); @Override final List<Integer> getNearest(final double[] queryVector,
                                          final int nResults); static void main(final String[] args);  }