// DO NOT REPRODUCE WITHOUT PERMISSION - HMC JULY 2000 /* Self-organizing map - square grid problem ========================================= This applet illustrates the behaviour of a simple self-organizing map in the square grid problem. The data consist of randomly-generated pairs of values in the range 1 to mapsize, where the map is square, and of dimension mapsize x mapsize. At each node in the map, a pair of weights (wx,wy) is stored. When the applet draws to the screen, a red blob is placed at coordinates (wx,wy), and a line is drawn from each node to its neighbours on the map, wherever their own node weights have placed them. As the weights at neighbouring nodes become more alike, the nodes move towards each other, and the connecting lines grow shorter. Ultimately, if the parameters for the map have been chosen reasonably, the map should converge to a roughly square pattern. However, satisfactory convergence to a square depends strongly upon the size of the map, the rate of diminution of node weight changes, and other factors. HMC May 2000. */ import java.applet.*; import java.awt.*; import java.util.Random; public class squaresom extends Applet implements Runnable { // Define the variables double som_weights[][][] = new double[21][21][2]; Random rs = new Random(); double a,xa,ya,mult1,mult2,adjustment,diff,bestdiff,scale,rubble; int i,j,k,l,w,h,besti,bestj,cycle,mapsize,mapsize1,displacement; Choice choice; Button resetbutton, pausebutton; Font font; Image offscreen; Thread animator = null; boolean please_stop = false; boolean zeroweights, paused; public void init() { // Make the widgets and the Font font = new Font("Helvetica", Font.BOLD, 20); resetbutton=new Button("Reset"); this.add(resetbutton); choice = new Choice(); choice.add("Adjust parameters....."); choice.add("Mapsize: 10"); choice.add("Mapsize: 15"); choice.add("Mapsize: 20"); choice.add("Weight adjustment per cycle: 1"); choice.add("Weight adjustment per cycle: 3"); choice.add("Weight adjustment per cycle: 8"); choice.add("Random initial weights"); choice.add("Zero initial weights"); this.add(choice); pausebutton = new Button(" Start "); pausebutton.setForeground(Color.red); paused=true; this.add(pausebutton); // Initialize miscellaneous values rubble=300.0; mapsize=10; displacement=80; zeroweights=false; restart(); } public void restart() { /* Set values of parameters which are revalued each run ==================================================== Initialize the node weights with random values between 1 and mapsize. The first weight at each node corresponds to the x co-ordinate in the data, the second to the y co-ordinate. */ cycle=0; mapsize1=mapsize-1; scale=260.0/mapsize; // chosen to keep the map on screen for (i=0; i=0 && i=0 && jbesti-2 && ibestj-2 && j