Exemplo n.º 1
0
    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;
    }