public static void Apply(IRandom random, LinearLinkage lle, int n) { var grouping = lle.GetGroups().ToList(); var groupsLargerOne = grouping.Select((v, i) => Tuple.Create(i, v)) .Where(x => x.Item2.Count > 1) .ToDictionary(x => x.Item1, x => x.Item2); if (groupsLargerOne.Count == 0) return; var toRemove = new List<int>(); for (var i = 0; i < n; i++) { var g = groupsLargerOne.Keys.SampleRandom(random); var idx = random.Next(1, groupsLargerOne[g].Count); // shuffle here to avoid a potential bias of grouping smaller and larger numbers together var tmp = groupsLargerOne[g].Shuffle(random); var before = new List<int>(); var after = new List<int>(); foreach (var t in tmp) { if (idx > 0) before.Add(t); else after.Add(t); idx--; } if (before.Count > 1) groupsLargerOne[grouping.Count] = before; grouping.Add(before); if (after.Count > 1) groupsLargerOne[grouping.Count] = after; grouping.Add(after); toRemove.Add(g); groupsLargerOne.Remove(g); if (groupsLargerOne.Count == 0) break; } foreach (var r in toRemove.OrderByDescending(x => x)) grouping.RemoveAt(r); lle.SetGroups(grouping); }

/// <summary> /// Performs the rounded blend alpha crossover (BLX-a) of two integer vectors.<br/> /// It creates new offspring by sampling a new value in the range [min_i - d * alpha, max_i + d * alpha) at each position i /// and rounding the result to the next integer. /// Here min_i and max_i are the smaller and larger value of the two parents at position i and d is max_i - min_i. /// </summary> /// <exception cref="ArgumentException"> /// Thrown when <paramref name="parent1"/> and <paramref name="parent2"/> are of different length or<br/> /// when <paramref name="alpha"/> is less than 0. /// </exception> /// <param name="random">The random number generator.</param> /// <param name="parent1">The first parent for the crossover operation.</param> /// <param name="parent2">The second parent for the crossover operation.</param> /// <param name="bounds">The bounds and step size for each dimension (will be cycled in case there are less rows than elements in the parent vectors).</param> /// <param name="alpha">The alpha value for the crossover.</param> /// <returns>The newly created integer vector resulting from the crossover operation.</returns> public static IntegerVector Apply(IRandom random, IntegerVector parent1, IntegerVector parent2, IntMatrix bounds, DoubleValue alpha) { if (parent1.Length != parent2.Length) throw new ArgumentException("RoundedBlendAlphaCrossover: The parents' vectors are of different length.", "parent1"); if (alpha.Value < 0) throw new ArgumentException("RoundedBlendAlphaCrossover: Paramter alpha must be greater or equal than 0.", "alpha"); if (bounds == null || bounds.Rows < 1 || bounds.Columns < 2) throw new ArgumentException("RoundedBlendAlphaCrossover: Invalid bounds specified.", "bounds"); int length = parent1.Length; var result = new IntegerVector(length); double max = 0, min = 0, d = 0, resMin = 0, resMax = 0; int minBound, maxBound, step = 1; for (int i = 0; i < length; i++) { minBound = bounds[i % bounds.Rows, 0]; maxBound = bounds[i % bounds.Rows, 1]; if (bounds.Columns > 2) step = bounds[i % bounds.Rows, 2]; maxBound = FloorFeasible(minBound, maxBound, step, maxBound - 1); max = Math.Max(parent1[i], parent2[i]); min = Math.Min(parent1[i], parent2[i]); d = Math.Abs(max - min); resMin = FloorFeasible(minBound, maxBound, step, min - d * alpha.Value); resMax = CeilingFeasible(minBound, maxBound, step, max + d * alpha.Value); result[i] = RoundFeasible(minBound, maxBound, step, resMin + random.NextDouble() * Math.Abs(resMax - resMin)); } return result; }

public static PotvinPDShiftMove Apply(PotvinEncoding individual, IVRPProblemInstance problemInstance, IRandom rand) { List<int> cities = new List<int>(); IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance; for (int i = 1; i <= individual.Cities; i++) { if (pdp == null || pdp.GetDemand(i) >= 0) cities.Add(i); } if (cities.Count >= 1) { int city = cities[rand.Next(cities.Count)]; Tour oldTour = individual.Tours.Find(t => t.Stops.Contains(city)); int oldTourIndex = individual.Tours.IndexOf(oldTour); int max = individual.Tours.Count; if (individual.Tours.Count >= problemInstance.Vehicles.Value) max = max - 1; int newTourIndex = rand.Next(max); if (newTourIndex >= oldTourIndex) newTourIndex++; return new PotvinPDShiftMove(city, oldTourIndex, newTourIndex, individual); } else { return null; } }

public static void RemoveRandomBranch(IRandom random, ISymbolicExpressionTree symbolicExpressionTree, int maxTreeLength, int maxTreeDepth) { var allowedSymbols = new List<ISymbol>(); ISymbolicExpressionTreeNode parent; int childIndex; int maxLength; int maxDepth; // repeat until a fitting parent and child are found (MAX_TRIES times) int tries = 0; var nodes = symbolicExpressionTree.Root.IterateNodesPrefix().Skip(1).Where(n => n.SubtreeCount > 0).ToList(); do { parent = nodes.SampleRandom(random); childIndex = random.Next(parent.SubtreeCount); var child = parent.GetSubtree(childIndex); maxLength = maxTreeLength - symbolicExpressionTree.Length + child.GetLength(); maxDepth = maxTreeDepth - symbolicExpressionTree.Root.GetBranchLevel(child); allowedSymbols.Clear(); foreach (var symbol in parent.Grammar.GetAllowedChildSymbols(parent.Symbol, childIndex)) { // check basic properties that the new symbol must have if ((symbol.Name != child.Symbol.Name || symbol.MinimumArity > 0) && symbol.InitialFrequency > 0 && parent.Grammar.GetMinimumExpressionDepth(symbol) <= maxDepth && parent.Grammar.GetMinimumExpressionLength(symbol) <= maxLength) { allowedSymbols.Add(symbol); } } tries++; } while (tries < MAX_TRIES && allowedSymbols.Count == 0); if (tries >= MAX_TRIES) return; ReplaceWithMinimalTree(random, symbolicExpressionTree.Root, parent, childIndex); }

/// <summary> /// Performs an adaptive normally distributed all position manipulation on the given /// <paramref name="vector"/>. /// </summary> /// <exception cref="InvalidOperationException">Thrown when the strategy vector is not /// as long as the vector to get manipulated.</exception> /// <param name="sigma">The strategy vector determining the strength of the mutation.</param> /// <param name="random">A random number generator.</param> /// <param name="vector">The real vector to manipulate.</param> /// <returns>The manipulated real vector.</returns> public static void Apply(IRandom random, RealVector vector, RealVector sigma) { if (sigma == null || sigma.Length == 0) throw new ArgumentException("ERROR: Vector containing the standard deviations is not defined.", "sigma"); NormalDistributedRandom N = new NormalDistributedRandom(random, 0.0, 1.0); for (int i = 0; i < vector.Length; i++) { vector[i] = vector[i] + (N.NextDouble() * sigma[i % sigma.Length]); } }

public PlanetGenerator(IMap map, IRandom random) { _map = map; _random = random; MaximumMapSize = new Size(10000,10000); MaximumPlanetSize = 250; }

protected override void Manipulate(IRandom random, PrinsEncoding individual) { List<Tour> tours = individual.GetTours(); bool improvement = false; int iterations = 0; do { improvement = false; double originalQuality = GetQuality(individual); PrinsEncoding child = null; int samples = 0; while (!improvement && samples < SampleSize.Value.Value) { int u = random.Next(ProblemInstance.Cities.Value); int v = random.Next(ProblemInstance.Cities.Value); child = Manipulate(individual, originalQuality, u, v); improvement = child != null; samples++; } if (improvement) { for (int i = 0; i < child.Length; i++) { individual[i] = child[i]; } } iterations++; } while (improvement && iterations < Iterations.Value.Value); }

private void CreateDecorationAt(Chunk chunk, int blockX, int blockY, int blockZ, IRandom random) { int offsetX = blockX; int offsetY = blockY; int numberOfVerticalSegments = BlockSize.Z / 5; int diskZ = blockZ; int radius = 5; BlockType blockType = BlockType.Stone; for (int seg = 0; seg < numberOfVerticalSegments; seg++) { for (int disc = 0; disc < 5; disc++) { CreateDiskAt(offsetX, offsetY, diskZ, radius, blockType); diskZ++; } if (radius > 1) { radius--; if (radius == 1) { blockType = BlockType.Dirt; } } } AddGameObjectDecorationToWorld("gray diamond", chunk, new Vector3(blockX + 0.5f, blockY + 0.5f, diskZ + 0.1f), new Vector3(0, -90, 0)); }

/// <summary> /// Performs a breeder genetic algorithm manipulation on the given <paramref name="vector"/>. /// </summary> /// <param name="random">A random number generator.</param> /// <param name="vector">The real vector to manipulate.</param> /// <param name="bounds">The lower and upper bound (1st and 2nd column) of the positions in the vector. If there are less rows than dimensions, the rows are cycled.</param> /// <param name="searchIntervalFactor">The factor determining the size of the search interval.</param> public static void Apply(IRandom random, RealVector vector, DoubleMatrix bounds, DoubleValue searchIntervalFactor) { int length = vector.Length; double prob, value; do { value = Sigma(random); } while (value == 0); prob = 1.0 / (double)length; bool wasMutated = false; for (int i = 0; i < length; i++) { if (random.NextDouble() < prob) { double range = bounds[i % bounds.Rows, 1] - bounds[i % bounds.Rows, 0]; if (random.NextDouble() < 0.5) { vector[i] = vector[i] + value * searchIntervalFactor.Value * range; } else { vector[i] = vector[i] - value * searchIntervalFactor.Value * range; } wasMutated = true; } } // make sure at least one gene was mutated if (!wasMutated) { int pos = random.Next(length); double range = bounds[pos % bounds.Rows, 1] - bounds[pos % bounds.Rows, 0]; if (random.NextDouble() < 0.5) { vector[pos] = vector[pos] + value * searchIntervalFactor.Value * range; } else { vector[pos] = vector[pos] - value * searchIntervalFactor.Value * range; } } }

public static AlbaLambdaInterchangeMove Apply(AlbaEncoding individual, int cities, int lambda, IRandom rand) { List<Tour> tours = individual.GetTours(); if (tours.Count > 1) { int route1Index = rand.Next(tours.Count); Tour route1 = tours[route1Index]; int route2Index = rand.Next(tours.Count - 1); if (route2Index >= route1Index) route2Index += 1; Tour route2 = tours[route2Index]; int length1 = rand.Next(Math.Min(lambda + 1, route1.Stops.Count + 1)); int index1 = rand.Next(route1.Stops.Count - length1 + 1); int l2Min = 0; if (length1 == 0) l2Min = 1; int length2 = rand.Next(l2Min, Math.Min(lambda + 1, route2.Stops.Count + 1)); int index2 = rand.Next(route2.Stops.Count - length2 + 1); return new AlbaLambdaInterchangeMove(route1Index, index1, length1, route2Index, index2, length2, individual); } else { return new AlbaLambdaInterchangeMove(0, 0, 0, 0, 0, 0, individual); } }

/// <summary> /// Mixes the elements of the given <paramref name="permutation"/> randomly /// in a randomly chosen interval. /// </summary> /// <param name="random">The random number generator.</param> /// <param name="permutation">The permutation to manipulate.</param> public static void Apply(IRandom random, Permutation permutation) { int breakPoint1, breakPoint2; int[] scrambledIndices, remainingIndices, temp; int selectedIndex, index; breakPoint1 = random.Next(permutation.Length - 1); breakPoint2 = random.Next(breakPoint1 + 1, permutation.Length); scrambledIndices = new int[breakPoint2 - breakPoint1 + 1]; remainingIndices = new int[breakPoint2 - breakPoint1 + 1]; for (int i = 0; i < remainingIndices.Length; i++) { // initialise indices remainingIndices[i] = i; } for (int i = 0; i < scrambledIndices.Length; i++) { // generate permutation of indices selectedIndex = random.Next(remainingIndices.Length); scrambledIndices[i] = remainingIndices[selectedIndex]; temp = remainingIndices; remainingIndices = new int[temp.Length - 1]; index = 0; for (int j = 0; j < remainingIndices.Length; j++) { if (index == selectedIndex) { index++; } remainingIndices[j] = temp[index]; index++; } } Apply(permutation, breakPoint1, scrambledIndices); }

protected override void Manipulate(IRandom random, GVREncoding individual) { Tour tour = individual.Tours[random.Next(individual.Tours.Count)]; int breakPoint1 = random.Next(tour.Stops.Count); int length = random.Next(1, tour.Stops.Count - breakPoint1 + 1); List<int> displaced = tour.Stops.GetRange(breakPoint1, length); tour.Stops.RemoveRange(breakPoint1, length); //with a probability of 1/(2*V) create a new tour, else insert at another position if (individual.GetTours().Count > 0 && individual.GetTours().Count < ProblemInstance.Vehicles.Value && random.Next(individual.GetTours().Count * 2) == 0) { Tour newTour = new Tour(); newTour.Stops.InsertRange(0, displaced); individual.Tours.Add(newTour); } else { Tour newTour = individual.Tours[random.Next(individual.Tours.Count)]; int newPosition = newTour.Stops.Count; newTour.Stops.InsertRange(newPosition, displaced); } if (tour.Stops.Count == 0) individual.Tours.Remove(tour); }

public static bool DeleteSubroutine( IRandom random, ISymbolicExpressionTree symbolicExpressionTree, int maxFunctionDefinitions, int maxFunctionArguments) { var functionDefiningBranches = symbolicExpressionTree.IterateNodesPrefix().OfType<DefunTreeNode>().ToList(); if (!functionDefiningBranches.Any()) // no ADF to delete => abort return false; var selectedDefunBranch = functionDefiningBranches.SampleRandom(random); // remove the selected defun int defunSubtreeIndex = symbolicExpressionTree.Root.IndexOfSubtree(selectedDefunBranch); symbolicExpressionTree.Root.RemoveSubtree(defunSubtreeIndex); // remove references to deleted function foreach (var subtree in symbolicExpressionTree.Root.Subtrees.OfType<SymbolicExpressionTreeTopLevelNode>()) { var matchingInvokeSymbol = (from symb in subtree.Grammar.Symbols.OfType<InvokeFunction>() where symb.FunctionName == selectedDefunBranch.FunctionName select symb).SingleOrDefault(); if (matchingInvokeSymbol != null) { subtree.Grammar.RemoveSymbol(matchingInvokeSymbol); } } DeletionByRandomRegeneration(random, symbolicExpressionTree, selectedDefunBranch); return true; }

public virtual void Randomize(IRandom random, int startIndex, int length) { if (length > 0) { for (int i = 0; i < length; i++) array[startIndex + i] = random.Next(2) == 0; OnReset(); } }

public static LinearLinkage Apply(IRandom random, ItemArray<LinearLinkage> parents) { var len = parents[0].Length; var child = new LinearLinkage(len); var childGroup = new List<HashSet<int>>(); var currentParent = random.Next(parents.Length); var groups = parents.Select(x => x.GetGroups().Select(y => new HashSet<int>(y)).ToList()).ToList(); bool remaining; do { var maxGroup = groups[currentParent].Select((v, i) => Tuple.Create(i, v)) .MaxItems(x => x.Item2.Count) .SampleRandom(random).Item1; var group = groups[currentParent][maxGroup]; groups[currentParent].RemoveAt(maxGroup); childGroup.Add(group); remaining = false; for (var p = 0; p < groups.Count; p++) { for (var j = 0; j < groups[p].Count; j++) { foreach (var elem in group) groups[p][j].Remove(elem); if (!remaining && groups[p][j].Count > 0) remaining = true; } } currentParent = (currentParent + 1) % parents.Length; } while (remaining); child.SetGroups(childGroup); return child; }

public SnailNameGenerator(IRandom random) { this.random = random; names = new List<string>() { "Mike", "Alan", "Hugh", "Clement", "Levi", "Oak", "Potato", "Ethan", "Hannah", "Kimbo", "Cheese-Man", "Choco", "Strawberry", "Pancake", "Monster", "Smurf", "Fish", "Bobrika", "Bacon", "Speedy", "Lightning", "Trailblazer", "Maimai", "Denden", "Rambo" }; }

private DoubleArray Randomize(IRandom random, int length, DoubleMatrix bounds) { var result = new DoubleArray(length); for (int i = 0; i < length; i++) { result[i] = random.NextDouble() * bounds[i % bounds.Rows, 1] - bounds[i % bounds.Rows, 0]; } return result; }

/// <summary> /// Performs the order crossover of two permutations. /// </summary> /// <exception cref="ArgumentException">Thrown when <paramref name="parent1"/> and <paramref name="parent2"/> are not of equal length.</exception> /// <exception cref="InvalidOperationException">Thrown if the numbers in the permutation elements are not in the range [0,N) with N = length of the permutation.</exception> /// <remarks> /// Crosses two permutations by copying a randomly chosen interval from the first permutation, preserving /// the positions. Then, starting from the end of the copied interval, copies the missing values from the second permutation /// in the order they occur. /// </remarks> /// <param name="random">A random number generator.</param> /// <param name="parent1">The first parent permutation to cross.</param> /// <param name="parent2">The second parent permutation to cross.</param> /// <returns>The new permutation resulting from the crossover.</returns> public static Permutation Apply(IRandom random, Permutation parent1, Permutation parent2) { if (parent1.Length != parent2.Length) throw new ArgumentException("OrderCrossover: The parent permutations are of unequal length."); int length = parent1.Length; int[] result = new int[length]; bool[] copied = new bool[length]; int breakPoint1 = random.Next(length - 1); int breakPoint2 = random.Next(breakPoint1 + 1, length); try { for (int j = breakPoint1; j <= breakPoint2; j++) { // copy part of first permutation result[j] = parent1[j]; copied[parent1[j]] = true; } int index = ((breakPoint2 + 1 >= length) ? (0) : (breakPoint2 + 1)); int i = index; // for moving in parent2 while (index != breakPoint1) { if (!copied[parent2[i]]) { result[index] = parent2[i]; index++; if (index >= length) index = 0; } i++; if (i >= length) i = 0; } } catch (IndexOutOfRangeException) { throw new InvalidOperationException("OrderCrossover: The permutation must consist of numbers in the interval [0;N) with N = length of the permutation."); } return new Permutation(parent1.PermutationType, result); }

protected override void Manipulate(IRandom random, GVREncoding individual) { int customer = random.Next(1, individual.Cities + 1); Tour tour; int position; individual.FindCustomer(customer, out tour, out position); tour.Stops.RemoveAt(position); //with a probability of 1/(2*V) create a new tour, else insert at another position if (individual.GetTours().Count > 0 && individual.GetTours().Count < ProblemInstance.Vehicles.Value && random.Next(individual.GetTours().Count * 2) == 0) { Tour newTour = new Tour(); newTour.Stops.Add(customer); individual.Tours.Add(newTour); } else { Tour newTour = individual.Tours[random.Next(individual.Tours.Count)]; int newPosition = random.Next(newTour.Stops.Count + 1); newTour.Stops.Insert(newPosition, customer); } if (tour.Stops.Count == 0) individual.Tours.Remove(tour); }

public static AlbaIntraRouteInversionMove Apply(AlbaEncoding individual, int cities, IRandom rand) { int index1 = -1; int index2 = -1; List<Tour> validTours = new List<Tour>(); foreach (Tour tour in individual.GetTours()) { if (tour.Stops.Count >= 4) validTours.Add(tour); } if (validTours.Count > 0) { Tour chosenTour = validTours[rand.Next(validTours.Count)]; int currentTourStart = -1; for (int i = 0; i < individual.Length; i++) { if (individual[i] + 1 == chosenTour.Stops[0]) { currentTourStart = i; break; } } int currentTourEnd = currentTourStart; while (currentTourEnd < individual.Length && individual[currentTourEnd] < cities) { currentTourEnd++; } int tourLength = currentTourEnd - currentTourStart; int a = rand.Next(tourLength - 3); index1 = currentTourStart + a; index2 = currentTourStart + rand.Next(a + 2, tourLength - 1); } return new AlbaIntraRouteInversionMove(index1, index2, individual); }

/// <summary> /// Moves an randomly chosen element in the specified <paramref name="permutation"/> array /// to another randomly generated position. /// </summary> /// <param name="random">The random number generator.</param> /// <param name="permutation">The permutation to manipulate.</param> public static void Apply(IRandom random, Permutation permutation) { Permutation original = (Permutation)permutation.Clone(); int cutIndex, insertIndex, number; cutIndex = random.Next(original.Length); insertIndex = random.Next(original.Length); number = original[cutIndex]; int i = 0; // index in new permutation int j = 0; // index in old permutation while (i < original.Length) { if (j == cutIndex) { j++; } if (i == insertIndex) { permutation[i] = number; i++; } if ((i < original.Length) && (j < original.Length)) { permutation[i] = original[j]; i++; j++; } } }

public static JSMEncoding Apply(int jobs, int resources, IRandom random) { var solution = new JSMEncoding(); for (int i = 0; i < resources; i++) { solution.JobSequenceMatrix.Add(new Permutation(PermutationTypes.Absolute, jobs, random)); } return solution; }

/// <summary> /// Performs a cross over permutation of <paramref name="parent1"/> and <paramref name="parent2"/> /// based on randomly chosen positions to define which position to take from where. /// </summary> /// <exception cref="ArgumentException">Thrown when <paramref name="parent1"/> and <paramref name="parent2"/> are not of equal length.</exception> /// <param name="random">The random number generator.</param> /// <param name="parent1">First parent</param> /// <param name="parent2">Second Parent</param> /// <returns>Child</returns> public static Permutation Apply(IRandom random, Permutation parent1, Permutation parent2) { if (parent1.Length != parent2.Length) throw new ArgumentException("PositionBasedCrossover: The parent permutations are of unequal length."); int length = parent1.Length; int[] result = new int[length]; bool[] randomPosition = new bool[length]; bool[] numberCopied = new bool[length]; int randomPosNumber = random.Next(length); for (int i = 0; i < randomPosNumber; i++) { // generate random bit mask randomPosition[random.Next(length)] = true; } for (int i = 0; i < length; i++) { // copy numbers masked as true from second permutation if (randomPosition[i]) { result[i] = parent2[i]; numberCopied[parent2[i]] = true; } } int index = 0; for (int i = 0; i < length; i++) { // copy numbers masked as false from first permutation if (!numberCopied[parent1[i]]) { if (randomPosition[index]) { while (randomPosition[index]) { index++; } } result[index] = parent1[i]; index++; } } return new Permutation(parent1.PermutationType, result); }

public static PWREncoding Apply(IRandom random, PWREncoding parent1, PWREncoding parent2) { var result = new PWREncoding(); var p1 = ((IntegerVector)(parent1.PermutationWithRepetition.Clone())).ToList(); var p2 = ((IntegerVector)(parent2.PermutationWithRepetition.Clone())).ToList(); var child = new List<int>(); var lookUpTable = new bool[parent1.PermutationWithRepetition.Length]; for (int i = 0; i < lookUpTable.Length; i++) { lookUpTable[i] = random.Next(2) == 1; } foreach (bool b in lookUpTable) { if (b) { child.Add(p1[0]); p2.Remove(p1[0]); p1.RemoveAt(0); } else { child.Add(p2[0]); p1.Remove(p2[0]); p2.RemoveAt(0); } } result.PermutationWithRepetition = new IntegerVector(child.ToArray()); return result; }

/// <summary> /// Generates a "sparse" or "dense" polynomial containing numOnes ints equal to 1, /// numNegOnes int equal to -1, and the rest equal to 0. /// </summary> /// /// <param name="N">Number of coeffeients</param> /// <param name="NumOnes">Number of ones</param> /// <param name="NumNegOnes">Number of negative ones</param> /// <param name="Sparse">Create a SparseTernaryPolynomial or DenseTernaryPolynomial</param> /// <param name="Rng">Random number generator</param> /// /// <returns>A ternary polynomial</returns> public static ITernaryPolynomial GenerateRandomTernary(int N, int NumOnes, int NumNegOnes, bool Sparse, IRandom Rng) { if (Sparse) return SparseTernaryPolynomial.GenerateRandom(N, NumOnes, NumNegOnes, Rng); else return DenseTernaryPolynomial.GenerateRandom(N, NumOnes, NumNegOnes, Rng); }

public static ScrambleMove GenerateRandomMove(Permutation permutation, IRandom random) { int breakPoint1, breakPoint2; int[] scrambledIndices; breakPoint1 = random.Next(permutation.Length); do { breakPoint2 = random.Next(permutation.Length); } while (Math.Abs(breakPoint2 - breakPoint1) <= 1); if (breakPoint2 < breakPoint1) { int h = breakPoint1; breakPoint1 = breakPoint2; breakPoint2 = h; } scrambledIndices = new int[breakPoint2 - breakPoint1 + 1]; for (int i = 0; i < scrambledIndices.Length; i++) scrambledIndices[i] = i; bool[] moved = new bool[scrambledIndices.Length]; bool changed = false; do { for (int i = scrambledIndices.Length - 1; i > 0; i--) { int j = random.Next(i + 1); int t = scrambledIndices[j]; scrambledIndices[j] = scrambledIndices[i]; scrambledIndices[i] = t; if (scrambledIndices[j] == j) moved[j] = false; else moved[j] = true; if (scrambledIndices[i] == i) moved[i] = false; else moved[i] = true; } changed = moved.Any(x => x); } while (!changed); return new ScrambleMove(breakPoint1, scrambledIndices); }

/// <summary> /// Performs a slight variation of the order crossover of two permutations. /// </summary> /// <exception cref="ArgumentException">Thrown when <paramref name="parent1"/> and <paramref name="parent2"/> are not of equal length.</exception> /// <remarks> /// Crosses two permutations by copying a randomly chosen interval from the first permutation, preserving /// the positions. Then, from the beginning of the permutation, copies the missing values from the second permutation /// in the order they occur. /// </remarks> /// <param name="random">A random number generator.</param> /// <param name="parent1">The first parent permutation to cross.</param> /// <param name="parent2">The second parent permutation to cross.</param> /// <returns>The new permutation resulting from the crossover.</returns> public static Permutation Apply(IRandom random, Permutation parent1, Permutation parent2) { if (parent1.Length != parent2.Length) throw new ArgumentException("OrderCrossover2: The parent permutations are of unequal length."); int[] result = new int[parent1.Length]; bool[] copied = new bool[result.Length]; int breakPoint1 = random.Next(result.Length - 1); int breakPoint2 = random.Next(breakPoint1 + 1, result.Length); for (int i = breakPoint1; i <= breakPoint2; i++) { // copy part of first permutation result[i] = parent1[i]; copied[parent1[i]] = true; } int index = 0; for (int i = 0; i < parent2.Length; i++) { // copy remaining part of second permutation if (index == breakPoint1) { // skip already copied part index = breakPoint2 + 1; } if (!copied[parent2[i]]) { result[index] = parent2[i]; index++; } } return new Permutation(parent1.PermutationType, result); }

public static LinearLinkage Apply(IRandom random, LinearLinkage p1, LinearLinkage p2) { var length = p1.Length; var child = new LinearLinkage(length); var endNodes = new HashSet<int>(); for (var i = 0; i < length; i++) { if ((p1[i] == i && p2[i] == i) || ((p1[i] == i || p2[i] == i) && random.NextDouble() < 0.5)) { child[i] = i; endNodes.Add(i); } } for (var i = 0; i < length; i++) { if (endNodes.Contains(i)) continue; var p1End = endNodes.Contains(p1[i]); var p2End = endNodes.Contains(p2[i]); if ((p1End && p2End) || (!p1End && !p2End)) { child[i] = random.NextDouble() < 0.5 ? p1[i] : p2[i]; } else if (p1End) { child[i] = p1[i]; } else { child[i] = p2[i]; } } child.LinearizeTreeStructures(); return child; }

public static void Create(IRandom random, ISymbolicExpressionTreeNode seedNode, int maxDepth) { // make sure it is possible to create a trees smaller than maxDepth if (seedNode.Grammar.GetMinimumExpressionDepth(seedNode.Symbol) > maxDepth) throw new ArgumentException("Cannot create trees of depth " + maxDepth + " or smaller because of grammar constraints.", "maxDepth"); var arity = SampleArity(random, seedNode); // throw an exception if the seedNode happens to be a terminal, since in this case we cannot grow a tree if (arity <= 0) throw new ArgumentException("Cannot grow tree. Seed node shouldn't have arity zero."); var allowedSymbols = seedNode.Grammar.AllowedSymbols.Where(s => s.InitialFrequency > 0.0).ToList(); for (var i = 0; i < arity; i++) { var possibleSymbols = allowedSymbols.Where(s => seedNode.Grammar.IsAllowedChildSymbol(seedNode.Symbol, s, i)).ToList(); var weights = possibleSymbols.Select(s => s.InitialFrequency).ToList(); #pragma warning disable 612, 618 var selectedSymbol = possibleSymbols.SelectRandom(weights, random); #pragma warning restore 612, 618 var tree = selectedSymbol.CreateTreeNode(); if (tree.HasLocalParameters) tree.ResetLocalParameters(random); seedNode.AddSubtree(tree); } // Only iterate over the non-terminal nodes (those which have arity > 0) // Start from depth 2 since the first two levels are formed by the rootNode and the seedNode foreach (var subTree in seedNode.Subtrees) if (subTree.Grammar.GetMaximumSubtreeCount(subTree.Symbol) > 0) RecursiveCreate(random, subTree, 2, maxDepth); }

/// <summary> /// Performs the some positions bitflip mutation on a binary vector. /// </summary> /// <param name="random">The random number generator to use.</param> /// <param name="vector">The vector that should be manipulated.</param> /// <param name="pm">The probability a bit is flipped.</param> public static void Apply(IRandom random, BinaryVector vector, DoubleValue pm) { for (int i = 0; i < vector.Length; i++) { if (random.NextDouble() < pm.Value) { vector[i] = !vector[i]; } } }