private static Genome crossDominant(NeatManager neat, Genome dominant, Genome other) { if (dominant.synapses.Count == 0 || other.synapses.Count == 0) { return(null); } int similarityNeurons = -1; for (int i = 1; i < 100000; i++) { if (dominant.hasSynapse(i) && other.hasSynapse(i)) { similarityNeurons = i; } } if (similarityNeurons == -1) { throw new Exception("No similarity between Genomes"); } Genome newGenome = new Genome(neat, null, dominant.inputNeurons.ToArray(), dominant.outputNeurons.ToArray()); for (int i = 1; i <= dominant.getHighestInnovationNumber(); i++) { if (dominant.hasSynapse(i)) { int innovationNumber, inputNeuron, outputNeuron; double weigth; bool enabled; if (other.hasSynapse(i)) { Random r = new Random(); if (r.Next(0, 1) == 1) { innovationNumber = dominant.synapses[i].innovationNumber; inputNeuron = dominant.synapses[i].from; outputNeuron = dominant.synapses[i].to; weigth = dominant.synapses[i].weight; enabled = dominant.synapses[i].enabled; } else { innovationNumber = other.synapses[i].innovationNumber; inputNeuron = other.synapses[i].from; outputNeuron = other.synapses[i].to; weigth = other.synapses[i].weight; enabled = other.synapses[i].enabled; } } else { innovationNumber = dominant.synapses[i].innovationNumber; inputNeuron = dominant.synapses[i].from; outputNeuron = dominant.synapses[i].to; weigth = dominant.synapses[i].weight; enabled = dominant.synapses[i].enabled; } newGenome.addSynapse(new Synapse(innovationNumber, inputNeuron, outputNeuron, weigth, enabled), dominant, other); } } newGenome.removeDuplicateSynapses(); newGenome.mutate(); return(newGenome); }
// REF: [GITHUB] SanderGielisse logic for distance // between genomes (eg compatibility) // (https://github.com/SanderGielisse/Mythan) public static double distance(Genome a, Genome b) { int aLength = a.getHighestInnovationNumber(); int bLength = b.getHighestInnovationNumber(); Genome longest; Genome shortest; if (aLength > bLength) { longest = a; shortest = b; } else { longest = b; shortest = a; } int shortestLength = shortest.getHighestInnovationNumber(); int longestLength = longest.getHighestInnovationNumber(); double disjoint = 0; double excess = 0; List <double> weights = new List <double>(); for (int i = 0; i < longestLength; i++) { Synapse aa = longest.getSynapse(i); Synapse bb = shortest.getSynapse(i); if ((aa == null && bb != null) || (aa != null && bb == null)) { // only present in one of them if (i <= shortestLength) { disjoint++; } else if (i > shortestLength) { excess++; } } if (aa != null && bb != null) { double distance = Math.Abs(aa.weight - bb.weight); weights.Add(distance); } } double total = 0; double size = 0; foreach (double w in weights) { total += w; size++; } double averageWeightDistance = total / size; double n = longest.synapses.Count; double c1 = Config.DISTANCE_EXCESS_WEIGHT; double c2 = Config.DISTANCE_DISJOINT_WEIGHT; double c3 = Config.DISTANCE_WEIGHTS_WEIGHT; double d = ((c1 * excess) / n) + ((c2 * disjoint) / n) + (c3 * averageWeightDistance); return(d); }