using System; using System.Collections.Generic; using Random = UnityEngine.Random; public class NeuralNetwork : IComparable { private int[] _layers; //layers of the neural network private float[][] _neurons; //neurons of the neural network public float[][][] _weights; //weights of the neural network private float _score; //score of the neural network /// /// Creates a new neural network with the given layers /// /// The layers with the count of the individual neurons public NeuralNetwork(in int[] layers) { _layers = new int[layers.Length]; for (int i = 0; i < layers.Length; i++) { _layers[i] = layers[i]; } InitializeNeurons(); InitializeWeights(); } /// /// Copy a NeuralNetwork /// /// The NeuralNetwork you wanna copy public NeuralNetwork(in NeuralNetwork network) { _layers = new int[network._layers.Length]; for (var i = 0; i < network._layers.Length; i++) { _layers[i] = network._layers[i]; } InitializeNeurons(); CopyWeights(network._weights); } /// /// Calculate output based on ihe given input /// /// The values at the first layer /// public float[] FeedForward(in float[] inputs) { for (int i = 0; i < inputs.Length; i++) { _neurons[0][i] = inputs[i]; } for (int i = 1; i < _layers.Length; i++) { for (int j = 0; j < _neurons[i].Length; j++) { float value = 0.25f; for (int k = 0; k < _neurons[i - 1].Length; k++) { value += _weights[i - 1][j][k] * _neurons[i - 1][k]; } _neurons[i][j] = (float)Math.Tan(value); } } return _neurons[_neurons.Length - 1]; } /// /// Randomize the weights of the neural network /// public void Mutate() { for (int i = 0; i < _weights.Length; i++) { for (int j = 0; j < _weights[i].Length; j++) { for (int k = 0; k < _weights[i][j].Length; k++) { float weight = _weights[i][j][k]; float random = Random.value * 100.0f; switch (random) { case 2.0f: weight *= -1; break; case 4.0f: weight = Random.Range(-0.5f, 0.5f); break; case 6.0f: weight *= Random.Range(0.0f, 1.0f) + 1; break; case 8.0f: weight *= Random.Range(0.0f, 1.0f); break; } _weights[i][j][k] = weight; } } } } public void AddScore(in float score) => _score += score; public void SetScore(in float score) => _score = score; public float GetScore() => _score; private void InitializeNeurons() { List neurons = new List(); for (int i = 0; i < _layers.Length; i++) { neurons.Add(new float[_layers[i]]); } _neurons = neurons.ToArray(); } private void InitializeWeights() { List weights = new List(); for (int i = 1; i < _layers.Length; i++) { List layerWeights = new List(); int neuronsInPreviousLayer = _layers[i - 1]; for (int j = 0; j < _neurons[i].Length; j++) { float[] neuronWeights = new float[neuronsInPreviousLayer]; for (int k = 0; k < neuronsInPreviousLayer; k++) { neuronWeights[k] = Random.value - 0.5f; } layerWeights.Add(neuronWeights); } weights.Add(layerWeights.ToArray()); } _weights = weights.ToArray(); } private void CopyWeights(in float[][][] weights) { _weights = new float[weights.Length][][]; for (int i = 0; i < weights.Length; i++) { _weights[i] = new float[weights[i].Length][]; for (int j = 0; j < weights[i].Length; j++) { _weights[i][j] = new float[weights[i][j].Length]; for (int k = 0; k < weights[i][j].Length; k++) { _weights[i][j][k] = weights[i][j][k]; } } } } public int CompareTo(NeuralNetwork other) { if (other == null) { return 1; } if (other._score > _score) { return -1; } if (other._score < _score) { return 1; } return 0; } }