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/soft/Hierarchical#T#PathAssigner.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.soft; 035 036import java.util.Arrays; 037import java.util.HashMap; 038import java.util.Map; 039 040import org.openimaj.ml.clustering.assignment.HardAssigner; 041import org.openimaj.ml.clustering.assignment.SoftAssigner; 042import org.openimaj.ml.clustering.assignment.hard.ExactDoubleAssigner; 043import org.openimaj.ml.clustering.CentroidsProvider; 044import org.openimaj.ml.clustering.kmeans.HierarchicalDoubleKMeansResult; 045import org.openimaj.ml.clustering.kmeans.HierarchicalDoubleKMeansResult.Node; 046import org.openimaj.util.pair.IndependentPair; 047import org.openimaj.util.pair.IntDoublePair; 048 049/** 050 * A {@link SoftAssigner} for gathering the clusters assigned 051 * to a point from a hierarchical clustering. The returned clusters 052 * represent the path down the tree to the final closest leaf node. 053 * 054 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 055 */ 056public class HierarchicalDoublePathAssigner implements SoftAssigner<double[], double[]> { 057 protected HierarchicalDoubleKMeansResult result; 058 protected Map<CentroidsProvider<double[]>, HardAssigner<double[], double[], IntDoublePair>> assigners; 059 060 /** 061 * Construct with the given {@link HierarchicalDoubleKMeansResult} instance. 062 * @param result the {@link HierarchicalDoubleKMeansResult} instance. 063 */ 064 public HierarchicalDoublePathAssigner(HierarchicalDoubleKMeansResult result) { 065 this.result = result; 066 assigners = new HashMap<CentroidsProvider<double[]>, HardAssigner<double[], double[], IntDoublePair>>(); 067 } 068 069 @Override 070 public int[][] assign(double[][] data) { 071 int[][] assignments = new int[data.length][result.getDepth()]; 072 073 for (int i = 0; i < data.length; i++) { 074 Node node = result.getRoot(); 075 076 int d = 0; 077 while (node != null) { 078 HardAssigner<double[], double[], IntDoublePair> assigner = assigners.get(node.result); 079 080 if (assigner == null) { 081 assigner = new ExactDoubleAssigner(node.result); 082 assigners.put(node.result, assigner); 083 } 084 085 int best = assigner.assign(data[i]); 086 087 assignments[i][d] = best; 088 ++d; 089 090 if (node.children == null) 091 break; 092 node = node.children[best]; 093 } 094 } 095 096 return assignments; 097 } 098 099 @Override 100 public int[] assign(double[] data) { 101 return assign(new double[][] {data})[0]; 102 } 103 104 @Override 105 public void assignWeighted(double[][] data, int[][] assignments, double[][] weights) { 106 int depth = result.getDepth(); 107 108 for (int i = 0; i < data.length; i++) { 109 Node node = result.getRoot(); 110 111 if (assignments[i].length != depth) 112 assignments[i] = new int[depth]; 113 Arrays.fill(assignments, -1); 114 115 if (weights[i].length != depth) 116 weights[i] = new double[depth]; 117 118 int d = 0; 119 while (node != null) { 120 HardAssigner<double[], double[], IntDoublePair> assigner = assigners.get(node.result); 121 122 if (assigner == null) { 123 assigner = new ExactDoubleAssigner(node.result); 124 assigners.put(node.result, assigner); 125 } 126 127 IntDoublePair best = assigner.assignDistance(data[i]); 128 129 assignments[i][d] = best.first; 130 weights[i][d] = best.second; 131 ++d; 132 133 if (node.children == null) 134 break; 135 136 node = node.children[best.first]; 137 } 138 } 139 } 140 141 @Override 142 public IndependentPair<int[], double[]> assignWeighted(double[] data) { 143 int[][] assignments = new int[1][]; 144 double[][] weights = new double[1][]; 145 146 assignWeighted(new double[][] { data }, assignments, weights); 147 148 return new IndependentPair<int[], double[]>(assignments[0], weights[0]); 149 } 150 151 @Override 152 public int numDimensions() { 153 return result.numDimensions(); 154 } 155 156 @Override 157 public int size() { 158 return result.numClusters(); 159 } 160}