using System; using System.Windows.Forms; namespace aiNnFingers { public class SOM { public SOM() { } public RichTextBox richTextBox; //#include //#include //#include //typedef int BOOL; //typedef int INT; //typedef double REAL; //#define FALSE 0 //#define TRUE 1 //#define NOT ! //#define AND && //#define OR || //#define MIN_REAL -HUGE_VAL const double MIN_REAL = double.MinValue; //#define MAX_REAL +HUGE_VAL const double MAX_REAL = double.MaxValue; //#define MIN(x,y) ((x)<(y) ? (x) : (y)) //#define MAX(x,y) ((x)>(y) ? (x) : (y)) //#define PI (2*asin(1)) //#define sqr(x) ((x)*(x)) public double SQR(double x) { return x * x; } public double SQR(int x) { return (double) x * x; } public struct LAYER { /* A LAYER OF A NET: */ public double Units; /* - number of units in this layer */ public double[] Output; /* - output of ith unit */ public double[][] Weight; /* - connection weights to ith unit */ public double[] StepSize; /* - size of search steps of ith unit */ public double[] dScoreMean; /* - mean score delta of ith unit */ } public struct NET { /* A NET: */ public LAYER InputLayer; /* - input layer */ public LAYER KohonenLayer; /* - Kohonen layer */ public LAYER OutputLayer; /* - output layer */ public double Winner; /* - last winner in Kohonen layer */ public double Alpha; /* - learning rate for Kohonen layer */ public double Alpha_; /* - learning rate for output layer */ public double Alpha__; /* - learning rate for step sizes */ public double Gamma; /* - smoothing factor for score deltas */ public double Sigma; /* - parameter for width of neighborhood */ } /****************************************************************************** R A N D O M S D R A W N F R O M D I S T R I B U T I O N S ******************************************************************************/ Random r; const int RAND_MAX = Int32.MaxValue; void InitializeRandoms() { //srand(4711); r = new Random(4715); } double RandomEqualREAL(double Low, double High) { //return ((REAL) rand() / RAND_MAX) * (High-Low) + Low; double retVal = ((double) r.Next() / (double) RAND_MAX) * (High-Low) + Low; //268 times return retVal; } double RandomNormalREAL(double Mu, double Sigma) { double x,fx; do { x = RandomEqualREAL(Mu-3*Sigma, Mu+3*Sigma); fx = (1 / (Math.Sqrt(2*Math.PI)*Sigma)) * Math.Exp(-SQR(x-Mu) / (2*SQR(Sigma))); } while (fx < RandomEqualREAL(0, 1)); return x; } /****************************************************************************** A P P L I C A T I O N - S P E C I F I C C O D E ******************************************************************************/ //#define ROWS 25 const double ROWS = 25; //#define COLS 25 const double COLS = 25; //#define N 2 const double N = 2; //#define C (ROWS * COLS) const double C = ROWS * COLS; //#define M 1 const double M = 1; //#define TRAIN_STEPS 10000 const double TRAIN_STEPS = 10000; //#define BALANCED 100 const double BALANCED = 100; //FILE* f; void InitializeApplication(ref NET Net) { double i; for (i=0; i= -60) && (Pole.w <= 60); } double ScoreOfPole(ref POLE Pole) { double retVal = -SQR(Pole.w); return retVal; } /****************************************************************************** I N I T I A L I Z A T I O N ******************************************************************************/ void GenerateNetwork(ref NET Net) { double i; Net.InputLayer = new LAYER(); //(LAYER*) malloc(sizeof(LAYER)); Net.KohonenLayer = new LAYER(); //(LAYER*) malloc(sizeof(LAYER)); Net.OutputLayer = new LAYER(); //(LAYER*) malloc(sizeof(LAYER)); Net.InputLayer.Units = N; Net.InputLayer.Output = new double[(int)N]; //(double*) calloc(N, sizeof(double)); Net.KohonenLayer.Units = C; Net.KohonenLayer.Output = new double[(int)C]; //(double*) calloc(C, sizeof(double)); Net.KohonenLayer.Weight = new double[(int)C][]; //(double**) calloc(C, sizeof(double*)); Net.KohonenLayer.StepSize = new double[(int)C]; //(double*) calloc(C, sizeof(double)); Net.KohonenLayer.dScoreMean = new double[(int)C]; //(double*) calloc(C, sizeof(double)); Net.OutputLayer.Units = M; Net.OutputLayer.Output = new double[(int)M]; //(double*) calloc(M, sizeof(double)); Net.OutputLayer.Weight = new double[(int)M][]; //(double**) calloc(M, sizeof(double*)); for (i=0; i dScoreMean) { Target[0] = Pole.F; TrainUnits(ref Net, Input, Target); } double winnerVal = Net.Gamma * (dScore - dScoreMean); Net.KohonenLayer.dScoreMean[(int)Net.Winner] += winnerVal; } Application.DoEvents(); if (PoleStillBalanced(ref Pole)) { out1 = t * T; richTextBox.AppendText("Pole still balanced after " + out1.ToString() + " ...\n\n"); //fprintf(f, "Pole still balanced after %0.1fs ...\n\n", t * T); } else { out1 = (t+1) * T; richTextBox.AppendText("Pole fallen after " + out1.ToString() + " ...\n\n"); //fprintf(f, "Pole fallen after %0.1fs ...\n\n", (t+1) * T); } } } /****************************************************************************** M A I N ******************************************************************************/ public void main() { NET Net = new NET(); InitializeRandoms(); GenerateNetwork(ref Net); RandomWeights(ref Net); InitializeApplication(ref Net); TrainNet(ref Net); WriteNet(ref Net); FinalizeApplication(ref Net); } } }