class SOM{ int W,H,NGEONEURON,j,vectorChoice; double px,py,theta,phi,momentum,mindist; geoNeuron [] gn; double [][] r; double [] xv,yv; boolean comeToDaddy; boolean stable; SOM(int size, double [] _x, double [] _y){ xv = _x; // yv = _y; //target vectors theta = 0.5; phi = 0.5; momentum = 0.999; W = size; H = W; NGEONEURON = W * H; gn = new geoNeuron[NGEONEURON]; for(int x = 0; x < W; x++) for(int y = 0; y < H; y++){ gn[x * W + y] = new geoNeuron((double)x/(double)(W-1), (double)y/(double)(H-1)); } r = new double[NGEONEURON][NGEONEURON]; makeR(theta); } void run(){ px = xv[vectorChoice]; py = yv[vectorChoice]; // SEARCH FOR MINIMAL mindist = 100000.0; j = -1; for(int i = 0; i < NGEONEURON;i++){ double d = (px - gn[i].wx) * (px - gn[i].wx) + (py - gn[i].wy) * (py - gn[i].wy); if (comeToDaddy) d = px*gn[i].wx + py*gn[i].wy; if(d < mindist){ mindist = d; j = i; } } // UPDATE WEIGHTS for(int i=0; i < NGEONEURON;i++){ gn[i].wx += (phi * r[i][j] * (px - gn[i].wx)); gn[i].wy += (phi * r[i][j] * (py - gn[i].wy)); } // DECREASE LEARNING PARAMETERS phi *= momentum; theta *= momentum; if (theta < 0.1) stable = true; // RE-COMPUTE r MATRIX makeR(theta); vectorChoice = (vectorChoice+1)%xv.length; } void makeR(double th){ for(int i = 0; i < NGEONEURON; i++){ r[i][i] = 1.0; for(int j = i + 1; j < NGEONEURON; j++){ r[i][j] = Math.exp( -1.0 * ( gn[i].dist(gn[j]) * gn[i].dist(gn[j])) / (2.0 * th * th)); r[j][i] = r[i][j]; } } } void addVector(double x, double y){ double [] xtemp = new double[xv.length+1]; double [] ytemp = new double[yv.length+1]; System.arraycopy(xv, 0, xtemp, 0, xv.length); System.arraycopy(yv, 0, ytemp, 0, yv.length); xtemp[xv.length] = x; ytemp[yv.length] = y; xv = xtemp; yv = ytemp; } void draw(){ stroke(0); //DRAW PATH stroke(255,0,0); fill(255); stroke(255,0,0); for(int i = 0; i < gn.length; i++){ ellipse((float)(gn[i].wx)*width, (float)(gn[i].wy)*height,4,4); } for(int i = 0; i < H; i++) for(int j = 1; j < W; j++){ line((float)(gn[(j-1)+(i*H)].wx)*width, (float)(gn[(j-1)+(i*H)].wy)*height,(float)(gn[(j)+(i*H)].wx)*width, (float)(gn[(j)+(i*H)].wy)*height); line((float)(gn[(i)+((j-1)*H)].wx)*width, (float)(gn[(i)+((j-1)*H)].wy)*height,(float)(gn[(i)+(j*H)].wx)*width, (float)(gn[(i)+(j*H)].wy)*height); } stroke(0); stroke(0); fill(255,0,255); for (int i = 0; i < xv.length; i++) ellipse((float)xv[i]*width,(float)yv[i]*height,15,15); fill(255); ellipse((float)(px)*width, (float)(py)*height, 10,10); } }