/* SOM1.java * * You may use and distribute under the terms of either the GNU Lesser * General Public License, either version 2 of the license or, * at your choice, any later version. Alternatively, you may use and * distribute under the terms of the XPL. * * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of * the licenses. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README * file for more details. * */ /* * Written by Tuomas Lukka */ package org.gzigzag.map; import java.util.*; /** A self-organizing map stored outside the structure. */ public class SOM1 { // // First, a framework for pluggable algorithms // /** An interface which calculates how far the given input * is from the given vector. */ public interface Dist { float dist(int[] q, float[] vec); } /** An interface to move vectors closer to inputs */ public interface Teacher { void teach(float weight, int nth, float[][] vec, int[] q); } /** An interface that chooses which vectors to move * by how much. */ public interface Geom { int getSize(); void teach(Teacher t, int nth, float[][] vec, float weight, int qid, int[] q); } /** Teach the given input vector to the given basis. */ public interface Rule { void teach( float[][] vecFrom, float[][] vecTo, Dist d, Geom g, Teacher teach, float weight, int qid, int[] q); } // // And now, some simple implementations // /** Euclidean distance squared. */ static public class EuclideanDist implements Dist { public float dist(int[] q, float[] vec) { float dist = 0; for(int i=0; i 0.001) for(int j=0; j= w) continue; for(int dy=-4; dy<=4; dy++) { if(y + dy < 0 || y + dy >= h) continue; int dist = dx*dx + dy*dy; if(onepersig2 * dist > 4) continue; double w = Math.exp(-onepersig2*dist); t.teach((float)w * weight, getN(x+dx, y+dy), vec, q); } } } else { float cx = (x - (w-1)/2.0f) * ctrWeight + (w-1)/2.0f; float cy = (y - (h-1)/2.0f) * ctrWeight + (h-1)/2.0f; // System.out.println("Centering: "+x+" "+y+" "+cx+" "+cy); x = (int)cx; y = (int)cy; for(int dx=-4; dx<=4; dx++) { if(x + dx < 0 || x + dx >= w) continue; for(int dy=-4; dy<=4; dy++) { if(y + dy < 0 || y + dy >= h) continue; float fx = (x+dx - cx); float fy = (y+dy - cy); float dist = fx*fx + fy*fy; if(onepersig2 * dist > 4) continue; double w = Math.exp(-onepersig2*dist); t.teach((float)w * weight, getN(x+dx, y+dy), vec, q); } } } } public void setWeightToCenter(int[] wtc) { weightToCenter = wtc; } public int getX(int n) { return n % w; } public int getY(int n) { return n / w; } public int getN(int x, int y) { return x+y*w; } } static int findMin(float[][] vec, Dist d, int[] q) { int imin = -1; float min = 0; for(int i=0; i