예제 #1
0
    // Selection function to find most probable parents of the generation
    NN_Data[] SelectParents()
    {
        NN_Data[] parents = new NN_Data[2];

        // Get the fitness of all runners combined
        int combinedFitness = 0;

        foreach (var stats in deathList)
        {
            combinedFitness += stats.framesAlive;
        }

        // Get a random value between 0 and the combinedFitness. Use this to find a probable parent
        for (int p_Index = 0; p_Index < 2; p_Index++)
        {
            int randFitness = Random.Range(0, combinedFitness) - deathList[0].framesAlive;
            int locatedID   = 0;
            while (randFitness > 0)
            {
                locatedID++;
                randFitness -= deathList[locatedID].framesAlive;
            }
            parents[p_Index] = deathList[locatedID].nn_data;
        }
        return(parents);
    }
예제 #2
0
    // Combine 2 parents' DNA using crossover & apply mutations
    NN_Data CrossOver(NN_Data[] parents)
    {
        float[,] ih_w = new float[parents[0].ih_w.GetLength(0), parents[0].ih_w.GetLength(1)];
        float[] ih_b = new float[parents[0].ih_b.Length];
        float[,] ho_w = new float[parents[0].ho_w.GetLength(0), parents[0].ho_w.GetLength(1)];
        float[] ho_b = new float[parents[0].ho_b.Length];


        for (int row = 0; row < ih_w.GetLength(0); row++)
        {
            for (int col = 0; col < ih_w.GetLength(1); col++)
            {
                ih_w[row, col] = parents[Random.Range(0, 2)].ih_w[row, col];
                if (mutationPercentage > Random.value)
                {
                    ih_w[row, col] += (Random.value - .5f) * mutationScale;
                }
            }
        }

        for (int element = 0; element < ih_b.Length; element++)
        {
            ih_b[element] = parents[Random.Range(0, 2)].ih_b[element];
            if (mutationPercentage > Random.value)
            {
                ih_b[element] += (Random.value - .5f) * mutationScale;
            }
        }

        for (int row = 0; row < ho_w.GetLength(0); row++)
        {
            for (int col = 0; col < ho_w.GetLength(1); col++)
            {
                ho_w[row, col] = parents[Random.Range(0, 2)].ho_w[row, col];
                if (mutationPercentage > Random.value)
                {
                    ho_w[row, col] += (Random.value - .5f) * mutationScale;
                }
            }
        }
        for (int element = 0; element < ho_b.Length; element++)
        {
            ho_b[element] = parents[Random.Range(0, 2)].ho_b[element];
            if (mutationPercentage > Random.value)
            {
                ho_b[element] += (Random.value - .5f) * mutationScale;
            }
        }

        NN_Data childDNA = new NN_Data();

        childDNA.UpdateData(ih_w, ih_b, ho_w, ho_b);

        return(childDNA);
    }
        // Get saved NN data from a playerID
        public static NN_Data ReadData(int playerID)
        {
            if (File.Exists(path + "Runner" + playerID.ToString() + ".txt"))
            {
                string[] lines = File.ReadAllLines(path + "Runner" + playerID.ToString() + ".txt");


                string[] ih_w_rows = lines[0].Split(':');
                float[,] ih_w = new float[ih_w_rows.Length, ih_w_rows[0].Split(',').Length];
                for (int row = 0; row < ih_w.GetLength(0); row++)
                {
                    string[] ih_w_cols = ih_w_rows[row].Split(',');
                    for (int col = 0; col < ih_w.GetLength(1); col++)
                    {
                        //File.WriteAllText(path + "Debug.txt", ih_w_cols[col]);
                        ih_w[row, col] = float.Parse(ih_w_cols[col]);
                    }
                }

                string[] ih_b_elements = lines[1].Split(',');
                float[]  ih_b          = new float[ih_b_elements.Length];
                for (int element = 0; element < ih_b_elements.Length; element++)
                {
                    ih_b[element] = float.Parse(ih_b_elements[element]);
                }


                string[] ho_w_rows = lines[2].Split(':');
                float[,] ho_w = new float[ho_w_rows.Length, ho_w_rows[0].Split(',').Length];
                for (int row = 0; row < ho_w.GetLength(0); row++)
                {
                    string[] ho_w_cols = ho_w_rows[row].Split(',');
                    for (int col = 0; col < ho_w.GetLength(1); col++)
                    {
                        ho_w[row, col] = float.Parse(ho_w_cols[col]);
                    }
                }

                string[] ho_b_elements = lines[3].Split(',');
                float[]  ho_b          = new float[ho_b_elements.Length];
                for (int element = 0; element < ho_b_elements.Length; element++)
                {
                    ho_b[element] = float.Parse(ho_b_elements[element]);
                }

                NN_Data readData = new NN_Data();
                readData.UpdateData(ih_w, ih_b, ho_w, ho_b);

                return(readData);
            }
            else
            {
                return(null);
            }
        }
