/* * Copyright 2004-2010 Information & Software Engineering Group (188/1) * Institute of Software Technology and Interactive Systems * Vienna University of Technology, Austria * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.ifs.tuwien.ac.at/dm/somtoolbox/license.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package at.tuwien.ifs.somtoolbox.layers.metrics; import java.awt.Point; import at.tuwien.ifs.somtoolbox.data.InputDatum; import at.tuwien.ifs.somtoolbox.layers.Unit; /** * A metric for mnemonic SOMs. The metric is basically a Manhattan/L1 Metric, but takes into consideration that not all * paths between two units might be possible (as the grid of the Mnemonic SOM might be sparse). For performance reasons, * a distance matrix is pre-calculated. * * @version $Id: MnemonicSOMMetric.java 3586 2010-05-21 10:34:19Z mayer $ * @author Rudolf Mayer */ public class MnemonicSOMMetric extends L2Metric { int[][][][] distanceMatrix; Integer[][][][] distanceMatrix_; /** @see at.tuwien.ifs.somtoolbox.layers.metrics.DistanceMetric#distance(double[], double[]) */ @Override public double distance(InputDatum datum1, InputDatum datum2) throws MetricException { Point point1 = (Point) datum1.getProperty("coordinates"); Point point2 = (Point) datum2.getProperty("coordinates"); if (point1 == null || point2 == null) { throw new IllegalArgumentException("Input data do not contain 'coordinates' property"); } return distanceMatrix[point1.x][point1.y][point2.x][point2.y]; } public void countDistances(int distanceFromStart, Unit startUnit, Unit currentUnit, Unit[][] units) { int xpos = currentUnit.getXPos(); int ypos = currentUnit.getYPos(); if (distanceMatrix_[startUnit.getXPos()][startUnit.getYPos()][xpos][ypos] == null || distanceMatrix_[startUnit.getXPos()][startUnit.getYPos()][xpos][ypos].intValue() > distanceFromStart) { // the unit has not been reached yet or on a longer path distanceMatrix_[startUnit.getXPos()][startUnit.getYPos()][xpos][ypos] = new Integer(distanceFromStart); // now we check all neighbours. if (xpos > 0 && units[xpos - 1][ypos] != null) { countDistances(distanceFromStart + 1, startUnit, units[xpos - 1][ypos], units); } if (xpos + 1 < units.length && units[xpos + 1][ypos] != null) { countDistances(distanceFromStart + 1, startUnit, units[xpos + 1][ypos], units); } if (ypos > 0 && units[xpos][ypos - 1] != null) { countDistances(distanceFromStart + 1, startUnit, units[xpos][ypos - 1], units); } if (ypos + 1 < units[0].length && units[xpos][ypos + 1] != null) { countDistances(distanceFromStart + 1, startUnit, units[xpos][ypos + 1], units); } } } public MnemonicSOMMetric(Unit[][] units) { // init the non-empty units to have a max-value distance. distanceMatrix_ = new Integer[units.length][units[0].length][units.length][units[0].length]; for (Unit[] unit : units) { for (int row = 0; row < units[0].length; row++) { if (unit[row] != null) { countDistances(0, unit[row], unit[row], units); } } } } }