/*
* 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;
import java.util.ArrayList;
import at.tuwien.ifs.somtoolbox.SOMToolboxException;
import at.tuwien.ifs.somtoolbox.data.InputData;
/**
* Implementation of a toroid Self-Organizing Map layer, i.e. a "doughnut" shaped layer, whose left & right and
* upper & lower edges are interconnected. This class mainly adjusts distance functions.
*
* @author Rudolf Mayer
* @version $Id: ToroidLayer.java 3583 2010-05-21 10:07:41Z mayer $
*/
public class ToroidLayer extends GrowingLayer {
/** @see GrowingLayer#GrowingLayer(int, int, String, int, boolean, boolean, long, InputData) */
public ToroidLayer(int xSize, int ySize, String metricName, int dim, boolean normalize, boolean usePCA, long seed,
InputData data) {
super(xSize, ySize, metricName, dim, normalize, usePCA, seed, data);
initToroid();
}
/** @see GrowingLayer#GrowingLayer(int, int, int, String, int, boolean, boolean, long, InputData) */
public ToroidLayer(int xSize, int ySize, int zSize, String metricName, int dim, boolean normalize, boolean usePCA,
long seed, InputData data) {
super(xSize, ySize, zSize, metricName, dim, normalize, usePCA, seed, data);
initToroid();
}
/** @see GrowingLayer#GrowingLayer(int, Unit, int, int, String, int, boolean, boolean, long, InputData) */
public ToroidLayer(int id, Unit su, int xSize, int ySize, String metricName, int dim, boolean normalize,
boolean usePCA, long seed, InputData data) {
super(id, su, xSize, ySize, metricName, dim, normalize, usePCA, seed, data);
initToroid();
}
/** @see GrowingLayer#GrowingLayer(int, Unit, int, int, int, String, int, boolean, boolean, long, InputData) */
public ToroidLayer(int id, Unit su, int xSize, int ySize, int zSize, String metricName, int dim, boolean normalize,
boolean usePCA, long seed, InputData data) {
super(id, su, xSize, ySize, metricName, dim, normalize, usePCA, seed, data);
initToroid();
}
/** @see GrowingLayer#GrowingLayer(int, Unit, int, int, String, int, double[][][], long) */
public ToroidLayer(int id, Unit su, int xSize, int ySize, String metricName, int dim, double[][][] vectors,
long seed) throws SOMToolboxException {
super(id, su, xSize, ySize, metricName, dim, vectors, seed);
initToroid();
}
/** @see GrowingLayer#GrowingLayer(int, Unit, int, int, int, String, int, double[][][][], long) */
public ToroidLayer(int id, Unit su, int xSize, int ySize, int zSize, String metricName, int dim,
double[][][][] vectors, long seed) throws SOMToolboxException {
super(id, su, xSize, ySize, zSize, metricName, dim, vectors, seed);
initToroid();
}
private void initToroid() {
gridTopology = GridTopology.toroid;
}
/** Toroid distance on the map */
@Override
public double getMapDistance(int x1, int y1, int x2, int y2) {
int distX = Math.min(Math.abs(x1 - x2), xSize - Math.abs(x1 - x2));
int distY = Math.min(Math.abs(y1 - y2), ySize - Math.abs(y1 - y2));
return Math.sqrt(distX * distX + distY * distY);
}
@Override
public double getMapDistance(int x1, int y1, int z1, int x2, int y2, int z2) {
int distX = Math.min(Math.abs(x1 - x2), xSize - Math.abs(x1 - x2));
int distY = Math.min(Math.abs(y1 - y2), ySize - Math.abs(y1 - y2));
int distZ = Math.min(Math.abs(z1 - z2), zSize - Math.abs(z1 - z2));
return Math.sqrt(distX * distX + distY * distY + distZ * distZ);
}
@Override
public double getMapDistanceSq(int x1, int y1, int z1, int x2, int y2, int z2) {
int distX = Math.min(Math.abs(x1 - x2), xSize - Math.abs(x1 - x2));
int distY = Math.min(Math.abs(y1 - y2), ySize - Math.abs(y1 - y2));
int distZ = Math.min(Math.abs(z1 - z2), zSize - Math.abs(z1 - z2));
return distX * distX + distY * distY + distZ * distZ;
}
/** On a toroid map each unit has a neighbour */
@Override
public boolean hasNeighbours(int x, int y) throws LayerAccessException {
return true;
}
@Override
protected ArrayList<Unit> getNeighbouringUnits(Unit u) throws LayerAccessException {
int x = u.getXPos();
int y = u.getYPos();
int z = u.getZPos();
ArrayList<Unit> neighbourUnits = new ArrayList<Unit>();
if (x > 0) {
neighbourUnits.add(getUnit(x - 1, y, z));
} else {
neighbourUnits.add(getUnit(xSize - 1, y, z));
}
if (x + 1 < getXSize()) {
neighbourUnits.add(getUnit(x + 1, y, z));
} else {
neighbourUnits.add(getUnit(0, y, z));
}
if (y > 0) {
neighbourUnits.add(getUnit(x, y - 1, z));
} else {
neighbourUnits.add(getUnit(x, ySize - 1, z));
}
if (y + 1 < getYSize()) {
neighbourUnits.add(getUnit(x, y + 1, z));
} else {
neighbourUnits.add(getUnit(x, 0, z));
}
if (z > 0) {
neighbourUnits.add(getUnit(x, y, z - 1));
} else {
neighbourUnits.add(getUnit(x, y, zSize - 1));
}
if (z + 1 < getYSize()) {
neighbourUnits.add(getUnit(x, y, z + 1));
} else {
neighbourUnits.add(getUnit(x, y, 0));
}
return neighbourUnits;
}
@Override
protected ArrayList<Unit> getNeighbouringUnits(Unit u, double radius) throws LayerAccessException {
// FIXME: implement this :-)
throw new IllegalArgumentException("Not implemented");
}
}