예제 #4
0
    public void RunnerDies(int framesAlive, NN_Data nn_data)
    {
        deathCount++;
        deathList.Add(new RunnerDeathStats((int)Mathf.Pow((float)framesAlive, fitnessInfluence), nn_data));

        // When all runners are dead use their stats to reproduce
        if (deathCount == numberOfRunners)
        {
            Reproduce();
        }
    }
        // Save NN data to a playerID
        public static void WriteData(int playerID, NN_Data data)
        {
            // Add all data values to List<string> and save to txt file
            List <string> lines = new List <string>()
            {
                "", "", "", ""
            };

            for (int row = 0; row < data.ih_w.GetLength(0); row++)
            {
                for (int col = 0; col < data.ih_w.GetLength(1); col++)
                {
                    lines[0] += data.ih_w[row, col].ToString() + ",";
                }
                lines[0] += ":";
            }
            for (int element = 0; element < data.ih_b.Length; element++)
            {
                lines[1] += data.ih_b[element].ToString() + ",";
            }

            for (int row = 0; row < data.ho_w.GetLength(0); row++)
            {
                for (int col = 0; col < data.ho_w.GetLength(1); col++)
                {
                    lines[2] += data.ho_w[row, col].ToString() + ",";
                }
                lines[2] += ":";
            }
            for (int element = 0; element < data.ho_b.Length; element++)
            {
                lines[3] += data.ho_b[element].ToString() + ",";
            }
            // Clean up line endings
            for (int line = 0; line < lines.Count; line++)
            {
                lines[line] = lines[line].Replace(",:", ":");
                lines[line] = lines[line].TrimEnd(':');
                lines[line] = lines[line].TrimEnd(',');
            }

            File.WriteAllLines(path + "Runner" + playerID.ToString() + ".txt", lines);
        }
예제 #6
0
    public NN(int playerID, int inputNodes, int hiddenNodes, int outputNodes)
    {
        NN_Data saveData = FileCtrl.ReadData(playerID);

        // If file exists for this playerID, read file and set NN data
        if (saveData != null)
        {
            nn_data.ih_w = saveData.ih_w;
            nn_data.ih_b = saveData.ih_b;
            nn_data.ho_w = saveData.ho_w;
            nn_data.ho_b = saveData.ho_b;
        }
        // If file does not exist for this playerID, create new set of NN_Data
        else
        {
            nn_data.ih_w = Math.RandomMatrix(inputNodes, hiddenNodes);
            nn_data.ih_b = Math.RandomLst(hiddenNodes);
            nn_data.ho_w = Math.RandomMatrix(hiddenNodes, outputNodes);
            nn_data.ho_b = Math.RandomLst(outputNodes);
        }
    }
예제 #7
0
    // Genetic algorithm to create new neural networks
    void Reproduce()
    {
        // Breed and save children to file
        for (int ID = 0; ID < numberOfRunners - 1; ID++)
        {
            // Selection
            NN_Data[] parents = SelectParents();

            // Cross Over to child DNA and mutate the child's DNA
            NN_Data childDNA = CrossOver(parents);

            // Save new genes
            FileCtrl.WriteData(ID, childDNA);
        }

        // Save the fittest runner on his own
        FileCtrl.WriteData(deathList.Count - 1, deathList[deathList.Count - 1].nn_data);

        FileCtrl.SaveStats(generation + 1, deathList[deathList.Count - 1].framesAlive);

        UnityEngine.SceneManagement.SceneManager.LoadScene(0);
    }
예제 #8
0
 public RunnerDeathStats(int framesAlive, NN_Data nn_data)
 {
     this.framesAlive = framesAlive;
     this.nn_data     = nn_data;
 }