001/*
002        AUTOMATICALLY GENERATED BY jTemp FROM
003        /Users/jsh2/Work/openimaj/target/checkout/machine-learning/clustering/src/main/jtemp/org/openimaj/ml/clustering/assignment/hard/KDTree#T#EuclideanAssigner.jtemp
004*/
005/**
006 * Copyright (c) 2011, The University of Southampton and the individual contributors.
007 * All rights reserved.
008 *
009 * Redistribution and use in source and binary forms, with or without modification,
010 * are permitted provided that the following conditions are met:
011 *
012 *   *  Redistributions of source code must retain the above copyright notice,
013 *      this list of conditions and the following disclaimer.
014 *
015 *   *  Redistributions in binary form must reproduce the above copyright notice,
016 *      this list of conditions and the following disclaimer in the documentation
017 *      and/or other materials provided with the distribution.
018 *
019 *   *  Neither the name of the University of Southampton nor the names of its
020 *      contributors may be used to endorse or promote products derived from this
021 *      software without specific prior written permission.
022 *
023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
024 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
025 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
026 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
027 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
028 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
029 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
030 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
031 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
032 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
033 */
034package org.openimaj.ml.clustering.assignment.hard;
035
036import org.openimaj.knn.IntNearestNeighbours;
037import org.openimaj.knn.IntNearestNeighboursProvider;
038import org.openimaj.knn.approximate.IntNearestNeighboursKDTree;
039import org.openimaj.ml.clustering.assignment.HardAssigner;
040import org.openimaj.ml.clustering.CentroidsProvider;
041import org.openimaj.util.pair.IntFloatPair;
042
043/**
044 * A {@link HardAssigner} that uses a {@link IntNearestNeighboursKDTree} to
045 * generate approximately correct cluster assignments.
046 * 
047 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
048 *
049 */
050public class KDTreeIntEuclideanAssigner implements HardAssigner<int[], float[], IntFloatPair> {
051        protected IntNearestNeighboursKDTree nn;
052        
053        /**
054         * Construct the assigner using the given cluster data.
055         * 
056         * @param provider the cluster data provider
057         */
058        public KDTreeIntEuclideanAssigner(CentroidsProvider<int[]> provider) {
059                if (provider instanceof IntNearestNeighboursProvider) {
060                        IntNearestNeighbours internal = ((IntNearestNeighboursProvider)provider).getNearestNeighbours();
061                        
062                        if (internal != null && internal instanceof IntNearestNeighboursKDTree) {
063                                nn = (IntNearestNeighboursKDTree) internal;
064                                return;
065                        }
066                }
067                
068                nn = new IntNearestNeighboursKDTree(provider.getCentroids(), 
069                                IntNearestNeighboursKDTree.DEFAULT_NTREES, IntNearestNeighboursKDTree.DEFAULT_NCHECKS);
070        }
071        
072        /**
073         * Construct the assigner using the given cluster data.
074         * 
075         * @param data the cluster data
076         */
077        public KDTreeIntEuclideanAssigner(int[][] data) {
078                nn = new IntNearestNeighboursKDTree(data, IntNearestNeighboursKDTree.DEFAULT_NTREES, IntNearestNeighboursKDTree.DEFAULT_NCHECKS);
079        }
080        
081        @Override
082        public int[] assign(int[][] data) {
083                int [] argmins = new int [data.length];
084                float [] mins = new float [data.length];
085                nn.searchNN(data, argmins, mins);
086                return argmins;
087        }
088
089        @Override
090        public int assign(int[] data) {
091                return assign(new int[][] { data })[0];
092        }
093
094        @Override
095        public void assignDistance(int[][] data, int[] indices, float[] distances) {
096                nn.searchNN(data, indices, distances);
097        }
098
099        @Override
100        public IntFloatPair assignDistance(int[] data) {
101                int [] index = new int [1];
102                float [] distance = new float [1];
103                
104                nn.searchNN(new int[][] { data }, index, distance);
105                
106                return new IntFloatPair(index[0], distance[0]);
107        }
108        
109        @Override
110        public int size() {
111            return nn.size();
112        }
113        
114        @Override
115        public int numDimensions() {
116            return nn.numDimensions();
117        }
118}