private static Network breed(int parentA, int parentB) { List<Edge> childEdges = new List<Edge> (); int AIndex = 0; int BIndex = 0; //merge genomes while (AIndex < networks[parentA].edges.Count && BIndex < networks[parentB].edges.Count) { if (networks [parentA].edges [AIndex].innovation == networks [parentB].edges [BIndex].innovation) { if (rand.Next (0, 2) == 0) { Edge e = new Edge(networks[parentA].edges[AIndex].inNeuron,networks[parentA].edges[AIndex].outNeuron,networks[parentA].edges[AIndex].weight, networks[parentA].edges[AIndex].isEnabled,networks[parentA].edges[AIndex].innovation); childEdges.Add (e); } else { Edge e = new Edge(networks[parentB].edges[BIndex].inNeuron,networks[parentB].edges[BIndex].outNeuron,networks[parentB].edges[BIndex].weight, networks[parentB].edges[BIndex].isEnabled,networks[parentB].edges[BIndex].innovation); childEdges.Add (e); } AIndex++; BIndex++; } else if (networks [parentA].edges [AIndex].innovation > networks [parentB].edges [BIndex].innovation) { BIndex++; } else { Edge e = new Edge(networks[parentA].edges[AIndex].inNeuron,networks[parentA].edges[AIndex].outNeuron,networks[parentA].edges[AIndex].weight, networks[parentA].edges[AIndex].isEnabled,networks[parentA].edges[AIndex].innovation); childEdges.Add (e); AIndex++; } } //excess edges left over from dominant parent if (BIndex == networks [parentB].edges.Count) { for (int i=AIndex; i<networks[parentA].edges.Count; i++) { Edge e = new Edge(networks[parentA].edges[i].inNeuron,networks[parentA].edges[i].outNeuron,networks[parentA].edges[i].weight, networks[parentA].edges[i].isEnabled,networks[parentA].edges[i].innovation); childEdges.Add (e); } } //perturb it double rand01 = rand.NextDouble (); if (rand01 < perturbChance) { double perturbAmount = (rand.NextDouble () * perturbPercent * 2.0 - perturbPercent); for (int i=0; i<childEdges.Count; i++) { //perturb it! sore aru if(rand.NextDouble() < 0.9){ childEdges [i].weight = childEdges [i].weight + perturbAmount; } else{ //give weight a new value; childEdges [i].weight = randomEdgeWeight(); } if (!childEdges [i].isEnabled) { rand01 = rand.NextDouble (); if (rand01 < enableMutationChance) { childEdges [i].isEnabled = true; } } } } //create the child network Network net = new Network (); //add inputs for(int j=0;j<inputN;j++){ Neuron n = new Neuron(); net.addNeuron(n); net.addInput(j); } //add outputs for(int j=0;j<outputN;j++){ Neuron n = new Neuron(); net.addNeuron(n); net.addOutput(inputN + j); } for (int j=0; j<(neuronN - inputN - outputN); j++) { Neuron n = new Neuron (); net.addNeuron (n); } for(int i=0;i<childEdges.Count;i++){ bool flag = net.addEdge(childEdges[i].inNeuron, childEdges[i].outNeuron, childEdges[i].weight, childEdges[i].innovation); if(flag==false){ //Console.WriteLine("wtf add edge failed"); } } //new links double rand2 = rand.NextDouble(); if (rand2 < linkMutationChance) { int tCount = 0; while(tCount <30){ int inputNode = rand.Next(0,neuronN - outputN); if(inputNode >= inputN){ inputNode += outputN; } int outputNode = rand.Next (inputN, neuronN); if(net.checkEdge(inputNode, outputNode)){ //add edge if the edge is connected to the input. if(net.neurons[inputNode].inputEdges.Count > 0 || inputNode < inputN){ bool tb = net.addEdge(inputNode, outputNode, randomEdgeWeight(), getInnovation(inputNode, outputNode)); if(tb){ tCount = 20; } } } tCount++; } } //new node rand2 = rand.NextDouble (); if (rand2 < nodeMutationChance) { int tCount = 0; while(tCount < 10){ int randomEdge = rand.Next(0,net.edges.Count); bool flag = true; int randomEdgeIn = net.edges[randomEdge].inNeuron; int randomEdgeOut = net.edges[randomEdge].outNeuron; //check if there already exists a node that does the same thing for(int i=0;i<innovationInputs.Count;i++){ if(innovationInputs[i] == randomEdgeIn){ for(int j=0;j<innovationInputs.Count;j++){ if(innovationInputs[j] == innovationOutputs[i]){ if(innovationOutputs[j] == randomEdgeOut){ flag = false; } } } } } //create new node if(flag){ net.edges[randomEdge].isEnabled = false; Neuron tN = new Neuron(); net.addNeuron(tN); bool tb = net.addEdge(net.edges[randomEdge].inNeuron, neuronN, randomEdgeWeight(), getInnovation(net.edges[randomEdge].inNeuron, neuronN)); bool tc = net.addEdge(neuronN, net.edges[randomEdge].outNeuron, randomEdgeWeight(), getInnovation(neuronN, net.edges[randomEdge].outNeuron)); if(!tb || !tc){ //Console.WriteLine("add Edge failed"); } neuronN++; tCount = 20; net.printNetwork(); } tCount++; } } return net; }