private Dna(int[] outputsPerLayer, List <double> weightsAndBiases, List <int> activationIndexes, DnaHeritage origin = DnaHeritage.New) { Id = idCounter++; OutputsPerLayer = new List <int>(outputsPerLayer); WeightsAndBiases = new List <double>(weightsAndBiases); ActivationIndexes = new List <int>(activationIndexes); Heritage = origin; }
public static Dna CloneAndMutate(Dna dna, DnaHeritage origin, float weightMutationPrevalence, float activationMutationPrevalence = 0) { if (!(weightMutationPrevalence > 0)) { Debug.LogWarning("Attempted to mutate with a factor of zero"); return(Dna.Clone(dna)); } List <double> mutatedWeightGene = dna.WeightsAndBiases.GuaranteedApplyToPercentage(weightMutationPrevalence, (weight) => { double random01 = Random.Range(0f, 1f); bool shouldScramble = random01 < 0.25f; return(shouldScramble ? (random01 * 2) - 1 : weight *(0.5 + random01)); // scale by +/-50% OR random new value between -1 and 1 }); if (mutatedWeightGene.SequenceEqual(dna.WeightsAndBiases)) { Debug.LogError("Failed to mutate weights???"); } List <int> activationGene; if (!(activationMutationPrevalence > 0)) { activationGene = dna.ActivationIndexes; } else { int startIndexOfOutputLayerActivation = dna.ActivationIndexes.Count - dna.OutputsPerLayer.Last(); activationGene = dna.ActivationIndexes .Take(startIndexOfOutputLayerActivation) // preserve the output layer activations .ToList() .GuaranteedApplyToPercentage(activationMutationPrevalence, (_) => Random.Range(0, Activation.FunctionsCount)) .Concat(dna.ActivationIndexes.Skip(startIndexOfOutputLayerActivation)) .ToList(); } return(new Dna(dna.OutputsPerLayer.ToArray(), mutatedWeightGene, activationGene, origin)); }