double ComputeNetwork(ANN nn) { //Inputs int[] inputs = new int[INPUTS]; for (int i = 0; i < INPUTS; i++) { //inputs[i] = game.board[i % WIDTH, i / WIDTH]; if (game.board[i % WIDTH, i / WIDTH] == 0) { inputs[i] = 0; } else { inputs[i] = (int)Math.Log(game.board[i % WIDTH, i / WIDTH], 2); } } /*int[] inputs = new int[INPUTS]; * for (int i = 0; i < 16; i++) * { * for (int j = 0; j < 16; j++) * { * if ((int)Math.Log(game.board[i % WIDTH, i / WIDTH], 2) == j + 1) * inputs[i * 16 + j] = 1; * else * inputs[i * 16 + j] = 0; * } * }*/ //Compute values at hidden neurons double[] hidden = new double[HIDDEN]; for (int i = 0; i < HIDDEN; i++) { hidden[i] = 0; for (int j = 0; j < INPUTS; j++) { hidden[i] += inputs[j] * nn.neuronLayers[1].neurons[i].weights[j]; } hidden[i] -= nn.neuronLayers[1].neurons[i].weights[INPUTS]; hidden[i] = (1 / (float)(1 + Math.Pow(Math.E, -hidden[i]))); } //Compute values at output neurons double[] outputs = new double[OUTPUTS]; for (int i = 0; i < OUTPUTS; i++) { outputs[i] = 0; for (int j = 0; j < HIDDEN; j++) { outputs[i] += hidden[j] * nn.neuronLayers[2].neurons[i].weights[j]; } outputs[i] -= nn.neuronLayers[2].neurons[i].weights[HIDDEN]; outputs[i] = (1 / (float)(1 + Math.Pow(Math.E, -outputs[i]))); } return(outputs[0]); }
public void LoadNetwork(object sender, EventArgs e) { rootGrid.Children.Clear(); rootGrid.Children.Add(Score); rootGrid.Children.Add(Info); rootGrid.Children.Add(saveNetButton); // Create a string to read into int numWeights = (INPUTS + 1) * HIDDEN + (HIDDEN + 1) * OUTPUTS; string[] lines = new string[numWeights + 1]; //Initialize networks for (int i = 0; i < ann.Length; i++) { ann[i] = new ANN(INPUTS, HIDDEN, OUTPUTS); } //Read file if (System.IO.File.Exists(netPath)) { lines = System.IO.File.ReadAllLines(netPath); } gen = Convert.ToInt32(lines[2]); for (int i = 0; i < ann.Length; i++) { int ii = 3; for (int j = 1; j < 3; j++) { for (int k = 0; k < ann[i].neuronLayers[j].neuronNum; k++) { for (int l = 0; l < ann[i].neuronLayers[j].neurons[k].inputNum + 1; l++) { ann[i].neuronLayers[j].neurons[k].weights[l] = Convert.ToDouble(lines[ii]); ii++; } } } } GA.Mutate(ann); //Start a game game = new Game(rootGrid, random); timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromMilliseconds(SPEED2); timer.Tick += delegate { Update(); game.UpdateDisplay(); UpdateDisplay(); }; timer.Start(); KeyDown += AdjustSpeed; }
public void NewNetwork(object sender, EventArgs e) { rootGrid.Children.Clear(); rootGrid.Children.Add(Score); rootGrid.Children.Add(Info); rootGrid.Children.Add(saveNetButton); //Create randomized ann's for (int i = 0; i < POPULATION; i++) { //Create ann ann[i] = new ANN(INPUTS, HIDDEN, OUTPUTS); //For each neuron layer for (int j = 0; j < LAYERNUM; j++) { //For each neuron in that layer for (int k = 0; k < ann[i].neuronLayers[j].neuronNum; k++) { for (int l = 0; l < ann[i].neuronLayers[j].neurons[k].inputNum + 1; l++) { ann[i].neuronLayers[j].neurons[k].weights[l] = random.NextDouble(); } } } } //Start a game game = new Game(rootGrid, random); timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromMilliseconds(SPEED2); timer.Tick += delegate { Update(); game.UpdateDisplay(); UpdateDisplay(); }; timer.Start(); KeyDown += AdjustSpeed; }
//Mate and crossover static void Mate(ANN[] ann) { int popSize = ann.Length; int bestSize = popSize / 4; Random random = new Random(); int inputs = ann[0].neuronLayers[0].neuronNum; int hidden = ann[0].neuronLayers[1].neuronNum; int output = ann[0].neuronLayers[2].neuronNum; //Fittest half of population ANN[] best = new ANN[bestSize]; //Half to replace ANN[] children = new ANN[popSize - bestSize]; for (int i = 0; i < popSize - bestSize; i++) { children[i] = new ANN(inputs, hidden, output); } /**********************/ /*** Find most fit ***/ /**********************/ for (int i = 0; i < bestSize; i++) { //For each network for (int j = 0; j < popSize; j++) { //If this network hasn't already been selected if (!best.Contains(ann[j])) { //Set default best network if (best[i] == null) { best[i] = ann[j]; } //If this network is better, choose that one else if (ann[j].fitness > best[i].fitness) { best[i] = ann[j]; } } } } //Find total fitness of best half int totalFitness = 0; for (int i = 0; i < bestSize; i++) { totalFitness += best[i].fitness; } /******************/ /*** Crossover ***/ /******************/ for (int i = 0; i < popSize - bestSize; i += 2) { //Pick two random different parents ANN[] parents = new ANN[2]; for (int j = 0; j < 2; j++) { int parentFitness = random.Next(0, totalFitness); int currentFitness = 0; //Search best half for random parent for (int k = 0; k < bestSize; k++) { currentFitness += best[k].fitness; if (currentFitness > parentFitness) { parents[j] = best[k]; break; } } } //Find number of genes (weights) int numWeights = (inputs + 1) * hidden + (hidden + 1) * output; int cutLength = numWeights / 2; //Get two slices of genes int division1 = random.Next(0, numWeights - cutLength); int division2 = division1 + cutLength; //Splice together gene slices int ii = 0; for (int j = 1; j < 3; j++) { for (int k = 0; k < ann[i].neuronLayers[j].neuronNum; k++) { for (int l = 0; l < ann[i].neuronLayers[j].neurons[k].inputNum + 1; l++) { if (ii < division1 || ii >= division2) { children[i].neuronLayers[j].neurons[k].weights[l] = parents[0].neuronLayers[j].neurons[k].weights[l]; children[i + 1].neuronLayers[j].neurons[k].weights[l] = parents[1].neuronLayers[j].neurons[k].weights[l]; } else { children[i].neuronLayers[j].neurons[k].weights[l] = parents[1].neuronLayers[j].neurons[k].weights[l]; children[i + 1].neuronLayers[j].neurons[k].weights[l] = parents[0].neuronLayers[j].neurons[k].weights[l]; } ii++; } } } } //Replace ANN with best half and new children best.CopyTo(ann, 0); children.CopyTo(ann, best.Length); }
void GeneticAlgorithm() { ANN[] tmp = new ANN[POPULATION]; //Find best half int BEST = POPULATION / 2; int[] best = new int[BEST]; for (int i = 0; i < BEST; i++) { best[i] = -1; for (int j = 0; j < POPULATION; j++) { if (!best.Contains(j)) { if (best[i] == -1) { best[i] = j; } else if (ann[j].fitness > ann[best[i]].fitness) { best[i] = j; } } } } int selectFitness = 0; for (int i = 0; i < BEST; i++) { selectFitness += ann[best[i]].fitness; } //Create new ann's for (int i = 0; i < POPULATION; i++) { //Create ann tmp[i] = new ANN(INPUTS, HIDDEN, OUTPUTS); //Pick two parents ANN parent1 = ann[0], parent2 = ann[1]; int parentFitness = random.Next(0, selectFitness); int currentFitness = 0; for (int j = 0; j < BEST; j++) { currentFitness += ann[best[j]].fitness; if (parentFitness < currentFitness) { parent1 = ann[best[j]]; break; } } parentFitness = random.Next(0, selectFitness); currentFitness = 0; for (int j = 0; j < BEST; j++) { currentFitness += ann[best[j]].fitness; if (parentFitness < currentFitness) { parent2 = ann[best[j]]; break; } } //Pick a random division of their weights int numWeights = (INPUTS + 1) * HIDDEN + (HIDDEN + 1) * OUTPUTS; int division = 1 + random.Next(0, numWeights - 1); //Assign weights int ii = 0; //For each neuron layer for (int j = 0; j < LAYERNUM; j++) { //For each neuron in that layer for (int k = 0; k < tmp[i].neuronLayers[j].neuronNum; k++) { for (int l = 0; l < tmp[i].neuronLayers[j].neurons[k].inputNum + 1; l++) { //Parent 1 if (ii < division) { tmp[i].neuronLayers[j].neurons[k].weights[l] = parent1.neuronLayers[j].neurons[k].weights[l]; } //Parent 2 else { tmp[i].neuronLayers[j].neurons[k].weights[l] = parent2.neuronLayers[j].neurons[k].weights[l]; } ii++; //Small mutation float mutation = (random.Next(0, 2001) - 1000) / 20000f; tmp[i].neuronLayers[j].neurons[k].weights[l] *= (1 + mutation); } } } } //Assign old ann's to the new population for (int i = 0; i < POPULATION; i++) { ann[i] = tmp[i]; } }