@Override public DoubleNearestNeighboursExact create(double[][] data) { return new DoubleNearestNeighboursExact(data, distance); } }
/** * Quantise the given data using this Product Quantiser. The output is an * array of bytes corresponding to the index of the matching centroid for * each sub-vector (index numbers are offset by -128 so that 256 centroids * indexes can fit in a single byte). * * @param data * the data to quantise * @return the quantised data. */ public byte[] quantise(double[] data) { final byte[] quantised = new byte[assigners.length]; final int[] idx = { 0 }; final double[] dst = { 0 }; final double[][] qus = new double[1][0]; for (int i = 0, from = 0; i < assigners.length; i++) { final int to = assigners[i].numDimensions(); qus[0] = Arrays.copyOfRange(data, from, from + to); assigners[i].searchNN(qus, idx, dst); quantised[i] = (byte) (idx[0] - 128); from += to; } return quantised; }
/** * Decompress the quantised data by replacing each encoded index with the actual centroid subvector. * * @param qdata the quantised data * * @return the (approximate) decompressed feature */ public double[] decompress(byte[] qdata) { final double[] data = new double[ndims]; for (int i = 0, from = 0; i < assigners.length; i++) { final int len = assigners[i].numDimensions(); int index = (int)qdata[i] + 128; System.arraycopy(this.assigners[i].getPoints()[index], 0, data, from, len); from += len; } return data; } }
@Override public List<IntDoublePair> searchKNN(double[] query, int K) { // Fix for when the user asks for too many points. K = Math.min(K, pnts.length); final BoundedPriorityQueue<IntDoublePair> queue = new BoundedPriorityQueue<IntDoublePair>(K, IntDoublePair.SECOND_ITEM_ASCENDING_COMPARATOR); //prepare working data List<IntDoublePair> list = new ArrayList<IntDoublePair>(K + 1); for (int i = 0; i < K + 1; i++) { list.add(new IntDoublePair()); } // search return search(query, queue, list); }
@Override public void assignDistance(double[][] data, int[] indices, double[] distances) { nn.searchNN(data, indices, distances); }
/** * Construct a {@link DoubleProductQuantiser} with the given * nearest-neighbour assigners. The number of dimensions of the assigners * determines how long each sub-vector is. There is a one-to-one mapping * between in the order of assigners and sub-vectors. * * @param assigners * the nearest-neighbour assigners. */ public DoubleProductQuantiser(DoubleNearestNeighboursExact[] assigners) { this.assigners = assigners; for (final DoubleNearestNeighboursExact nn : assigners) ndims += nn.numDimensions(); }
private List<IntDoublePair> search(double[] query, BoundedPriorityQueue<IntDoublePair> queue, List<IntDoublePair> results) { IntDoublePair wp = null; // reset all values in the queue to MAX, -1 for (final IntDoublePair p : results) { p.second = Float.MAX_VALUE; p.first = -1; wp = queue.offerItem(p); } // perform the search for (int i = 0; i < this.pnts.length; i++) { wp.second = distanceFunc(distance, query, pnts[i]); wp.first = i; wp = queue.offerItem(wp); } return queue.toOrderedListDestructive(); }
@Override public int size() { return nn.size(); }
@Override public HardAssigner<double[], double[], IntDoublePair> defaultHardAssigner() { if (nn instanceof DoubleNearestNeighboursExact) return new ExactDoubleAssigner(this, ((DoubleNearestNeighboursExact)nn).distanceComparator()); return new KDTreeDoubleEuclideanAssigner(this); }
@Override public IntDoublePair searchNN(final double[] query) { final BoundedPriorityQueue<IntDoublePair> queue = new BoundedPriorityQueue<IntDoublePair>(1, IntDoublePair.SECOND_ITEM_ASCENDING_COMPARATOR); //prepare working data List<IntDoublePair> list = new ArrayList<IntDoublePair>(2); list.add(new IntDoublePair()); list.add(new IntDoublePair()); return search(query, queue, list).get(0); }
@Override public int[] assign(double[][] data) { int [] argmins = new int [data.length]; double [] mins = new double [data.length]; nn.searchNN(data, argmins, mins); return argmins; }
/** * Construct a {@link DoubleProductQuantiser} with the given * nearest-neighbour assigners. The number of dimensions of the assigners * determines how long each sub-vector is. There is a one-to-one mapping * between in the order of assigners and sub-vectors. * * @param assigners * the nearest-neighbour assigners. */ public DoubleProductQuantiser(DoubleNearestNeighboursExact[] assigners) { this.assigners = assigners; for (final DoubleNearestNeighboursExact nn : assigners) ndims += nn.numDimensions(); }
private List<IntDoublePair> search(double[] query, BoundedPriorityQueue<IntDoublePair> queue, List<IntDoublePair> results) { IntDoublePair wp = null; // reset all values in the queue to MAX, -1 for (final IntDoublePair p : results) { p.second = Float.MAX_VALUE; p.first = -1; wp = queue.offerItem(p); } // perform the search for (int i = 0; i < this.pnts.length; i++) { wp.second = distanceFunc(distance, query, pnts[i]); wp.first = i; wp = queue.offerItem(wp); } return queue.toOrderedListDestructive(); }
/** * Construct the assigner using the given cluster data and * distance function. * * @param data the cluster data * @param comparison the distance function */ public ExactDoubleAssigner(double[][] data, DoubleFVComparator comparison) { nn = new DoubleNearestNeighboursExact(data, comparison); }
/** * Quantise the given data using this Product Quantiser. The output is an * array of bytes corresponding to the index of the matching centroid for * each sub-vector (index numbers are offset by -128 so that 256 centroids * indexes can fit in a single byte). * * @param data * the data to quantise * @return the quantised data. */ public byte[] quantise(double[] data) { final byte[] quantised = new byte[assigners.length]; final int[] idx = { 0 }; final double[] dst = { 0 }; final double[][] qus = new double[1][0]; for (int i = 0, from = 0; i < assigners.length; i++) { final int to = assigners[i].numDimensions(); qus[0] = Arrays.copyOfRange(data, from, from + to); assigners[i].searchNN(qus, idx, dst); quantised[i] = (byte) (idx[0] - 128); from += to; } return quantised; }
/** * Decompress the quantised data by replacing each encoded index with the actual centroid subvector. * * @param qdata the quantised data * * @return the (approximate) decompressed feature */ public double[] decompress(byte[] qdata) { final double[] data = new double[ndims]; for (int i = 0, from = 0; i < assigners.length; i++) { final int len = assigners[i].numDimensions(); int index = (int)qdata[i] + 128; System.arraycopy(this.assigners[i].getPoints()[index], 0, data, from, len); from += len; } return data; } }
@Override public IntDoublePair searchNN(final double[] query) { final BoundedPriorityQueue<IntDoublePair> queue = new BoundedPriorityQueue<IntDoublePair>(1, IntDoublePair.SECOND_ITEM_ASCENDING_COMPARATOR); //prepare working data List<IntDoublePair> list = new ArrayList<IntDoublePair>(2); list.add(new IntDoublePair()); list.add(new IntDoublePair()); return search(query, queue, list).get(0); }
@Override public IntDoublePair assignDistance(double[] data) { int [] index = new int [1]; double [] distance = new double [1]; nn.searchNN(new double[][] { data }, index, distance); return new IntDoublePair(index[0], distance[0]); }
@Override public int numDimensions() { return nn.numDimensions(); }
@Override public DoubleNearestNeighboursExact create(double[][] data) { return new DoubleNearestNeighboursExact(data, distance); } }