public void Run(ref IGrid grid, SelectionFunction SelectionFunction) { var startAt = grid.GetRandomCell; active = new Stack<Cell>(); active.Push(startAt); while(active.Any()) { var cell = SelectionFunction(active); var availableNeighbors = cell.Neighbors.Where(x => x.Links.Count == 0); if (availableNeighbors.Any()) { var neighbor = availableNeighbors.Sample(); cell.Link(neighbor); active.Push(neighbor); } else { var list = active.ToList(); list.Remove(cell); active = new Stack<Cell>(list); } } }
public void Run(ref IGrid grid, SelectionFunction SelectionFunction) { var startAt = grid.GetRandomCell; active = new Stack <Cell>(); active.Push(startAt); while (active.Any()) { var cell = SelectionFunction(active); var availableNeighbors = cell.Neighbors.Where(x => x.Links.Count == 0); if (availableNeighbors.Any()) { var neighbor = availableNeighbors.Sample(); cell.Link(neighbor); active.Push(neighbor); } else { var list = active.ToList(); list.Remove(cell); active = new Stack <Cell>(list); } } }
public static (MatingPool.Parent better, MatingPool.Parent worse) Select(this MatingPool pool, SelectionFunction selectionFunction, float fitnessPower) { switch (selectionFunction) { case SelectionFunction.Best: var b = pool.Best(); return (b, b); case SelectionFunction.TopTwo: return (pool.Best(), pool.Best(1)); case SelectionFunction.TopTwoRandom: var r1 = Random.value; var r2 = Random.value; var (max, min) = r1 > r2 ? (r1, r2) : (r2, r1); return (pool.elements.First(p => Mathf.Pow(p.Fitness, fitnessPower) >= max), pool.elements.First(p => Mathf.Pow(p.Fitness, fitnessPower) >= min)); default: return default; } }
public static void Crossover(this CrossoverFunction crossoverFunction, NeuralNetwork child, GenerationEvaluation evaluation, SelectionFunction selectionFunction, float fitnessPower) { var(b, w) = evaluation.pool.Select(selectionFunction, fitnessPower); var(better, worse) = (b.Genes, w.Genes); var genes = child.genes; var count = genes.Length; var halfCount = genes.Length / 2; switch (crossoverFunction) { case CrossoverFunction.HalfWorstBest: for (var i = 0; i < halfCount; i++) { child.genes[i] = better[i]; } for (var i = halfCount; i < count; i++) { child.genes[i] = worse[i]; } break; case CrossoverFunction.HalfBestWorse: for (var i = 0; i < halfCount; i++) { child.genes[i] = worse[i]; } for (var i = halfCount; i < count; i++) { child.genes[i] = better[i]; } break; case CrossoverFunction.HalfRandomShift: var shift = Random.Range(0, count - 1); var overlaps = shift + halfCount > count - 1; for (var i = 0; i < count; i++) { child.genes[i] = (!overlaps && i > shift && i < shift + halfCount || overlaps && !(i > shift && i < shift + halfCount) ? better : worse)[i]; } break; case CrossoverFunction.Step: for (var i = 0; i < count; i++) { genes[i] = (i % 2 == 0 ? better : worse)[i]; } break; case CrossoverFunction.StepRandom: for (var i = 0; i < count; i++) { genes[i] = (Random.value > .5f ? better : worse)[i]; } break; case CrossoverFunction.FractionRandom: { for (var i = 0; i < count; i++) { var fraction = Random.value; genes[i] = better[i] * fraction + worse[i] * (1f - fraction); } break; } case CrossoverFunction.FractionByFitness: { var fraction = b.Fitness / (b.Fitness + w.Fitness); for (var i = 0; i < count; i++) { genes[i] = better[i] * fraction + worse[i] * (1f - fraction); } break; } case CrossoverFunction.Average: default: for (var i = 0; i < count; i++) { genes[i] = (better[i] + worse[i]) * .5f; } break; } }