/// <summary> /// Performs a discrete crossover operation of any number of given parents. /// </summary> /// <exception cref="ArgumentException">Thrown when the vectors of the parents are of different length or when there are less than 2 parents.</exception> /// <param name="random">A random number generator.</param> /// <param name="parents">The list of parents for the crossover operation.</param> /// <returns>The newly created integer vector, resulting from the crossover operation.</returns> public static IntegerVector Apply(IRandom random, ItemArray <IntegerVector> parents) { if (parents.Length < 2) { throw new ArgumentException("DiscreteCrossover: There are less than two parents to cross."); } int length = parents[0].Length; for (int i = 0; i < parents.Length; i++) { if (parents[i].Length != length) { throw new ArgumentException("DiscreteCrossover: The parents' vectors are of different length.", "parents"); } } var result = new IntegerVector(length); for (int i = 0; i < length; i++) { result[i] = parents[random.Next(parents.Length)][i]; } return(result); }
/// <summary> /// Perfomrs a heuristic crossover on the two given parents. /// </summary> /// <exception cref="ArgumentException">Thrown when two parents are not of the same length.</exception> /// <param name="random">The random number generator.</param> /// <param name="betterParent">The first parent for the crossover operation.</param> /// <param name="worseParent">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> /// <returns>The newly created integer vector, resulting from the heuristic crossover.</returns> public static IntegerVector Apply(IRandom random, IntegerVector betterParent, IntegerVector worseParent, IntMatrix bounds) { if (betterParent.Length != worseParent.Length) { throw new ArgumentException("HeuristicCrossover: the two parents are not of the same length"); } int length = betterParent.Length; var result = new IntegerVector(length); double factor = random.NextDouble(); int min, max, step = 1; for (int i = 0; i < length; i++) { min = bounds[i % bounds.Rows, 0]; max = bounds[i % bounds.Rows, 1]; if (bounds.Columns > 2) { step = bounds[i % bounds.Rows, 2]; } max = FloorFeasible(min, max, step, max - 1); result[i] = RoundFeasible(min, max, step, betterParent[i] + factor * (betterParent[i] - worseParent[i])); } return(result); }
public static double CalculateSimilarity(IntegerVector left, IntegerVector right) { if (left == null || right == null) { throw new ArgumentException("Cannot calculate similarity because one or both of the provided solutions is null."); } if (left.Length != right.Length) { throw new ArgumentException("Cannot calculate similarity because the provided solutions have different lengths."); } if (left.Length == 0) { throw new ArgumentException("Cannot calculate similarity because solutions are of length 0."); } if (ReferenceEquals(left, right)) { return(1.0); } double similarity = 0.0; for (int i = 0; i < left.Length; i++) { if (left[i] == right[i]) { similarity++; } } return(similarity / left.Length); }
/// <summary> /// Performs a local crossover on the two given parent vectors. /// </summary> /// <exception cref="ArgumentException">Thrown when two parents are not of the same length.</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> /// <returns>The newly created integer vector, resulting from the local crossover.</returns> public static IntegerVector Apply(IRandom random, IntegerVector parent1, IntegerVector parent2, IntMatrix bounds) { if (parent1.Length != parent2.Length) { throw new ArgumentException("RoundedLocalCrossover: the two parents are not of the same length"); } double factor; int length = parent1.Length; var result = new IntegerVector(length); int min, max, step = 1; for (int i = 0; i < length; i++) { min = bounds[i % bounds.Rows, 0]; max = bounds[i % bounds.Rows, 1]; if (bounds.Columns > 2) { step = bounds[i % bounds.Rows, 2]; } max = FloorFeasible(min, max, step, max - 1); factor = random.NextDouble(); result[i] = RoundFeasible(min, max, step, (factor * parent1[i]) + ((1 - factor) * parent2[i])); } return(result); }
public static void Manipulate(IRandom random, IntegerVector vector, IntMatrix bounds, int index) { if (bounds == null || bounds.Rows == 0 || bounds.Columns < 2) { throw new ArgumentException("UniformOnePositionManipulator: Invalid bounds specified", "bounds"); } int min = bounds[index % bounds.Rows, 0], max = bounds[index % bounds.Rows, 1], step = 1; if (min == max) { vector[index] = min; } else { if (bounds.Columns > 2) { step = bounds[index % bounds.Rows, 2]; } // max has to be rounded to the lower feasible value // e.g. min...max / step = 0...100 / 5, max is exclusive so it would be 0..99 // but 99 is not a feasible value, so max needs to be adjusted => min = 0, max = 95 max = FloorFeasible(min, max, step, max - 1); vector[index] = RoundFeasible(min, max, step, random.Next(min, max)); } }
/// <summary> /// Genotype-to-Phenotype mapper (iterative breath-first approach, by using a queue -> FIFO). /// </summary> /// <param name="startNode">first node of the tree with arity 1</param> /// <param name="genotype">integer vector, which should be mapped to a tree</param> /// <param name="grammar">grammar to determine the allowed child symbols for each node</param> /// <param name="maxSubtreeCount">maximum allowed subtrees (= number of used genomes)</param> /// <param name="random">random number generator</param> private void MapBreathFirstIteratively(ISymbolicExpressionTreeNode startNode, IntegerVector genotype, ISymbolicExpressionGrammar grammar, int maxSubtreeCount, IRandom random) { Queue<Tuple<ISymbolicExpressionTreeNode, int>> queue = new Queue<Tuple<ISymbolicExpressionTreeNode, int>>(); // tuples of <node, arity> int genotypeIndex = 0; queue.Enqueue(new Tuple<ISymbolicExpressionTreeNode, int>(startNode, 1)); while (queue.Count > 0) { Tuple<ISymbolicExpressionTreeNode, int> current = queue.Dequeue(); // foreach subtree of the current node, create a new node and enqueue it, if it is no terminal node for (int i = 0; i < current.Item2; ++i) { if (genotypeIndex >= maxSubtreeCount) { // if all genomes were used, only add terminal nodes to the remaining subtrees current.Item1.AddSubtree(GetRandomTerminalNode(current.Item1, grammar, random)); } else { var newNode = GetNewChildNode(current.Item1, genotype, grammar, genotypeIndex, random); int arity = SampleArity(random, newNode, grammar); current.Item1.AddSubtree(newNode); genotypeIndex++; if (arity > 0) { // new node has subtrees so enqueue the node queue.Enqueue(new Tuple<ISymbolicExpressionTreeNode, int>(newNode, arity)); } } } } }
/// <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 double CalculateSimilarity(IntegerVector left, IntegerVector right, double scaling = 1.0) { if (left == null || right == null) { throw new ArgumentException("Cannot calculate similarity because one or both of the provided solutions is null."); } if (left.Length != right.Length) { throw new ArgumentException("Cannot calculate similarity because the provided solutions have different lengths."); } if (left.Length == 0) { throw new ArgumentException("Cannot calculate similarity because solutions are of length 0."); } if (scaling <= 0) { throw new ArgumentException("Cannot choose a 0 or negative scaling value."); } if (ReferenceEquals(left, right)) { return(1.0); } var distance = 0.0; for (int i = 0; i < left.Length; i++) { distance += (left[i] - right[i]) * (left[i] - right[i]); } return(1.0 / (1.0 + Math.Sqrt(distance) / scaling)); }
/// <summary> /// Generates a new random integer vector with the given <paramref name="length"/>. /// </summary> /// <param name="random">The random number generator.</param> /// <param name="length">The length of the int vector.</param> /// <param name="bounds">A matrix containing the inclusive lower and inclusive upper bound in the first and second column and a step size in the third column. /// Each line represents the bounds for a certain dimension. If fewer lines are given, the lines are cycled.</param> /// <returns>The newly created integer vector.</returns> public static IntegerVector Apply(IRandom random, int length, IntMatrix bounds) { var result = new IntegerVector(length); result.Randomize(random, bounds); return(result); }
/// <summary> /// Performs a normally distributed all position manipulation on the given /// <paramref name="vector"/> and rounds the result to the next feasible value. /// </summary> /// <exception cref="InvalidOperationException">Thrown when the sigma vector is null or of length 0.</exception> /// <param name="sigma">The sigma vector determining the strength of the mutation.</param> /// <param name="random">A random number generator.</param> /// <param name="vector">The integer vector to manipulate.</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> /// <returns>The manipulated integer vector.</returns> public static void Apply(IRandom random, IntegerVector vector, IntMatrix bounds, DoubleArray sigma) { if (sigma == null || sigma.Length == 0) { throw new ArgumentException("RoundedNormalAllPositionsManipulator: Vector containing the standard deviations is not defined.", "sigma"); } if (bounds == null || bounds.Rows == 0 || bounds.Columns < 2) { throw new ArgumentException("RoundedNormalAllPositionsManipulator: Invalid bounds specified.", "bounds"); } var N = new NormalDistributedRandom(random, 0.0, 1.0); for (int i = 0; i < vector.Length; i++) { int min = bounds[i % bounds.Rows, 0], max = bounds[i % bounds.Rows, 1], step = 1; if (bounds.Columns > 2) { step = bounds[i % bounds.Rows, 2]; } int value = (vector[i] + (int)Math.Round((N.NextDouble() * sigma[i % sigma.Length])) - min) / step; max = FloorFeasible(min, max, step, max - 1); vector[i] = RoundFeasible(min, max, step, value); } }
/// <summary> /// Changes randomly a single position in the given integer <paramref name="vector"/>. /// </summary> /// <remarks>Calls <see cref="Apply"/>.</remarks> /// <param name="random">A random number generator.</param> /// <param name="vector">The integer vector to manipulate.</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> protected override void ManipulateBounded(IRandom random, IntegerVector vector, IntMatrix bounds) { if (BoundsParameter.ActualValue == null) { throw new InvalidOperationException("UniformOnePositionManipulator: Parameter " + BoundsParameter.ActualName + " could not be found."); } Apply(random, vector, bounds); }
protected sealed override void Manipulate(IRandom random, IntegerVector integerVector) { if (BoundsParameter.ActualValue == null) { throw new InvalidOperationException("BoundedIntegerVectorManipulator: Parameter " + BoundsParameter.ActualName + " could not be found."); } ManipulateBounded(random, integerVector, BoundsParameter.ActualValue); }
/// <summary> /// Performs a normally distributed all position manipulation on the given /// <paramref name="vector"/> and rounds the result to the next feasible value. /// </summary> /// <exception cref="InvalidOperationException">Thrown when the sigma vector is null or of length 0.</exception> /// <param name="sigma">The sigma vector determining the strength of the mutation.</param> /// <param name="random">A random number generator.</param> /// <param name="vector">The integer vector to manipulate.</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> /// <returns>The manipulated integer vector.</returns> public static void Apply(IRandom random, IntegerVector vector, IntMatrix bounds, DoubleArray sigma) { if (sigma == null || sigma.Length == 0) throw new ArgumentException("RoundedNormalAllPositionsManipulator: Vector containing the standard deviations is not defined.", "sigma"); if (bounds == null || bounds.Rows == 0 || bounds.Columns < 2) throw new ArgumentException("RoundedNormalAllPositionsManipulator: Invalid bounds specified.", "bounds"); var N = new NormalDistributedRandom(random, 0.0, 1.0); for (int i = 0; i < vector.Length; i++) { int min = bounds[i % bounds.Rows, 0], max = bounds[i % bounds.Rows, 1], step = 1; if (bounds.Columns > 2) step = bounds[i % bounds.Rows, 2]; int value = (vector[i] + (int)Math.Round((N.NextDouble() * sigma[i % sigma.Length])) - min) / step; max = FloorFeasible(min, max, step, max - 1); vector[i] = RoundFeasible(min, max, step, value); } }
/// <summary> /// Changes randomly several, but at least one, positions in the given integer <paramref name="vector"/>, according to the given probabilities. /// </summary> /// <param name="random">A random number generator.</param> /// <param name="vector">The integer vector to manipulate.</param> /// <param name="bounds"> Contains the minimum value (inclusive), maximum value (exclusive), and step size of the sampling range for /// the vector element to change.</param> /// <param name="probability">The probability for each dimension to be manipulated..</param> public static void Apply(IRandom random, IntegerVector vector, IntMatrix bounds, double probability) { if (bounds == null || bounds.Rows == 0 || bounds.Columns < 2) throw new ArgumentException("UniformSomePositionsManipulator: Invalid bounds specified", "bounds"); bool atLeastOneManipulated = false; for (int index = 0; index < vector.Length; index++) { if (random.NextDouble() < probability) { atLeastOneManipulated = true; UniformOnePositionManipulator.Manipulate(random, vector, bounds, index); } } if (!atLeastOneManipulated) { UniformOnePositionManipulator.Manipulate(random, vector, bounds, random.Next(vector.Length)); } }
public static void Manipulate(IRandom random, IntegerVector vector, IntMatrix bounds, int index) { if (bounds == null || bounds.Rows == 0 || bounds.Columns < 2) throw new ArgumentException("UniformOnePositionManipulator: Invalid bounds specified", "bounds"); int min = bounds[index % bounds.Rows, 0], max = bounds[index % bounds.Rows, 1], step = 1; if (min == max) { vector[index] = min; } else { if (bounds.Columns > 2) step = bounds[index % bounds.Rows, 2]; // max has to be rounded to the lower feasible value // e.g. min...max / step = 0...100 / 5, max is exclusive so it would be 0..99 // but 99 is not a feasible value, so max needs to be adjusted => min = 0, max = 95 max = FloorFeasible(min, max, step, max - 1); vector[index] = RoundFeasible(min, max, step, random.Next(min, max)); } }
/// <summary> /// Performs the rounded blend alpha beta crossover (BLX-a-b) on two parent vectors. /// </summary> /// <exception cref="ArgumentException"> /// Thrown when either:<br/> /// <list type="bullet"> /// <item><description>The length of <paramref name="betterParent"/> and <paramref name="worseParent"/> is not equal.</description></item> /// <item><description>The parameter <paramref name="alpha"/> is smaller than 0.</description></item> /// <item><description>The parameter <paramref name="beta"/> is smaller than 0.</description></item> /// </list> /// </exception> /// <param name="random">The random number generator to use.</param> /// <param name="betterParent">The better of the two parents with regard to their fitness.</param> /// <param name="worseParent">The worse of the two parents with regard to their fitness.</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 parameter alpha.</param> /// <param name="beta">The parameter beta.</param> /// <returns>The integer vector that results from the crossover.</returns> public static IntegerVector Apply(IRandom random, IntegerVector betterParent, IntegerVector worseParent, IntMatrix bounds, DoubleValue alpha, DoubleValue beta) { if (betterParent.Length != worseParent.Length) { throw new ArgumentException("RoundedBlendAlphaBetaCrossover: The parents' vectors are of different length.", "betterParent"); } if (alpha.Value < 0) { throw new ArgumentException("RoundedBlendAlphaBetaCrossover: Parameter alpha must be greater or equal to 0.", "alpha"); } if (beta.Value < 0) { throw new ArgumentException("RoundedBlendAlphaBetaCrossover: Parameter beta must be greater or equal to 0.", "beta"); } if (bounds == null || bounds.Rows < 1 || bounds.Columns < 2) { throw new ArgumentException("RoundedBlendAlphaBetaCrossover: Invalid bounds specified.", "bounds"); } int length = betterParent.Length; double min, max, d; var result = new IntegerVector(length); 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); d = Math.Abs(betterParent[i] - worseParent[i]); if (betterParent[i] <= worseParent[i]) { min = FloorFeasible(minBound, maxBound, step, betterParent[i] - d * alpha.Value); max = CeilingFeasible(minBound, maxBound, step, worseParent[i] + d * beta.Value); } else { min = FloorFeasible(minBound, maxBound, step, worseParent[i] - d * beta.Value); max = CeilingFeasible(minBound, maxBound, step, betterParent[i] + d * alpha.Value); } result[i] = RoundFeasible(minBound, maxBound, step, min + random.NextDouble() * (max - min)); } return(result); }
public PWREncoding(int nrOfJobs, int nrOfResources, IRandom random) : base() { PermutationWithRepetition = new IntegerVector(nrOfJobs * nrOfResources); int[] lookUpTable = new int[nrOfJobs]; for (int i = 0; i < PermutationWithRepetition.Length; i++) { int newValue = random.Next(nrOfJobs); while (lookUpTable[newValue] >= nrOfResources) newValue = random.Next(nrOfJobs); PermutationWithRepetition[i] = newValue; lookUpTable[newValue]++; } }
/// <summary> /// Performs a single point crossover at a randomly chosen position of the two /// given parent integer vectors. /// </summary> /// <param name="random">A random number generator.</param> /// <param name="parent1">The first parent for crossover.</param> /// <param name="parent2">The second parent for crossover.</param> /// <returns>The newly created integer vector, resulting from the single point crossover.</returns> public static IntegerVector Apply(IRandom random, IntegerVector parent1, IntegerVector parent2) { if (parent1.Length != parent2.Length) throw new ArgumentException("SinglePointCrossover: The parents are of different length."); int length = parent1.Length; int[] result = new int[length]; int breakPoint = random.Next(1, length); for (int i = 0; i < breakPoint; i++) result[i] = parent1[i]; for (int i = breakPoint; i < length; i++) result[i] = parent2[i]; return new IntegerVector(result); }
/// <summary> /// Maps a genotype (an integer vector) to a phenotype (a symbolic expression tree). /// Random approach. /// </summary> /// <param name="random">random number generator</param> /// <param name="bounds">only used for PIGEMapper (ignore here)</param> /// <param name="length">only used for PIGEMapper (ignore here)</param> /// <param name="grammar">grammar definition</param> /// <param name="genotype">integer vector, which should be mapped to a tree</param> /// <returns>phenotype (a symbolic expression tree)</returns> public override SymbolicExpressionTree Map(IRandom random, IntMatrix bounds, int length, ISymbolicExpressionGrammar grammar, IntegerVector genotype) { SymbolicExpressionTree tree = new SymbolicExpressionTree(); var rootNode = (SymbolicExpressionTreeTopLevelNode)grammar.ProgramRootSymbol.CreateTreeNode(); var startNode = (SymbolicExpressionTreeTopLevelNode)grammar.StartSymbol.CreateTreeNode(); rootNode.AddSubtree(startNode); tree.Root = rootNode; MapRandomIteratively(startNode, genotype, grammar, genotype.Length, random); return tree; }
/// <summary> /// Performs a discrete crossover operation of any number of given parents. /// </summary> /// <exception cref="ArgumentException">Thrown when the vectors of the parents are of different length or when there are less than 2 parents.</exception> /// <param name="random">A random number generator.</param> /// <param name="parents">The list of parents for the crossover operation.</param> /// <returns>The newly created integer vector, resulting from the crossover operation.</returns> public static IntegerVector Apply(IRandom random, ItemArray<IntegerVector> parents) { if (parents.Length < 2) throw new ArgumentException("DiscreteCrossover: There are less than two parents to cross."); int length = parents[0].Length; for (int i = 0; i < parents.Length; i++) { if (parents[i].Length != length) throw new ArgumentException("DiscreteCrossover: The parents' vectors are of different length.", "parents"); } var result = new IntegerVector(length); for (int i = 0; i < length; i++) { result[i] = parents[random.Next(parents.Length)][i]; } return result; }
/// <summary> /// Performs the arithmetic crossover on some positions by taking either x = alpha * p1 + (1 - alpha) * p2 or x = p1 depending on the probability for a gene to be crossed. /// </summary> /// <param name="random">The random number generator.</param> /// <param name="parent1">The first parent vector.</param> /// <param name="parent2">The second parent vector.</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 parameter (<see cref="AlphaParameter"/>).</param> /// <param name="probability">The probability parameter (<see cref="ProbabilityParameter"/>).</param> /// <returns>The vector resulting from the crossover.</returns> public static IntegerVector Apply(IRandom random, IntegerVector parent1, IntegerVector parent2, IntMatrix bounds, DoubleValue alpha, DoubleValue probability) { int length = parent1.Length; if (length != parent2.Length) throw new ArgumentException("RoundedUniformArithmeticCrossover: The parent vectors are of different length.", "parent1"); if (alpha.Value < 0 || alpha.Value > 1) throw new ArgumentException("RoundedUniformArithmeticCrossover: Parameter alpha must be in the range [0;1]", "alpha"); if (probability.Value < 0 || probability.Value > 1) throw new ArgumentException("RoundedUniformArithmeticCrossover: Parameter probability must be in the range [0;1]", "probability"); var result = new IntegerVector(length); for (int i = 0; i < length; i++) { if (random.NextDouble() < probability.Value) { int min = bounds[i % bounds.Rows, 0], max = bounds[i % bounds.Rows, 1], step = 1; if (bounds.Columns > 2) step = bounds[i % bounds.Rows, 2]; max = FloorFeasible(min, max, step, max - 1); double value = alpha.Value * parent1[i] + (1 - alpha.Value) * parent2[i]; result[i] = RoundFeasible(min, max, step, value); } else result[i] = parent1[i]; } return result; }
/// <summary> /// Perfomrs a heuristic crossover on the two given parents. /// </summary> /// <exception cref="ArgumentException">Thrown when two parents are not of the same length.</exception> /// <param name="random">The random number generator.</param> /// <param name="betterParent">The first parent for the crossover operation.</param> /// <param name="worseParent">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> /// <returns>The newly created integer vector, resulting from the heuristic crossover.</returns> public static IntegerVector Apply(IRandom random, IntegerVector betterParent, IntegerVector worseParent, IntMatrix bounds) { if (betterParent.Length != worseParent.Length) throw new ArgumentException("HeuristicCrossover: the two parents are not of the same length"); int length = betterParent.Length; var result = new IntegerVector(length); double factor = random.NextDouble(); int min, max, step = 1; for (int i = 0; i < length; i++) { min = bounds[i % bounds.Rows, 0]; max = bounds[i % bounds.Rows, 1]; if (bounds.Columns > 2) step = bounds[i % bounds.Rows, 2]; max = FloorFeasible(min, max, step, max - 1); result[i] = RoundFeasible(min, max, step, betterParent[i] + factor * (betterParent[i] - worseParent[i])); } return result; }
/// <summary> /// Performs a local crossover on the two given parent vectors. /// </summary> /// <exception cref="ArgumentException">Thrown when two parents are not of the same length.</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> /// <returns>The newly created integer vector, resulting from the local crossover.</returns> public static IntegerVector Apply(IRandom random, IntegerVector parent1, IntegerVector parent2, IntMatrix bounds) { if (parent1.Length != parent2.Length) throw new ArgumentException("RoundedLocalCrossover: the two parents are not of the same length"); double factor; int length = parent1.Length; var result = new IntegerVector(length); int min, max, step = 1; for (int i = 0; i < length; i++) { min = bounds[i % bounds.Rows, 0]; max = bounds[i % bounds.Rows, 1]; if (bounds.Columns > 2) step = bounds[i % bounds.Rows, 2]; max = FloorFeasible(min, max, step, max - 1); factor = random.NextDouble(); result[i] = RoundFeasible(min, max, step, (factor * parent1[i]) + ((1 - factor) * parent2[i])); } return result; }
public static OrienteeringEvaluationResult Apply(IntegerVector solution, DoubleArray scores, DistanceMatrix distances, double maximumDistance, double pointVisitingCosts, double distancePenaltyFactor) { double score = solution.Sum(t => scores[t]); double distance = distances.CalculateTourLength(solution.ToList(), pointVisitingCosts); double distanceViolation = distance - maximumDistance; double penalty = 0.0; penalty += distanceViolation > 0 ? distanceViolation * distancePenaltyFactor : 0; double quality = score - penalty; return new OrienteeringEvaluationResult { Quality = new DoubleValue(quality), Penalty = new DoubleValue(penalty), Distance = new DoubleValue(distance) }; }
/// <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); }
/// <summary> /// Performs an average crossover of the two given parent integer vectors. /// The average is rounded and mapped to the nearest valid value (e.g. if step size is > 1) /// </summary> /// <param name="random">A random number generator.</param> /// <param name="parents">The parents for crossover.</param> /// <param name="bounds">The bounds matrix that contains for each dimension one row with minimum (inclusive), maximum (exclusive), and step size columns. /// If the number of rows is smaller than the number of dimensions the matrix is cycled.</param> /// <returns>The newly created integer vector, resulting from the single point crossover.</returns> public static IntegerVector Apply(IRandom random, ItemArray <IntegerVector> parents, IntMatrix bounds) { int length = parents[0].Length, parentsCount = parents.Length; if (parents.Length < 2) { throw new ArgumentException("RoundedAverageCrossover: The number of parents is less than 2.", "parents"); } if (bounds == null || bounds.Rows < 1 || bounds.Columns < 2) { throw new ArgumentException("AverageCrossover: Invalid bounds specified.", "bounds"); } var result = new IntegerVector(length); try { double avg; for (int i = 0; i < length; i++) { avg = 0; for (int j = 0; j < parentsCount; j++) { avg += parents[j][i]; } avg /= parentsCount; int min = bounds[i % bounds.Rows, 0], max = bounds[i % bounds.Rows, 1], step = 1; if (bounds.Columns > 2) { step = bounds[i % bounds.Rows, 2]; } max = FloorFeasible(min, max, step, max - 1); result[i] = RoundFeasible(min, max, step, avg); } } catch (IndexOutOfRangeException) { throw new ArgumentException("RoundedAverageCrossover: The parents' vectors are of different length.", "parents"); } return(result); }
/// <summary> /// Changes randomly several, but at least one, positions in the given integer <paramref name="vector"/>, according to the given probabilities. /// </summary> /// <param name="random">A random number generator.</param> /// <param name="vector">The integer vector to manipulate.</param> /// <param name="bounds"> Contains the minimum value (inclusive), maximum value (exclusive), and step size of the sampling range for /// the vector element to change.</param> /// <param name="probability">The probability for each dimension to be manipulated..</param> public static void Apply(IRandom random, IntegerVector vector, IntMatrix bounds, double probability) { if (bounds == null || bounds.Rows == 0 || bounds.Columns < 2) { throw new ArgumentException("UniformSomePositionsManipulator: Invalid bounds specified", "bounds"); } bool atLeastOneManipulated = false; for (int index = 0; index < vector.Length; index++) { if (random.NextDouble() < probability) { atLeastOneManipulated = true; UniformOnePositionManipulator.Manipulate(random, vector, bounds, index); } } if (!atLeastOneManipulated) { UniformOnePositionManipulator.Manipulate(random, vector, bounds, random.Next(vector.Length)); } }
/// <summary> /// Performs the arithmetic crossover on some positions by taking either x = alpha * p1 + (1 - alpha) * p2 or x = p1 depending on the probability for a gene to be crossed. /// </summary> /// <param name="random">The random number generator.</param> /// <param name="parent1">The first parent vector.</param> /// <param name="parent2">The second parent vector.</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 parameter (<see cref="AlphaParameter"/>).</param> /// <param name="probability">The probability parameter (<see cref="ProbabilityParameter"/>).</param> /// <returns>The vector resulting from the crossover.</returns> public static IntegerVector Apply(IRandom random, IntegerVector parent1, IntegerVector parent2, IntMatrix bounds, DoubleValue alpha, DoubleValue probability) { int length = parent1.Length; if (length != parent2.Length) { throw new ArgumentException("RoundedUniformArithmeticCrossover: The parent vectors are of different length.", "parent1"); } if (alpha.Value < 0 || alpha.Value > 1) { throw new ArgumentException("RoundedUniformArithmeticCrossover: Parameter alpha must be in the range [0;1]", "alpha"); } if (probability.Value < 0 || probability.Value > 1) { throw new ArgumentException("RoundedUniformArithmeticCrossover: Parameter probability must be in the range [0;1]", "probability"); } var result = new IntegerVector(length); for (int i = 0; i < length; i++) { if (random.NextDouble() < probability.Value) { int min = bounds[i % bounds.Rows, 0], max = bounds[i % bounds.Rows, 1], step = 1; if (bounds.Columns > 2) { step = bounds[i % bounds.Rows, 2]; } max = FloorFeasible(min, max, step, max - 1); double value = alpha.Value * parent1[i] + (1 - alpha.Value) * parent2[i]; result[i] = RoundFeasible(min, max, step, value); } else { result[i] = parent1[i]; } } return(result); }
/// <summary> /// Performs a single point crossover at a randomly chosen position of the two /// given parent integer vectors. /// </summary> /// <param name="random">A random number generator.</param> /// <param name="parent1">The first parent for crossover.</param> /// <param name="parent2">The second parent for crossover.</param> /// <returns>The newly created integer vector, resulting from the single point crossover.</returns> public static IntegerVector Apply(IRandom random, IntegerVector parent1, IntegerVector parent2) { if (parent1.Length != parent2.Length) { throw new ArgumentException("SinglePointCrossover: The parents are of different length."); } int length = parent1.Length; int[] result = new int[length]; int breakPoint = random.Next(1, length); for (int i = 0; i < breakPoint; i++) { result[i] = parent1[i]; } for (int i = breakPoint; i < length; i++) { result[i] = parent2[i]; } return(new IntegerVector(result)); }
/// <summary> /// Performs an average crossover of the two given parent integer vectors. /// The average is rounded and mapped to the nearest valid value (e.g. if step size is > 1) /// </summary> /// <param name="random">A random number generator.</param> /// <param name="parents">The parents for crossover.</param> /// <param name="bounds">The bounds matrix that contains for each dimension one row with minimum (inclusive), maximum (exclusive), and step size columns. /// If the number of rows is smaller than the number of dimensions the matrix is cycled.</param> /// <returns>The newly created integer vector, resulting from the single point crossover.</returns> public static IntegerVector Apply(IRandom random, ItemArray<IntegerVector> parents, IntMatrix bounds) { int length = parents[0].Length, parentsCount = parents.Length; if (parents.Length < 2) throw new ArgumentException("RoundedAverageCrossover: The number of parents is less than 2.", "parents"); if (bounds == null || bounds.Rows < 1 || bounds.Columns < 2) throw new ArgumentException("AverageCrossover: Invalid bounds specified.", "bounds"); var result = new IntegerVector(length); try { double avg; for (int i = 0; i < length; i++) { avg = 0; for (int j = 0; j < parentsCount; j++) avg += parents[j][i]; avg /= parentsCount; int min = bounds[i % bounds.Rows, 0], max = bounds[i % bounds.Rows, 1], step = 1; if (bounds.Columns > 2) step = bounds[i % bounds.Rows, 2]; max = FloorFeasible(min, max, step, max - 1); result[i] = RoundFeasible(min, max, step, avg); } } catch (IndexOutOfRangeException) { throw new ArgumentException("RoundedAverageCrossover: The parents' vectors are of different length.", "parents"); } return result; }
protected IntegerVector(IntegerVector original, Cloner cloner) : base(original, cloner) { }
/// <summary> /// Returns a randomly chosen child node for the given <paramref name="parentNode"/>. /// </summary> /// <param name="parentNode">parent node to find a child node randomly for</param> /// <param name="genotype">integer vector, which should be mapped to a tree</param> /// <param name="grammar">grammar used to define the allowed child symbols</param> /// <param name="genotypeIndex">index in the integer vector; can be greater than vector length</param> /// <param name="random">random number generator</param> /// <returns>randomly chosen child node or null, if no child node exits</returns> protected ISymbolicExpressionTreeNode GetNewChildNode(ISymbolicExpressionTreeNode parentNode, IntegerVector genotype, ISymbolicExpressionGrammar grammar, int genotypeIndex, IRandom random) { // only select specific symbols, which can be interpreted ... IEnumerable<ISymbol> symbolList = (from s in grammar.GetAllowedChildSymbols(parentNode.Symbol) where s.InitialFrequency > 0.0 select s).ToList(); int prodRuleCount = symbolList.Count(); // no child node exists for the given parent node if (prodRuleCount < 1) return null; // genotypeIndex % genotype.Length, if wrapping is allowed int prodRuleIndex = genotype[genotypeIndex] % prodRuleCount; var newNode = symbolList.ElementAt(prodRuleIndex).CreateTreeNode(); if (newNode.HasLocalParameters) newNode.ResetLocalParameters(random); return newNode; }
protected abstract void ManipulateBounded(IRandom random, IntegerVector integerVector, IntMatrix bounds);
/// <summary> /// Performs the rounded blend alpha beta crossover (BLX-a-b) on two parent vectors. /// </summary> /// <exception cref="ArgumentException"> /// Thrown when either:<br/> /// <list type="bullet"> /// <item><description>The length of <paramref name="betterParent"/> and <paramref name="worseParent"/> is not equal.</description></item> /// <item><description>The parameter <paramref name="alpha"/> is smaller than 0.</description></item> /// <item><description>The parameter <paramref name="beta"/> is smaller than 0.</description></item> /// </list> /// </exception> /// <param name="random">The random number generator to use.</param> /// <param name="betterParent">The better of the two parents with regard to their fitness.</param> /// <param name="worseParent">The worse of the two parents with regard to their fitness.</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 parameter alpha.</param> /// <param name="beta">The parameter beta.</param> /// <returns>The integer vector that results from the crossover.</returns> public static IntegerVector Apply(IRandom random, IntegerVector betterParent, IntegerVector worseParent, IntMatrix bounds, DoubleValue alpha, DoubleValue beta) { if (betterParent.Length != worseParent.Length) throw new ArgumentException("RoundedBlendAlphaBetaCrossover: The parents' vectors are of different length.", "betterParent"); if (alpha.Value < 0) throw new ArgumentException("RoundedBlendAlphaBetaCrossover: Parameter alpha must be greater or equal to 0.", "alpha"); if (beta.Value < 0) throw new ArgumentException("RoundedBlendAlphaBetaCrossover: Parameter beta must be greater or equal to 0.", "beta"); if (bounds == null || bounds.Rows < 1 || bounds.Columns < 2) throw new ArgumentException("RoundedBlendAlphaBetaCrossover: Invalid bounds specified.", "bounds"); int length = betterParent.Length; double min, max, d; var result = new IntegerVector(length); 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); d = Math.Abs(betterParent[i] - worseParent[i]); if (betterParent[i] <= worseParent[i]) { min = FloorFeasible(minBound, maxBound, step, betterParent[i] - d * alpha.Value); max = CeilingFeasible(minBound, maxBound, step, worseParent[i] + d * beta.Value); } else { min = FloorFeasible(minBound, maxBound, step, worseParent[i] - d * beta.Value); max = CeilingFeasible(minBound, maxBound, step, betterParent[i] + d * alpha.Value); } result[i] = RoundFeasible(minBound, maxBound, step, min + random.NextDouble() * (max - min)); } return result; }
public abstract SymbolicExpressionTree Map(IRandom random, IntMatrix bounds, int length, ISymbolicExpressionGrammar grammar, IntegerVector genotype);
/// <summary> /// Genotype-to-Phenotype mapper (iterative depth-first approach, by using a stack -> LIFO). /// </summary> /// <param name="startNode">first node of the tree with arity 1</param> /// <param name="genotype">integer vector, which should be mapped to a tree</param> /// <param name="grammar">grammar to determine the allowed child symbols for each node</param> /// <param name="maxSubtreeCount">maximum allowed subtrees (= number of used genomes)</param> /// <param name="random">random number generator</param> private void MapDepthFirstIteratively(ISymbolicExpressionTreeNode startNode, IntegerVector genotype, ISymbolicExpressionGrammar grammar, int maxSubtreeCount, IRandom random) { Stack<Tuple<ISymbolicExpressionTreeNode, int>> stack = new Stack<Tuple<ISymbolicExpressionTreeNode, int>>(); // tuples of <node, arity> int genotypeIndex = 0; stack.Push(new Tuple<ISymbolicExpressionTreeNode, int>(startNode, 1)); while (stack.Count > 0) { // get next node from stack and re-push it, if this node still has unhandled subtrees ... Tuple<ISymbolicExpressionTreeNode, int> current = stack.Pop(); if (current.Item2 > 1) { stack.Push(new Tuple<ISymbolicExpressionTreeNode, int>(current.Item1, current.Item2 - 1)); } if (genotypeIndex >= maxSubtreeCount) { // if all genomes were used, only add terminal nodes to the remaining subtrees current.Item1.AddSubtree(GetRandomTerminalNode(current.Item1, grammar, random)); } else { var newNode = GetNewChildNode(current.Item1, genotype, grammar, genotypeIndex, random); int arity = SampleArity(random, newNode, grammar); current.Item1.AddSubtree(newNode); genotypeIndex++; if (arity > 0) { // new node has subtrees so push it onto the stack stack.Push(new Tuple<ISymbolicExpressionTreeNode, int>(newNode, arity)); } } } }
public static PWREncoding CreateTestPWR2() { PWREncoding result = new PWREncoding(); IntegerVector pwr = new IntegerVector(new int[] { 0, 1, 1, 0, 2, 0, 1, 2, 2 }); result.PermutationWithRepetition = pwr; return result; }
protected sealed override void Manipulate(IRandom random, IntegerVector integerVector) { if (BoundsParameter.ActualValue == null) throw new InvalidOperationException("BoundedIntegerVectorManipulator: Parameter " + BoundsParameter.ActualName + " could not be found."); ManipulateBounded(random, integerVector, BoundsParameter.ActualValue); }
/// <summary> /// Maps a genotype (an integer vector) to a phenotype (a symbolic expression tree). /// PIGE approach. /// </summary> /// <param name="random">random number generator</param> /// <param name="bounds">integer number range for genomes (codons) of the nont vector</param> /// <param name="length">length of the nont vector to create</param> /// <param name="grammar">grammar definition</param> /// <param name="genotype">integer vector, which should be mapped to a tree</param> /// <returns>phenotype (a symbolic expression tree)</returns> public override ISymbolicExpressionTree Map(IRandom random, IntMatrix bounds, int length, ISymbolicExpressionGrammar grammar, IntegerVector genotype) { SymbolicExpressionTree tree = new SymbolicExpressionTree(); var rootNode = (SymbolicExpressionTreeTopLevelNode)grammar.ProgramRootSymbol.CreateTreeNode(); var startNode = (SymbolicExpressionTreeTopLevelNode)grammar.StartSymbol.CreateTreeNode(); rootNode.AddSubtree(startNode); tree.Root = rootNode; // Map can be called simultaniously on multiple threads lock (nontVectorLocker) { if (NontVector == null) { NontVector = GetNontVector(random, bounds, length); } } MapPIGEIteratively(startNode, genotype, grammar, genotype.Length, random); return tree; }
/// <summary> /// Retrieves the bounds and forwards the call to the static Apply method. /// </summary> /// <param name="random">The random number generator.</param> /// <param name="vector">The vector of integer values that is manipulated.</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> protected override void ManipulateBounded(IRandom random, IntegerVector vector, IntMatrix bounds) { Apply(random, vector, bounds, SigmaParameter.Value); }
protected abstract void ManipulateBounded(IRandom random, IntegerVector integerVector, IntMatrix bounds);
protected abstract void Manipulate(IRandom random, IntegerVector integerVector);
private static IntegerVector GetNontVector(IRandom random, IntMatrix bounds, int length) { IntegerVector v = new IntegerVector(length); v.Randomize(random, bounds); return v; }
/// <summary> /// Genotype-to-Phenotype mapper (iterative 𝜋GE approach, using a list of not expanded nonTerminals). /// </summary> /// <param name="startNode">first node of the tree with arity 1</param> /// <param name="genotype">integer vector, which should be mapped to a tree</param> /// <param name="grammar">grammar to determine the allowed child symbols for each node</param> /// <param name="maxSubtreeCount">maximum allowed subtrees (= number of used genomes)</param> /// <param name="random">random number generator</param> private void MapPIGEIteratively(ISymbolicExpressionTreeNode startNode, IntegerVector genotype, ISymbolicExpressionGrammar grammar, int maxSubtreeCount, IRandom random) { List<ISymbolicExpressionTreeNode> nonTerminals = new List<ISymbolicExpressionTreeNode>(); int genotypeIndex = 0; nonTerminals.Add(startNode); while (nonTerminals.Count > 0) { if (genotypeIndex >= maxSubtreeCount) { // if all genomes were used, only add terminal nodes to the remaining subtrees ISymbolicExpressionTreeNode current = nonTerminals[0]; nonTerminals.RemoveAt(0); current.AddSubtree(GetRandomTerminalNode(current, grammar, random)); } else { // Order: NT = nont % Num. NT int nt = NontVector[genotypeIndex] % nonTerminals.Count; ISymbolicExpressionTreeNode current = nonTerminals[nt]; nonTerminals.RemoveAt(nt); // Content: Rule = rule % Num. Rules ISymbolicExpressionTreeNode newNode = GetNewChildNode(current, genotype, grammar, genotypeIndex, random); int arity = SampleArity(random, newNode, grammar); current.AddSubtree(newNode); genotypeIndex++; // new node has subtrees, so add "arity" number of copies of this node to the nonTerminals list for (int i = 0; i < arity; ++i) { nonTerminals.Add(newNode); } } } }
/// <summary> /// Changes randomly several, but at least one, positions in the given integer <paramref name="vector"/>. /// </summary> /// <remarks>Calls <see cref="Apply"/>.</remarks> /// <param name="random">A random number generator.</param> /// <param name="vector">The integer vector to manipulate.</param> protected override void ManipulateBounded(IRandom random, IntegerVector vector, IntMatrix bounds) { Apply(random, vector, bounds, ProbabilityParameter.ActualValue.Value); }
/// <summary> /// Retrieves the bounds and forwards the call to the static Apply method. /// </summary> /// <param name="random">The random number generator.</param> /// <param name="vector">The vector of integer values that is manipulated.</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> protected override void ManipulateBounded(IRandom random, IntegerVector vector, IntMatrix bounds) { Apply(random, vector, bounds, SigmaParameter.Value); }
/// <summary> /// Changes randomly a single position in the given integer <paramref name="vector"/>. /// </summary> /// <param name="random">A random number generator.</param> /// <param name="vector">The integer vector to manipulate.</param> /// <param name="min">The minimum value of the sampling range for /// the vector element to change (inclusive).</param> /// <param name="max">The maximum value of the sampling range for /// the vector element to change (exclusive).</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> public static void Apply(IRandom random, IntegerVector vector, IntMatrix bounds) { Manipulate(random, vector, bounds, random.Next(vector.Length)); }
/// <summary> /// Changes randomly several, but at least one, positions in the given integer <paramref name="vector"/>. /// </summary> /// <remarks>Calls <see cref="Apply"/>.</remarks> /// <param name="random">A random number generator.</param> /// <param name="vector">The integer vector to manipulate.</param> protected override void ManipulateBounded(IRandom random, IntegerVector vector, IntMatrix bounds) { Apply(random, vector, bounds, ProbabilityParameter.ActualValue.Value); }
public PRVEncoding(IntegerVector iv, IntValue nrOfRules) : base() { this.nrOfRules = (IntValue)nrOfRules.Clone(); this.PriorityRulesVector = (IntegerVector)iv.Clone(); }
/// <summary> /// Genotype-to-Phenotype mapper (iterative random approach, where the next non-terminal /// symbol to expand is randomly determined). /// </summary> /// <param name="startNode">first node of the tree with arity 1</param> /// <param name="genotype">integer vector, which should be mapped to a tree</param> /// <param name="grammar">grammar to determine the allowed child symbols for each node</param> /// <param name="maxSubtreeCount">maximum allowed subtrees (= number of used genomes)</param> /// <param name="random">random number generator</param> private void MapRandomIteratively(ISymbolicExpressionTreeNode startNode, IntegerVector genotype, ISymbolicExpressionGrammar grammar, int maxSubtreeCount, IRandom random) { List<ISymbolicExpressionTreeNode> nonTerminals = new List<ISymbolicExpressionTreeNode>(); int genotypeIndex = 0; nonTerminals.Add(startNode); while (nonTerminals.Count > 0) { if (genotypeIndex >= maxSubtreeCount) { // if all genomes were used, only add terminal nodes to the remaining subtrees ISymbolicExpressionTreeNode current = nonTerminals[0]; nonTerminals.RemoveAt(0); current.AddSubtree(GetRandomTerminalNode(current, grammar, random)); } else { // similar to PIGEMapper, but here the current node is determined randomly ... ISymbolicExpressionTreeNode current = nonTerminals.SampleRandom(random); nonTerminals.Remove(current); ISymbolicExpressionTreeNode newNode = GetNewChildNode(current, genotype, grammar, genotypeIndex, random); int arity = SampleArity(random, newNode, grammar); current.AddSubtree(newNode); genotypeIndex++; // new node has subtrees, so add "arity" number of copies of this node to the nonTerminals list for (int i = 0; i < arity; ++i) { nonTerminals.Add(newNode); } } } }
protected IntegerVector(IntegerVector original, Cloner cloner) : base(original, cloner) { }
protected abstract void Manipulate(IRandom random, IntegerVector integerVector);