Example #1
0
    void Start()
    {
        bird = GetComponent <Bird>();

        neuralNet = new NeuralNetwork(GameConstants.defaultLearningRate);
        neuralNet.AddDenseLayer(2, new ActivationFunction(Utils.ReLU));
        neuralNet.AddDenseLayer(6, new ActivationFunction(Utils.ReLU));
        neuralNet.AddDenseLayer(1, new ActivationFunction(Utils.Sigmoid));
        neuralNet.FinishBuilding(Utils.LinearError);


        this.dna = GameManager.instance.GetANewBirdDNA();
        // if we dont have a valid DNA from the DNA Generator
        if (dna == null)
        {
            this.dna = new BirdDNA(neuralNet.GetWeights(), neuralNet.GetBiases());
        }
        else
        {
            // we are here if we DID got a new DNA from the DNA Generator so we should actually apply it to the neural network
            this.neuralNet.SetWeights(this.dna.weightsOfNeuralNetwork);
            this.neuralNet.SetBiases(this.dna.biasesOfNeuralNetwork);
        }

        // we are adding this Evo bird to the static array that holds all Evo birds
        instances.Add(this);
    }
Example #2
0
    /// <summary>
    /// A Simple DNA Generator based on the best DNA's that were before it
    /// </summary>
    /// <returns>A new Bird's DNA to use, at first will be null, then will generate better ones</returns>
    public BirdDNA GetANewBirdDNA()
    {
        // MAIN LEARNING IS HERE AT GENERATING A BETTER BIRD'S DNA EACH GENERATION
        BirdDNA birdDNAToReturn = null;

        if (choosedBirdsDNAPool.Count < 2)
        {
            birdDNAToReturn = null;
        }
        else
        {
            // cross over the two dna's and loading the new bird's dna
            birdDNAToReturn = BirdDNA.CrossOver(choosedBirdsDNAPool[0].val2, choosedBirdsDNAPool[1].val2);
            // mutating the new dna a bit
            birdDNAToReturn.Mutate(GameConstants.defaultMutationChance);
        }
        return(birdDNAToReturn);
    }
Example #3
0
 // This function recieves a new dna and loads it to bird and its the neural network
 private void LoadNewBirdDNA(BirdDNA newDna)
 {
     this.dna = newDna;
     this.neuralNet.SetWeights(this.dna.weightsOfNeuralNetwork);
     this.neuralNet.SetBiases(this.dna.biasesOfNeuralNetwork);
 }
Example #4
0
    // static function to crossing over two bird dna
    // crossing over meaning taking half dna of each bird
    public static BirdDNA CrossOver(BirdDNA bird1, BirdDNA bird2)
    {
        // validating data dimensions
        if (bird1.weightsOfNeuralNetwork.Count != bird2.weightsOfNeuralNetwork.Count)
        {
            throw new DataDimensionsMismatchException();
        }
        if (bird1.biasesOfNeuralNetwork.Count != bird2.biasesOfNeuralNetwork.Count)
        {
            throw new DataDimensionsMismatchException();
        }


        // initializing the new weights array
        // now doing cross over algorithm, taking 1 info from bird and 1 from bird2
        List <List <List <double> > > weightsInNewDNA = new List <List <List <double> > >();

        // looping each layer and adding its weights to the 2D array
        for (int curLayerIndex = 0; curLayerIndex < bird1.weightsOfNeuralNetwork.Count; curLayerIndex++)
        {
            List <List <double> > curLayerNodesDna = new List <List <double> >();
            // looping each weight in a specific layer and adding its weight to the 2D array
            for (int curNodeIndex = 0; curNodeIndex < bird1.weightsOfNeuralNetwork[curLayerIndex].Count; curNodeIndex++)
            {
                List <double> curNodeWeightsDna = new List <double>();
                for (int curNodeWeightIndex = 0; curNodeWeightIndex < bird1.weightsOfNeuralNetwork[curLayerIndex][curNodeIndex].Count; curNodeWeightIndex++)
                {
                    // add here a weight of either from bird1 or from bird2, one from each one or randomly
                    // returns a number which is between 0 and 1
                    if (Utils.randomGenerator.NextDouble() > 0.5)
                    {
                        curNodeWeightsDna.Add(bird1.weightsOfNeuralNetwork[curLayerIndex][curNodeIndex][curNodeWeightIndex]);
                    }
                    else
                    {
                        curNodeWeightsDna.Add(bird2.weightsOfNeuralNetwork[curLayerIndex][curNodeIndex][curNodeWeightIndex]);
                    }
                }
                curLayerNodesDna.Add(curNodeWeightsDna);
            }
            weightsInNewDNA.Add(curLayerNodesDna);
        }


        // initializing the new biases array
        List <List <double> > biasesInNewDNA = new List <List <double> >();

        // looping each layer in the neural network
        for (int curLayerIndex = 0; curLayerIndex < bird1.biasesOfNeuralNetwork.Count; curLayerIndex++)
        {
            List <double> biasesOfNodesInCurLayer = new List <double>();
            // looping each bias in a specific layer and adding its bias to the 1D array
            for (int curBiasIndex = 0; curBiasIndex < bird1.biasesOfNeuralNetwork[curLayerIndex].Count; curBiasIndex++)
            {
                // add here a weight of either from bird1 or from bird2, one from each one or randomly
                if (Utils.randomGenerator.NextDouble() > 0.5)
                {
                    biasesOfNodesInCurLayer.Add(bird1.biasesOfNeuralNetwork[curLayerIndex][curBiasIndex]);
                }
                else
                {
                    biasesOfNodesInCurLayer.Add(bird2.biasesOfNeuralNetwork[curLayerIndex][curBiasIndex]);
                }
            }
            biasesInNewDNA.Add(biasesOfNodesInCurLayer);
        }



        // creating and returning the new bird dna that was cross over between the two dna's
        BirdDNA birdDNAToReturn = new BirdDNA(weightsInNewDNA, biasesInNewDNA);

        return(birdDNAToReturn);
    }