/// <summary> /// Performs a non uniformly distributed one position manipulation on the given /// real <paramref name="vector"/>. The probability of stronger mutations reduces the more <see cref="currentIteration"/> approaches <see cref="maximumIterations"/>. /// </summary> /// <exception cref="ArgumentException">Thrown when <paramref name="currentIteration"/> is greater than <paramref name="maximumIterations"/>.</exception> /// <param name="random">The 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="currentIteration">The current iteration of the algorithm.</param> /// <param name="maximumIterations">Maximum number of iterations.</param> /// <param name="iterationDependency">Specifies the degree of dependency on the number of iterations. A value of 0 means no dependency and the higher the value the stronger the progress towards maximum iterations will be taken into account by sampling closer around the current position. Value must be >= 0.</param> /// <returns>The manipulated real vector.</returns> public static void Apply(IRandom random, RealVector vector, DoubleMatrix bounds, IntValue currentIteration, IntValue maximumIterations, DoubleValue iterationDependency) { if (currentIteration.Value > maximumIterations.Value) { throw new ArgumentException("MichalewiczNonUniformOnePositionManipulator: CurrentIteration must be smaller or equal than MaximumIterations", "currentIteration"); } if (iterationDependency.Value < 0) { throw new ArgumentException("MichalewiczNonUniformOnePositionManipulator: iterationDependency must be >= 0.", "iterationDependency"); } int length = vector.Length; int index = random.Next(length); double prob = (1 - Math.Pow(random.NextDouble(), Math.Pow(1 - currentIteration.Value / maximumIterations.Value, iterationDependency.Value))); double min = bounds[index % bounds.Rows, 0]; double max = bounds[index % bounds.Rows, 1]; if (random.NextDouble() < 0.5) { vector[index] = vector[index] + (max - vector[index]) * prob; } else { vector[index] = vector[index] - (vector[index] - min) * prob; } }
public void Visit(FuncExpression <T> expression) { if (_random.NextDouble() < _mutationRate.GetValue()) { MutateFuncExpression(expression); } }
/// <summary> /// Generates normally distributed numbers. Each operation makes two Gaussian for the price of one, and apparently /// they can be cached or something for better performance, but who cares. /// </summary> /// <param name="random"></param> /// <param name="mu">Mean of the distribution</param> /// <param name="sigma">Standard deviation</param> /// <returns></returns> public static double NextGaussian( [NotNull] this IRandom random, double mu = 0, double sigma = 1) { if (random == null) { throw new ArgumentNullException(nameof(random)); } if (sigma <= 0) { throw new ArgumentOutOfRangeException(nameof(sigma)); } double u1 = random.NextDouble( ); double u2 = random.NextDouble( ); double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2); double randNormal = mu + sigma * randStdNormal; return(randNormal); }
/// <summary> /// <para>Sample a value from a gamma distribution.</para> /// <para>Implementation of "A Simple Method for Generating Gamma Variables" - Marsaglia & Tsang /// ACM Transactions on Mathematical Software, Vol. 26, No. 3, September 2000, Pages 363–372.</para> /// </summary> /// <param name="uniformRandom">A uniformly-distributed random number generator.</param> /// <param name="shape">The shape (k, α) of the Gamma distribution. Range: α ≥ 0.</param> /// <param name="rate">The rate or inverse scale (β) of the Gamma distribution. Range: β ≥ 0.</param> /// <returns>A sample from a Gamma distributed random variable.</returns> public static double NextDouble(IRandom uniformRandom, double shape, double rate) { if (double.IsPositiveInfinity(rate)) { return(shape); } var a = 1d; if (shape < 1) { a = Math.Pow(uniformRandom.NextDouble(), 1 / shape); shape += 1; } var d = shape - 1d / 3d; var c = 1 / Math.Sqrt(9 * d); for (;;) { double v, x; do { x = NormalDistributedRandom.NextDouble(uniformRandom, 0, 1); v = 1 + c * x; } while (v <= 0); v = v * v * v; x = x * x; // save a multiplication below var u = uniformRandom.NextDouble(); if (u < 1 - 0.0331 * x * x || Math.Log(u) < 0.5 * x + d * (1 - v + Math.Log(v))) { return(a * d * v / rate); } } }
/// <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; } } }
private IEnumerable <IOrganism> PickItems() { if (this.candidates.Count == 0) { throw new ArgumentException("candidates"); } double threshold = rand.NextDouble(); double totalFitnessSoFar = 0; for (int i = 0; i <= this.candidates.Count - 1; i++) { totalFitnessSoFar += this.candidates[i].FitnessProportion; if (totalFitnessSoFar >= threshold) { totalFitnessSoFar = 0; threshold = rand.NextDouble(); yield return(this.candidates[i]); } if (i == this.candidates.Count - 1) { i = 0; } } }
/// <summary> /// Returns a sample from the gamma distribution with scale parameter 1, shape parameter alpha /// </summary> /// <param name="alpha">Shape parameter</param> /// <param name="r">The random number generator to use</param> /// <returns>Sample from gamma distribution</returns> /// <remarks>Uses Marsaglia and Tsang's fast algorithm</remarks> public static double SampleFromGamma(IRandom r, double alpha) { Contracts.CheckParam(alpha > 0, nameof(alpha), "alpha must be positive"); if (alpha < 1) { return(SampleFromGamma(r, alpha + 1) * Math.Pow(r.NextDouble(), 1.0 / alpha)); } double d = alpha - 1.0 / 3; double c = 1 / Math.Sqrt(9 * d); double x; double u; double v; while (true) { do { x = SampleFromGaussian(r); v = Math.Pow(1.0 + c * x, 3); } while (v <= 0); u = r.NextDouble(); double xSqr = x * x; if (u < 1.0 - 0.0331 * xSqr * xSqr || Math.Log(u) < 0.5 * xSqr + d * (1.0 - v + Math.Log(v))) { return(d * v); } } }
private void InitSumupInputData(SumupInputData data, double sparsity, IRandom rgen) { int count = 0; foreach (int d in CreateDocIndices(sparsity, rgen)) { data.DocIndices[count++] = d; } _host.Assert(Utils.IsIncreasing(0, data.DocIndices, count, _len)); data.TotalCount = count; FloatType osum = 0; if (data.Weights == null) { for (int i = 0; i < count; ++i) { osum += (data.Outputs[i] = (FloatType)(2 * rgen.NextDouble() - 1)); } data.SumWeights = count; } else { FloatType wsum = 0; for (int i = 0; i < count; ++i) { osum += (data.Outputs[i] = (FloatType)(2 * rgen.NextDouble() - 1)); wsum += (data.Weights[i] = (FloatType)(2 * rgen.NextDouble() - 1)); } data.SumWeights = wsum; } data.SumTargets = osum; }
public void Update(float delta) { if (_random.NextDouble() < 0.001) { Brightness = (float)_random.NextDouble(_maxBrightness - 0.2f, _maxBrightness); //thunderInstance.Play(); //_soundEffectManager.Play("thunder_01", (float)_random.NextDouble(0.05, 0.25), (float)_random.NextDouble(-0.3, 0.3), (float)_random.NextDouble(-0.2, 0.1)); } if (Brightness > _minBrightness) { Brightness *= 0.9f; if (_random.NextDouble() < 0.04) { Brightness += (float)_random.NextDouble(0.1, 0.3); } if (Brightness < _minBrightness) { Brightness = _minBrightness; } } }
public override void ShakeLocalParameters(IRandom random, double shakingFactor) { // 50% additive & 50% multiplicative (override of functionality of base class because of a BUG) if (random.NextDouble() < 0.5) { double x = NormalDistributedRandom.NextDouble(random, Symbol.WeightManipulatorMu, Symbol.WeightManipulatorSigma); Weight = Weight + x * shakingFactor; } else { double x = NormalDistributedRandom.NextDouble(random, 1.0, Symbol.MultiplicativeWeightManipulatorSigma); Weight = Weight * x; } if (random.NextDouble() < Symbol.VariableChangeProbability) { var oldName = VariableName; VariableName = Symbol.VariableNames.SampleRandom(random); // reinitialize weights if variable has changed (similar to FactorVariableTreeNode) if (oldName != VariableName) { Weight = NormalDistributedRandom.NextDouble(random, Symbol.WeightMu, Symbol.WeightSigma); } } variableValue = Symbol.GetVariableValues(VariableName).SampleRandom(random); }
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 void Merge(T parent1, T parent2, T child) { double parent1Percent = _random.NextDouble(); double newValue = _getterFunc(parent1) * parent1Percent + _getterFunc(parent2) * (1 - parent1Percent); _setterAction(child, newValue); }
public override void ShakeLocalParameters(IRandom random, double shakingFactor) { // mutate only one randomly selected weight var idx = random.Next(weights.Length); // 50% additive & 50% multiplicative if (random.NextDouble() < 0.5) { double x = NormalDistributedRandom.NextDouble(random, Symbol.WeightManipulatorMu, Symbol.WeightManipulatorSigma); weights[idx] = weights[idx] + x * shakingFactor; } else { double x = NormalDistributedRandom.NextDouble(random, 1.0, Symbol.MultiplicativeWeightManipulatorSigma); weights[idx] = weights[idx] * x; } if (random.NextDouble() < Symbol.VariableChangeProbability) { VariableName = Symbol.VariableNames.SampleRandom(random); if (weights.Length != Symbol.GetVariableValues(VariableName).Count()) { // if the length of the weight array does not match => re-initialize weights weights = Symbol.GetVariableValues(variableName) .Select(_ => NormalDistributedRandom.NextDouble(random, 0, 1)) .ToArray(); } } }
/// <summary>Returns a random point within a triangle</summary> /// <param name="randomNumberGenerator">Random number generator that will be used</param> /// <param name="a">Location of the triangle's first corner</param> /// <param name="b">Location of the triangle's second corner</param> /// <param name="c">Location of the triangle's third corner</param> /// <returns>A random point within the triangle</returns> public static Vector3 GenerateRandomPointWithin( IRandom randomNumberGenerator, Vector3 a, Vector3 b, Vector3 c ) { // Treat triangle as the half of a parallelogram. Then calculate a // random point along the width and the height. // // Width // ----------- // a___________ // / / / // / / / Height // /__________/ / // b c // // Now split the parallelogram along a-c and mirror any points that // end up on the other side. // // xx = rand(1.0) // yy = rand(1.0) // // if((xx + yy) > 1.0) { // xx = 1.0 - xx; // yy = 1.0 - yy; // } // // Then calculate the absolute coordinates of the point // // a. // / . // / . // /________. // b c // // x = b.x + xx * (c.x - b.x) + (b.x - a.x) * yy // y = yy * (a.y - b.y) // This might be using the same approach, not sure though :) // http://vcg.isti.cnr.it/activities/geometryegraphics/pointintetraedro.html // Calculate random barycentric coordinates inside the unit // triangle (0,0)-(1,0)-(0,1). First, we take random x and y coordinates in // a box with side lengths ab, ac float x = (float)randomNumberGenerator.NextDouble(); float y = (float)randomNumberGenerator.NextDouble(); // The triangle covers exactly half of the box our random points are distributed // in. Instead of rejecting these coordinates, we mirror the other half of the box // back into the triangle (on the bc edge of the triangle) if (x + y > 1.0f) { x = 1.0f - x; y = 1.0f - y; } float z = 1.0f - x - y; // Convert the barycentric coordinates back into cartesian coordinates return((a * x) + (b * y) + (c * z)); }
/// <summary>Returns a random point within a rectangle</summary> /// <param name="randomNumberGenerator">Random number generator that will be used</param> /// <param name="extents">Extents of the rectangle</param> /// <returns>A random point within the rectangle</returns> public static Vector2 GenerateRandomPointWithin( IRandom randomNumberGenerator, Vector2 extents ) { float x = (float)randomNumberGenerator.NextDouble() * 2.0f - 1.0f; float y = (float)randomNumberGenerator.NextDouble() * 2.0f - 1.0f; return(new Vector2(x * extents.X, y * extents.Y)); }
/// <summary>Returns a random point on the surface of a box</summary> /// <param name="randomNumberGenerator">Random number generator that will be used</param> /// <param name="extents">Extents of the box</param> /// <returns>A random point on the box' surface</returns> /// <remarks> /// The performance of this algorithm varies slightly depending on the face /// that is chosen for the random point because a different number of /// comparisons and subtractions will be performed. /// </remarks> public static Vector3 GenerateRandomPointOnSurface( IRandom randomNumberGenerator, Vector3 extents ) { // For this task, we also need the dimensions of the box Vector3 dimensions = extents * 2.0f; // Determine the area covered by the sides of the box float leftRightArea = dimensions.Z * dimensions.Y; float topBottomArea = dimensions.X * dimensions.Z; float frontBackArea = dimensions.X * dimensions.Y; // Choose which face of the box the point is going be on float side = (float)randomNumberGenerator.NextDouble() * (leftRightArea * 2.0f) * (topBottomArea * 2.0f) * (frontBackArea * 2.0f); // Now obtain were the point will be located float u = (float)randomNumberGenerator.NextDouble() * 2.0f - 1.0f; float v = (float)randomNumberGenerator.NextDouble() * 2.0f - 1.0f; // Calculate the final world space coordinates of the point side -= leftRightArea; if (side < 0.0) { return(new Vector3(-extents.X, v * extents.Y, u * extents.Z)); } side -= leftRightArea; if (side < 0.0) { return(new Vector3(+extents.X, v * extents.Y, u * extents.Z)); } side -= topBottomArea; if (side < 0.0) { return(new Vector3(u * extents.X, +extents.Y, v * extents.Z)); } side -= topBottomArea; if (side < 0.0) { return(new Vector3(u * extents.X, -extents.Y, v * extents.Z)); } side -= frontBackArea; if (side < 0.0) { return(new Vector3(u * extents.X, v * extents.Y, -extents.Z)); } else { return(new Vector3(u * extents.X, v * extents.Y, +extents.Z)); } }
/// <summary>Returns a random point within a box</summary> /// <param name="randomNumberGenerator">Random number generator that will be used</param> /// <param name="extents">Extents of the box</param> /// <returns>A random point within the box</returns> public static Vector3 GenerateRandomPointWithin( IRandom randomNumberGenerator, Vector3 extents ) { return(new Vector3( ((float)randomNumberGenerator.NextDouble() * 2.0f - 1.0f) * extents.X, ((float)randomNumberGenerator.NextDouble() * 2.0f - 1.0f) * extents.Y, ((float)randomNumberGenerator.NextDouble() * 2.0f - 1.0f) * extents.Z )); }
/// <summary>Returns a random point on the surface of a cylinder</summary> /// <param name="randomNumberGenerator">Random number generator that will be used</param> /// <param name="orientation">Orientation of the cylinder</param> /// <param name="radius">Radius of the cylinder</param> /// <param name="length">Length of the cylinder</param> /// <returns>A random point on the volume's surface</returns> public static Vector3 GenerateRandomPointOnSurface( IRandom randomNumberGenerator, Matrix orientation, float radius, float length ) { // Calculate the surface areas of the three sections our cylinder has: // Upper cap, side and lower cap float capArea = MathHelper.Pi * (radius * radius); float sideArea = 2.0f * MathHelper.Pi * radius * length; float capAndSideArea = capArea + sideArea; // We need a phi value (angle of the random point) in any of the cases float phi = (float)randomNumberGenerator.NextDouble() * MathHelper.TwoPi; // Choose the section that the random point will be generated on in relation // to its surface area so the probability is constant on the entire surface float section = (float)randomNumberGenerator.NextDouble() * (capArea * 2.0f + sideArea); // Depending on the section, these two values are calculated differently float randomRadius; float randomZ; // Upper cap: Generate a random radius if (section < capArea) { randomZ = length / 2.0f; randomRadius = (float)Math.Sqrt(randomNumberGenerator.NextDouble()) * radius; // Side: Generate a random height } else if (section < capAndSideArea) { randomZ = ((float)randomNumberGenerator.NextDouble() - 0.5f) * length; randomRadius = radius; // Lower cap: Generate a random radius } else { randomZ = -length / 2.0f; randomRadius = (float)Math.Sqrt(randomNumberGenerator.NextDouble()) * radius; } // Now transform the point to cartesian coordinates and rotate it into // the global coordinate frame return(Vector3.Transform( new Vector3( randomRadius * (float)Math.Cos(phi), randomRadius * (float)Math.Sin(phi), randomZ ), orientation )); }
// use the Box-Mueller transform in the polar form to generate a N(0,1) random variable out of two uniformly distributed random variables private static double Gauss(IRandom random) { double u = 0.0, v = 0.0, s = 0.0; do { u = (random.NextDouble() * 2) - 1; v = (random.NextDouble() * 2) - 1; s = Math.Sqrt(u * u + v * v); } while (s < Double.Epsilon || s > 1); return(u * Math.Sqrt((-2.0 * Math.Log(s)) / s)); }
/// <summary>Returns a random point inside the area</summary> /// <param name="randomNumberGenerator">Random number generator that will be used</param> /// <returns>A random point inside the area</returns> public Vector2 RandomPointWithin(IRandom randomNumberGenerator) { Vector2 randomPoint = new Vector2( (float)randomNumberGenerator.NextDouble(), (float)randomNumberGenerator.NextDouble() ); Vector2 result; Vector2.Transform(ref randomPoint, ref this.Transform, out result); return(result); }
public void RecordedRates_TestRecording_ValuesAddedProperly() { _randomValue = 1; A.CallTo(() => _mockRandom.NextDouble()).Returns(_randomValue); _logic.StartRecording(); _logic.StartGenerating(); BuySellRate buySellRate = _logic.RecordedRates.First(); Assert.AreEqual(3.55m, buySellRate.BuyRate); Assert.AreEqual(3.8m, buySellRate.SellRate); }
public override double RandNormal(IRandom random, double mu, double sigma) { double z, zz, u1, u2; do { u1 = random.NextDouble(); u2 = 1 - random.NextDouble(); z = NormalMagicConst * (u1 - 0.5) / u2; zz = z * z / 4.0; } while (zz > -Math.Log(u2)); return(mu + z * sigma); }
private static double GetNormal(IRandom rand, double mu, double sigma) { double z, zz, u1, u2; do { u1 = rand.NextDouble(); u2 = 1 - rand.NextDouble(); z = NormalMagicConst * (u1 - 0.5) / u2; zz = z * z / 4.0; } while (zz > -Math.Log(u2)); return(mu + z * sigma); }
/// <summary>Returns a random point on the surface of a cylinder</summary> /// <param name="randomNumberGenerator">Random number generator that will be used</param> /// <param name="orientation">Orientation of the cylinder</param> /// <param name="radius">Radius of the cylinder</param> /// <param name="length">Length of the cylinder</param> /// <returns>A random point on the volume's surface</returns> public static Vector3 GenerateRandomPointOnSurface( IRandom randomNumberGenerator, Matrix orientation, float radius, float length ) { // Calculate the surface areas of the three sections our cylinder has: // Upper cap, side and lower cap float capArea = MathHelper.Pi * (radius * radius); float sideArea = 2.0f * MathHelper.Pi * radius * length; float capAndSideArea = capArea + sideArea; // We need a phi value (angle of the random point) in any of the cases float phi = (float)randomNumberGenerator.NextDouble() * MathHelper.TwoPi; // Choose the section that the random point will be generated on in relation // to its surface area so the probability is constant on the entire surface float section = (float)randomNumberGenerator.NextDouble() * (capArea * 2.0f + sideArea); // Depending on the section, these two values are calculated differently float randomRadius; float randomZ; // Upper cap: Generate a random radius if(section < capArea) { randomZ = length / 2.0f; randomRadius = (float)Math.Sqrt(randomNumberGenerator.NextDouble()) * radius; // Side: Generate a random height } else if(section < capAndSideArea) { randomZ = ((float)randomNumberGenerator.NextDouble() - 0.5f) * length; randomRadius = radius; // Lower cap: Generate a random radius } else { randomZ = -length / 2.0f; randomRadius = (float)Math.Sqrt(randomNumberGenerator.NextDouble()) * radius; } // Now transform the point to cartesian coordinates and rotate it into // the global coordinate frame return Vector3.Transform( new Vector3( randomRadius * (float)Math.Cos(phi), randomRadius * (float)Math.Sin(phi), randomZ ), orientation ); }
/// <summary>Returns a random point within a disc</summary> /// <param name="randomNumberGenerator">Random number generator that will be used</param> /// <param name="radius">Radius of the disc</param> /// <returns>A random point within the disc</returns> public static Vector2 GenerateRandomPointWithin( IRandom randomNumberGenerator, float radius ) { // Choose a random angle for the point float phi = (float)randomNumberGenerator.NextDouble() * MathHelper.Pi * 2.0f; // Get a random radius with compensated probability for the outer regions of the disc float r = (float)Math.Sqrt(randomNumberGenerator.NextDouble()) * radius; // Calculate the final position of the point in world space return(new Vector2( r * (float)Math.Cos(phi), r * (float)Math.Sin(phi))); }
/// <summary> /// Performs the simulated binary crossover on a real vector. Each position is crossed with a probability of 50% and if crossed either a contracting crossover or an expanding crossover is performed, again with equal probability. /// For more details refer to the paper by Deb and Agrawal. /// </summary> /// <exception cref="ArgumentException">Thrown when the parents' vectors are of unequal length or when <paramref name="contiguity"/> is smaller than 0.</exception> /// <remarks> /// The manipulated value is not restricted by the (possibly) specified lower and upper bounds. Use the <see cref="BoundsChecker"/> to correct the values after performing the crossover. /// </remarks> /// <param name="random">The random number generator to use.</param> /// <param name="parent1">The first parent vector.</param> /// <param name="parent2">The second parent vector.</param> /// <param name="contiguity">The contiguity value that specifies how close a child should be to its parents (larger value means closer). The value must be greater or equal than 0. Typical values are in the range [2;5].</param> /// <returns>The vector resulting from the crossover.</returns> public static RealVector Apply(IRandom random, RealVector parent1, RealVector parent2, DoubleValue contiguity) { if (parent1.Length != parent2.Length) { throw new ArgumentException("SimulatedBinaryCrossover: Parents are of unequal length"); } if (contiguity.Value < 0) { throw new ArgumentException("SimulatedBinaryCrossover: Contiguity value is smaller than 0", "contiguity"); } int length = parent1.Length; RealVector result = new RealVector(length); for (int i = 0; i < length; i++) { if (length == 1 || random.NextDouble() < 0.5) // cross this variable { double u = random.NextDouble(); double beta = 0; if (u < 0.5) // if u is smaller than 0.5 perform a contracting crossover { beta = Math.Pow(2 * u, 1.0 / (contiguity.Value + 1)); } else if (u > 0.5) // otherwise perform an expanding crossover { beta = Math.Pow(0.5 / (1.0 - u), 1.0 / (contiguity.Value + 1)); } else if (u == 0.5) { beta = 1; } if (random.NextDouble() < 0.5) { result[i] = ((parent1[i] + parent2[i]) / 2.0) - beta * 0.5 * Math.Abs(parent1[i] - parent2[i]); } else { result[i] = ((parent1[i] + parent2[i]) / 2.0) + beta * 0.5 * Math.Abs(parent1[i] - parent2[i]); } } else { result[i] = parent1[i]; } } return(result); }
/// <summary>Returns a random point within a disc</summary> /// <param name="randomNumberGenerator">Random number generator that will be used</param> /// <param name="radius">Radius of the disc</param> /// <returns>A random point within the disc</returns> public static Vector2 GenerateRandomPointWithin( IRandom randomNumberGenerator, float radius ) { // Choose a random angle for the point float phi = (float)randomNumberGenerator.NextDouble() * MathHelper.Pi * 2.0f; // Get a random radius with compensated probability for the outer regions of the disc float r = (float)Math.Sqrt(randomNumberGenerator.NextDouble()) * radius; // Calculate the final position of the point in world space return new Vector2( r * (float)Math.Cos(phi), r * (float)Math.Sin(phi)); }
protected static int SelectRandomTourBiasedByLength(IRandom random, PotvinEncoding individual, IVRPProblemInstance instance) { int tourIndex = -1; double sum = 0.0; double[] probabilities = new double[individual.Tours.Count]; for (int i = 0; i < individual.Tours.Count; i++) { probabilities[i] = 1.0 / ((double)individual.Tours[i].Stops.Count / (double)instance.Cities.Value); sum += probabilities[i]; } for (int i = 0; i < probabilities.Length; i++) { probabilities[i] = probabilities[i] / sum; } double rand = random.NextDouble(); double cumulatedProbabilities = 0.0; int index = 0; while (tourIndex == -1 && index < probabilities.Length) { if (cumulatedProbabilities <= rand && rand <= cumulatedProbabilities + probabilities[index]) { tourIndex = index; } cumulatedProbabilities += probabilities[index]; index++; } return(tourIndex); }
public override void ShakeLocalParameters(IRandom random, double shakingFactor) { // mutation var d = random.NextDouble() * 2.0 - 1.0; value += shakingFactor * d; if (value < 0.1) value = 0.1; if (value > 3) value = 3; }
protected static int SelectRandomTourBiasedByLength(IRandom random, PotvinEncoding individual, IVRPProblemInstance instance) { int tourIndex = -1; double sum = 0.0; double[] probabilities = new double[individual.Tours.Count]; for (int i = 0; i < individual.Tours.Count; i++) { probabilities[i] = 1.0 / ((double)individual.Tours[i].Stops.Count / (double)instance.Cities.Value); sum += probabilities[i]; } for (int i = 0; i < probabilities.Length; i++) probabilities[i] = probabilities[i] / sum; double rand = random.NextDouble(); double cumulatedProbabilities = 0.0; int index = 0; while (tourIndex == -1 && index < probabilities.Length) { if (cumulatedProbabilities <= rand && rand <= cumulatedProbabilities + probabilities[index]) tourIndex = index; cumulatedProbabilities += probabilities[index]; index++; } return tourIndex; }
/// <summary> /// Chooses <paramref name="count"/> elements from a sequence with repetition with equal chances for each element. /// </summary> /// <remarks> /// Runtime complexity is O(count) for sequences that are <see cref="IList{T}"/> and /// O(N * count) for all other. No exception is thrown if the sequence is empty. /// /// The method is online. /// </remarks> /// <typeparam name="T">The type of the items to be selected.</typeparam> /// <param name="source">The sequence of elements.</param> /// <param name="random">The random number generator to use, its NextDouble() method must produce values in the range [0;1)</param> /// <param name="count">The number of items to be selected.</param> /// <returns>A sequence of elements that have been chosen randomly.</returns> public static IEnumerable <T> SampleRandom <T>(this IEnumerable <T> source, IRandom random, int count) { var listSource = source as IList <T>; if (listSource != null) { while (count > 0) { yield return(listSource[random.Next(listSource.Count)]); count--; } } else { while (count > 0) { var enumerator = source.GetEnumerator(); enumerator.MoveNext(); T selectedItem = enumerator.Current; int counter = 1; while (enumerator.MoveNext()) { counter++; if (counter * random.NextDouble() < 1.0) { selectedItem = enumerator.Current; } } yield return(selectedItem); count--; } } }
/// <summary> /// Create a symbolic expression tree using 'RampedHalfAndHalf' strategy. /// Half the trees are created with the 'Grow' method, and the other half are created with the 'Full' method. /// </summary> /// <param name="random">Random generator</param> /// <param name="grammar">Available tree grammar</param> /// <param name="maxTreeLength">Maximum tree length (this parameter is ignored)</param> /// <param name="maxTreeDepth">Maximum tree depth</param> /// <returns></returns> public static ISymbolicExpressionTree Create(IRandom random, ISymbolicExpressionGrammar grammar, int maxTreeLength, int maxTreeDepth) { var tree = new SymbolicExpressionTree(); var rootNode = (SymbolicExpressionTreeTopLevelNode)grammar.ProgramRootSymbol.CreateTreeNode(); if (rootNode.HasLocalParameters) { rootNode.ResetLocalParameters(random); } rootNode.SetGrammar(grammar.CreateExpressionTreeGrammar()); var startNode = (SymbolicExpressionTreeTopLevelNode)grammar.StartSymbol.CreateTreeNode(); if (startNode.HasLocalParameters) { startNode.ResetLocalParameters(random); } startNode.SetGrammar(grammar.CreateExpressionTreeGrammar()); rootNode.AddSubtree(startNode); double p = random.NextDouble(); if (p < 0.5) { GrowTreeCreator.Create(random, startNode, maxTreeDepth - 2); } else { FullTreeCreator.Create(random, startNode, maxTreeDepth - 2); } tree.Root = rootNode; return(tree); }
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 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="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 RealVector Apply(IRandom random, RealVector parent1, RealVector parent2, DoubleValue alpha, DoubleValue probability) { int length = parent1.Length; if (length != parent2.Length) { throw new ArgumentException("UniformSomePositionsArithmeticCrossover: The parent vectors are of different length.", "parent1"); } if (alpha.Value < 0 || alpha.Value > 1) { throw new ArgumentException("UniformSomePositionsArithmeticCrossover: Parameter alpha must be in the range [0;1]", "alpha"); } if (probability.Value < 0 || probability.Value > 1) { throw new ArgumentException("UniformSomePositionsArithmeticCrossover: Parameter probability must be in the range [0;1]", "probability"); } RealVector result = new RealVector(length); for (int i = 0; i < length; i++) { if (random.NextDouble() < probability.Value) { result[i] = alpha.Value * parent1[i] + (1 - alpha.Value) * parent2[i]; } else { result[i] = parent1[i]; } } return(result); }
/// <summary> /// Performs the 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="alpha">The parameter alpha.</param> /// <param name="beta">The parameter beta.</param> /// <returns>The real vector that results from the crossover.</returns> public static RealVector Apply(IRandom random, RealVector betterParent, RealVector worseParent, DoubleValue alpha, DoubleValue beta) { if (betterParent.Length != worseParent.Length) { throw new ArgumentException("BlendAlphaBetaCrossover: The parents' vectors are of different length.", "betterParent"); } if (alpha.Value < 0) { throw new ArgumentException("BlendAlphaBetaCrossover: Parameter alpha must be greater or equal to 0.", "alpha"); } if (beta.Value < 0) { throw new ArgumentException("BlendAlphaBetaCrossover: Parameter beta must be greater or equal to 0.", "beta"); } int length = betterParent.Length; double min, max, d; RealVector result = new RealVector(length); for (int i = 0; i < length; i++) { d = Math.Abs(betterParent[i] - worseParent[i]); if (betterParent[i] <= worseParent[i]) { min = betterParent[i] - d * alpha.Value; max = worseParent[i] + d * beta.Value; } else { min = worseParent[i] - d * beta.Value; max = betterParent[i] + d * alpha.Value; } result[i] = min + random.NextDouble() * (max - min); } return(result); }
/// <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]; } } }
/** * Taken {@code weightedSampleWithReplacement} out of {@link ParticleFiltering} and extended by a minimum weight. * @param samples the samples to be re-sampled. * @param w the probability distribution on the samples. * @return the new set of samples. */ protected ISet <P> extendedWeightedSampleWithReplacement(ISet <P> samples, double[] w) { int i = 0; for (; i < samples.Size(); ++i) { if (w[i] > weightCutOff) { break; } } if (i >= samples.Size()) { return(generateCloud(samples.Size())); /*If all particleCloud are below weightCutOff, generate a new set of samples, as we are lost.*/ } /*WEIGHTED-SAMPLE-WITH-REPLACEMENT:*/ double[] normalizedW = Util.normalize(w); ISet <P> newSamples = CollectionFactory.CreateSet <P>(); P[] array = samples.ToArray(); for (i = 0; i < samples.Size(); ++i) { int selectedSample = (int)ProbUtil.sample(randomizer.NextDouble(), sampleIndexes, normalizedW); newSamples.Add((array[selectedSample]).Clone()); } return(newSamples); }
public override void ResetLocalParameters(IRandom random) { base.ResetLocalParameters(random); var range = Symbol.MaxValue - Symbol.MinValue; Value = random.NextDouble() * range + Symbol.MinValue; }
public virtual void Randomize(IRandom random, int startIndex, int length, double min, double max) { double delta = max - min; if (length > 0) { for (int i = 0; i < length; i++) array[startIndex + i] = min + delta * random.NextDouble(); OnReset(); } }
/// <summary>Returns a random point on the surface of a box</summary> /// <param name="randomNumberGenerator">Random number generator that will be used</param> /// <param name="extents">Extents of the box</param> /// <returns>A random point on the box' surface</returns> /// <remarks> /// The performance of this algorithm varies slightly depending on the face /// that is chosen for the random point because a different number of /// comparisons and subtractions will be performed. /// </remarks> public static Vector3 GenerateRandomPointOnSurface( IRandom randomNumberGenerator, Vector3 extents ) { // For this task, we also need the dimensions of the box Vector3 dimensions = extents * 2.0f; // Determine the area covered by the sides of the box float leftRightArea = dimensions.Z * dimensions.Y; float topBottomArea = dimensions.X * dimensions.Z; float frontBackArea = dimensions.X * dimensions.Y; // Choose which face of the box the point is going be on float side = (float)randomNumberGenerator.NextDouble() * (leftRightArea * 2.0f) * (topBottomArea * 2.0f) * (frontBackArea * 2.0f); // Now obtain were the point will be located float u = (float)randomNumberGenerator.NextDouble() * 2.0f - 1.0f; float v = (float)randomNumberGenerator.NextDouble() * 2.0f - 1.0f; // Calculate the final world space coordinates of the point side -= leftRightArea; if(side < 0.0) return new Vector3(-extents.X, v * extents.Y, u * extents.Z); side -= leftRightArea; if(side < 0.0) return new Vector3(+extents.X, v * extents.Y, u * extents.Z); side -= topBottomArea; if(side < 0.0) return new Vector3(u * extents.X, +extents.Y, v * extents.Z); side -= topBottomArea; if(side < 0.0) return new Vector3(u * extents.X, -extents.Y, v * extents.Z); side -= frontBackArea; if(side < 0.0) return new Vector3(u * extents.X, v * extents.Y, -extents.Z); else return new Vector3(u * extents.X, v * extents.Y, +extents.Z); }
public virtual void Randomize(IRandom random, int startIndex, int length, DoubleMatrix bounds) { if (length > 0) { for (int i = startIndex; i < startIndex + length; i++) { double min = bounds[i % bounds.Rows, 0]; double max = bounds[i % bounds.Rows, 1]; array[i] = min + (max - min) * random.NextDouble(); } OnReset(); } }
public override void ShakeLocalParameters(IRandom random, double shakingFactor) { base.ShakeLocalParameters(random, shakingFactor); // 50% additive & 50% multiplicative if (random.NextDouble() < 0.5) { double x = NormalDistributedRandom.NextDouble(random, Symbol.ManipulatorMu, Symbol.ManipulatorSigma); Value = Value + x * shakingFactor; } else { double x = NormalDistributedRandom.NextDouble(random, 1.0, Symbol.MultiplicativeManipulatorSigma); Value = Value * x; } }
/// <summary>Returns a random point within a sphere</summary> /// <param name="randomNumberGenerator">Random number generator that will be used</param> /// <param name="radius">Radius of the sphere</param> /// <returns>A random point with the sphere</returns> public static Vector3 GenerateRandomPointWithin( IRandom randomNumberGenerator, float radius ) { // TODO: This is just an approximation. Find the real algorithm. float r = (float)randomNumberGenerator.NextDouble(); r = (float)Math.Sqrt(r * r); r = (float)Math.Sqrt(r * r); return GenerateRandomPointOnSurface(randomNumberGenerator, r); }
/// <summary> /// Performs a random convex 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="parent1">The first parent vector for the crossover.</param> /// <param name="parent2">The second parent vector for the crossover.</param> /// <returns>The newly created real vector, resulting from the random convex crossover.</returns> public static RealVector Apply(IRandom random, RealVector parent1, RealVector parent2) { if (parent1.Length != parent2.Length) throw new ArgumentException("ERROR in RandomConvexCrossover: the two parents are not of the same length"); int length = parent1.Length; double[] result = new double[length]; double factor = random.NextDouble(); for (int i = 0; i < length; i++) result[i] = (factor * parent1[i]) + ((1 - factor) * parent2[i]); return new RealVector(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> /// <returns>The newly created real vector, resulting from the heuristic crossover.</returns> public static RealVector Apply(IRandom random, RealVector betterParent, RealVector worseParent) { if (betterParent.Length != worseParent.Length) throw new ArgumentException("HeuristicCrossover: the two parents are not of the same length"); int length = betterParent.Length; double[] result = new double[length]; double factor = random.NextDouble(); for (int i = 0; i < length; i++) { result[i] = betterParent[i] + factor * (betterParent[i] - worseParent[i]); } return new RealVector(result); }
/// <summary>Returns a random point on the surface of a sphere</summary> /// <param name="randomNumberGenerator">Random number generator that will be used</param> /// <param name="radius">Radius of the sphere</param> /// <returns>A random point on the sphere's surface</returns> public static Vector3 GenerateRandomPointOnSurface( IRandom randomNumberGenerator, float radius ) { // Choose a random longitude for the point float phi = (float)randomNumberGenerator.NextDouble() * MathHelper.TwoPi; // The z axis goes straight through the sphere and is chosen in random. float z = (float)randomNumberGenerator.NextDouble() * 2.0f - 1.0f; // From that, we'll calculate the latitude this point will have on the // sphere's surface. float theta = (float)Math.Sqrt(1.0f - z * z); // Calculate the final position of the point in world space return new Vector3( radius * theta * (float)Math.Cos(phi), radius * theta * (float)Math.Sin(phi), radius * z ); }
/// <summary>Returns a random point on the perimeter of a disc</summary> /// <param name="randomNumberGenerator">Random number generator that will be used</param> /// <param name="radius">Radius of the disc</param> /// <returns>A random point on the disc's perimeter</returns> public static Vector2 GenerateRandomPointOnPerimeter( IRandom randomNumberGenerator, float radius ) { // Choose a random angle for the point float phi = (float)randomNumberGenerator.NextDouble() * MathHelper.TwoPi; // Calculate the final position of the point in world space return new Vector2( radius * (float)Math.Cos(phi), radius * (float)Math.Sin(phi) ); }
/// <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="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 RealVector Apply(IRandom random, RealVector parent1, RealVector parent2, DoubleValue alpha, DoubleValue probability) { int length = parent1.Length; if (length != parent2.Length) throw new ArgumentException("UniformSomePositionsArithmeticCrossover: The parent vectors are of different length.", "parent1"); if (alpha.Value < 0 || alpha.Value > 1) throw new ArgumentException("UniformSomePositionsArithmeticCrossover: Parameter alpha must be in the range [0;1]", "alpha"); if (probability.Value < 0 || probability.Value > 1) throw new ArgumentException("UniformSomePositionsArithmeticCrossover: Parameter probability must be in the range [0;1]", "probability"); RealVector result = new RealVector(length); for (int i = 0; i < length; i++) { if (random.NextDouble() < probability.Value) result[i] = alpha.Value * parent1[i] + (1 - alpha.Value) * parent2[i]; else result[i] = parent1[i]; } 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)); } }
public override void ShakeLocalParameters(IRandom random, double shakingFactor) { base.ShakeLocalParameters(random, shakingFactor); // 50% additive & 50% multiplicative if (random.NextDouble() < 0) { double x = NormalDistributedRandom.NextDouble(random, Symbol.WeightManipulatorMu, Symbol.WeightManipulatorSigma); weight = weight + x * shakingFactor; } else { double x = NormalDistributedRandom.NextDouble(random, 1.0, Symbol.MultiplicativeWeightManipulatorSigma); weight = weight * x; } #pragma warning disable 612, 618 variableName = Symbol.VariableNames.SelectRandom(random); #pragma warning restore 612, 618 }
public static TwoPointFiveMove Apply(Permutation permutation, IRandom random) { int length = permutation.Length; if (length == 1) throw new ArgumentException("Stochastic 2.5-SingleMoveGenerator: There cannot be an inversion move given a permutation of length 1.", "permutation"); int index1 = random.Next(length - 1); int index2 = random.Next(index1 + 1, length); if (permutation.PermutationType == PermutationTypes.RelativeUndirected) { if (length > 3) { while (index2 - index1 >= length - 2) index2 = random.Next(index1 + 1, length); } } bool isInvert = random.NextDouble() > 0.5; return new TwoPointFiveMove(index1, index2, isInvert); }
/// <summary> /// Performs the simulated binary crossover on a real vector. Each position is crossed with a probability of 50% and if crossed either a contracting crossover or an expanding crossover is performed, again with equal probability. /// For more details refer to the paper by Deb and Agrawal. /// </summary> /// <exception cref="ArgumentException">Thrown when the parents' vectors are of unequal length or when <paramref name="contiguity"/> is smaller than 0.</exception> /// <remarks> /// The manipulated value is not restricted by the (possibly) specified lower and upper bounds. Use the <see cref="BoundsChecker"/> to correct the values after performing the crossover. /// </remarks> /// <param name="random">The random number generator to use.</param> /// <param name="parent1">The first parent vector.</param> /// <param name="parent2">The second parent vector.</param> /// <param name="contiguity">The contiguity value that specifies how close a child should be to its parents (larger value means closer). The value must be greater or equal than 0. Typical values are in the range [2;5].</param> /// <returns>The vector resulting from the crossover.</returns> public static RealVector Apply(IRandom random, RealVector parent1, RealVector parent2, DoubleValue contiguity) { if (parent1.Length != parent2.Length) throw new ArgumentException("SimulatedBinaryCrossover: Parents are of unequal length"); if (contiguity.Value < 0) throw new ArgumentException("SimulatedBinaryCrossover: Contiguity value is smaller than 0", "contiguity"); int length = parent1.Length; RealVector result = new RealVector(length); for (int i = 0; i < length; i++) { if (length == 1 || random.NextDouble() < 0.5) { // cross this variable double u = random.NextDouble(); double beta = 0; if (u < 0.5) { // if u is smaller than 0.5 perform a contracting crossover beta = Math.Pow(2 * u, 1.0 / (contiguity.Value + 1)); } else if (u > 0.5) { // otherwise perform an expanding crossover beta = Math.Pow(0.5 / (1.0 - u), 1.0 / (contiguity.Value + 1)); } else if (u == 0.5) beta = 1; if (random.NextDouble() < 0.5) result[i] = ((parent1[i] + parent2[i]) / 2.0) - beta * 0.5 * Math.Abs(parent1[i] - parent2[i]); else result[i] = ((parent1[i] + parent2[i]) / 2.0) + beta * 0.5 * Math.Abs(parent1[i] - parent2[i]); } else result[i] = parent1[i]; } return result; }
/// <summary> /// Performs the polynomial mutation on a single position in the real vector. /// </summary> /// <param name="random">The random number generator to use.</param> /// <param name="vector">The vector that should be manipulated.</param> /// <param name="contiguity">A parameter describing the shape of the probability density function which influences the strength of the manipulation.</param> /// <param name="maxManipulation">The maximum strength of the manipulation.</param> public static void Apply(IRandom random, RealVector vector, DoubleValue contiguity, DoubleValue maxManipulation) { if (contiguity.Value < 0) throw new ArgumentException("PolynomialAllPositionManipulator: Contiguity value is smaller than 0", "contiguity"); double u, delta = 0; for (int index = 0; index < vector.Length; index++) { u = random.NextDouble(); if (u < 0.5) { delta = Math.Pow(2 * u, 1.0 / (contiguity.Value + 1)) - 1.0; } else if (u >= 0.5) { delta = 1.0 - Math.Pow(2.0 - 2.0 * u, 1.0 / (contiguity.Value + 1)); } vector[index] += delta * maxManipulation.Value; } }
/// <summary> /// Performs a uniform crossover between two binary 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 binary vector, resulting from the uniform crossover.</returns> public static BinaryVector Apply(IRandom random, BinaryVector parent1, BinaryVector parent2) { if (parent1.Length != parent2.Length) throw new ArgumentException("UniformCrossover: The parents are of different length."); int length = parent1.Length; bool[] result = new bool[length]; for (int i = 0; i < length; i++) { if (random.NextDouble() < 0.5) result[i] = parent1[i]; else result[i] = parent2[i]; } return new BinaryVector(result); }
public static PotvinEncoding Apply(IRandom random, PotvinEncoding parent1, PotvinEncoding parent2, IVRPProblemInstance problemInstance, bool allowInfeasible) { PotvinEncoding child = parent1.Clone() as PotvinEncoding; Tour newTour = new Tour(); int cities = problemInstance.Cities.Value; if (cities > 0) { int breakPoint1 = random.Next(1, cities + 1); Tour tour1 = FindRoute(child, breakPoint1); breakPoint1 = tour1.Stops.IndexOf(breakPoint1); for (int i = 0; i < breakPoint1; i++) newTour.Stops.Add(tour1.Stops[i]); int breakPoint2 = random.Next(1, cities + 1); Tour tour2 = FindRoute(parent2, breakPoint2); breakPoint2 = tour2.Stops.IndexOf(breakPoint2); for (int i = breakPoint2; i < tour2.Stops.Count; i++) newTour.Stops.Add(tour2.Stops[i]); int tour1Index = child.Tours.IndexOf(tour1); child.Tours.Remove(tour1); child.Tours.Insert(tour1Index, newTour); foreach (int city in tour1.Stops) if (FindRoute(child, city) == null && !child.Unrouted.Contains(city)) child.Unrouted.Add(city); foreach (int city in tour2.Stops) if (FindRoute(child, city) == null && !child.Unrouted.Contains(city)) child.Unrouted.Add(city); if (Repair(random, child, newTour, problemInstance, allowInfeasible) || allowInfeasible) { return child; } else { if (random.NextDouble() < 0.5) return parent1.Clone() as PotvinEncoding; else return parent2.Clone() as PotvinEncoding; } } else { return child; } }
/// <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 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; }
public static Schedule Apply(IRandom random, Schedule parent1, Schedule parent2, ItemList<Job> jobData, double mutProp) { var child = new Schedule(parent1.Resources.Count); //Reset scheduled tasks in result foreach (Job j in jobData) { foreach (Task t in j.Tasks) { t.IsScheduled = false; } } //GT-Algorithm //STEP 0 - Compute a list of "earliest operations" ItemList<Task> earliestTasksList = GTAlgorithmUtils.GetEarliestNotScheduledTasks(jobData); while (earliestTasksList.Count > 0) { //STEP 1 - Get earliest not scheduled operation with minimal earliest completing time Task minimal = GTAlgorithmUtils.GetTaskWithMinimalEC(earliestTasksList, child); int conflictedResourceNr = minimal.ResourceNr; Resource conflictedResource = child.Resources[conflictedResourceNr]; //STEP 2 - Compute a conflict set of all operations that can be scheduled on the conflicted resource ItemList<Task> conflictSet = GTAlgorithmUtils.GetConflictSetForTask(minimal, earliestTasksList, jobData, child); //STEP 3 - Select a task from the conflict set int progressOnResource = conflictedResource.Tasks.Count; Task selectedTask = null; if (random.NextDouble() < mutProp) { //Mutation selectedTask = conflictSet[random.Next(conflictSet.Count)]; } else { //Crossover selectedTask = SelectTaskFromConflictSet(conflictSet, ((random.Next(2) == 0) ? parent1 : parent2), conflictedResourceNr, progressOnResource); } //STEP 4 - Add the selected task to the current schedule selectedTask.IsScheduled = true; double startTime = GTAlgorithmUtils.ComputeEarliestStartTime(selectedTask, child); child.ScheduleTask(selectedTask.ResourceNr, startTime, selectedTask.Duration, selectedTask.JobNr); //STEP 5 - Back to STEP 1 earliestTasksList = GTAlgorithmUtils.GetEarliestNotScheduledTasks(jobData); } return child; }
/// <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; }
/// <summary> /// Performs the cyclic crossover on <paramref name="parent1"/> and <paramref name="parent2"/>. /// </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> /// First this method randomly determines from which parent to start with equal probability. /// Then it copies the first cycle from the chosen parent starting from index 0 in the permutation. /// After the cycle is complete it copies the next cycle starting from the index closest to 0 which was not yet copied from the other parent. /// It continues to switch between parents for each completed cycle until no new cycle is found anymore.<br /><br /> /// The stochasticity of this operator is rather low. There are only two possible outcomes for a given pair of parents. /// </remarks> /// <exception cref="ArgumentException">Thrown if the two parents are not of equal length.</exception> /// <param name="random">The random number generator.</param> /// <param name="parent1">The parent scope 1 to cross over.</param> /// <param name="parent2">The parent scope 2 to cross over.</param> /// <returns>The created cross over permutation as int array.</returns> public static Permutation Apply(IRandom random, Permutation parent1, Permutation parent2) { if (parent1.Length != parent2.Length) throw new ArgumentException("CyclicCrossover: The parent permutations are of unequal length."); int length = parent1.Length; int[] result = new int[length]; bool[] indexCopied = new bool[length]; int[] invParent1 = new int[length]; int[] invParent2 = new int[length]; // calculate inverse mappings (number -> index) for parent1 and parent2 try { for (int i = 0; i < length; i++) { invParent1[parent1[i]] = i; invParent2[parent2[i]] = i; } } catch (IndexOutOfRangeException) { throw new InvalidOperationException("CyclicCrossover: The permutation must consist of numbers in the interval [0;N) with N = length of the permutation."); } // randomly choose whether to start copying from parent1 or parent2 bool copyFromParent1 = ((random.NextDouble() < 0.5) ? (false) : (true)); int j = 0; do { do { if (copyFromParent1) { result[j] = parent1[j]; // copy number at position j from parent1 indexCopied[j] = true; j = invParent2[result[j]]; // set position j to the position of the copied number in parent2 } else { result[j] = parent2[j]; // copy number at position j from parent2 indexCopied[j] = true; j = invParent1[result[j]]; // set position j to the position of the copied number in parent1 } } while (!indexCopied[j]); copyFromParent1 = !copyFromParent1; j = 0; while (j < length && indexCopied[j]) j++; } while (j < length); return new Permutation(parent1.PermutationType, result); }