protected override DecisionVector GetNewDecisionVector() { if (InitialVerticesStillUnevaluated.Count > 0) { // Still creating the first simplex return(InitialVerticesStillUnevaluated.First()); } else { //We're into the optimisation if (VerticesNotEvaluated.Count == 0) { try { //Create new individual var newDv = OperationsManager.PerformOperation((Simplex)Population, CurrentOperation); VerticesNotEvaluated.Add(newDv); return(newDv); } catch (ArgumentOutOfRangeException) { // We have gone 'out of bounds' - this is it for this optimisation. return(DecisionVector.CreateForEmpty()); } } else { //Provide the same individual back again return(VerticesNotEvaluated.First()); } } }
public void InvalidRoutes_ThrowError() { var correctDs = DecisionSpace.CreateForUniformIntArray(3, 0, 1); var tsp = new TravellingSalesman("A Tale of Two Cities", new List <double[]>() { new[] { 0.0, 0 }, new[] { 1.0, 0 } }, DecisionVector.CreateFromArray(DecisionSpace.CreateForUniformIntArray(3, 0, 2), new[] { 0, 1, 0 })); // Empty route Assert.Throws <ArgumentOutOfRangeException>(() => tsp.Evaluate(DecisionVector.CreateForEmpty())); // Route that is too long with location (2) that doesn't exist Assert.Throws <ArgumentOutOfRangeException>(() => tsp.Evaluate( DecisionVector.CreateFromArray(DecisionSpace.CreateForUniformIntArray(4, 0, 2), new[] { 0, 2, 1, 0 }))); // Route with location (2) that doesn't exist Assert.Throws <ArgumentOutOfRangeException>(() => tsp.Evaluate( DecisionVector.CreateFromArray(correctDs, new[] { 0, 2, 0 }))); }
/// <summary> /// Gets a new Decision Vector, based on the PCX logic. /// </summary> /// <param name="parents">A list of parent <see cref="DecisionVector"/>s.</param> /// <returns>A new <see cref="DecisionVector"/>.</returns> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown if: /// - there are less than two parents; or /// - the parents have different length or zero length decision vectors; or /// - any of the parents have non-continuous Decision Vector elements. /// </exception> public DecisionVector Operate(params DecisionVector[] parents) { if (parents.Length < 2) { throw new ArgumentOutOfRangeException(nameof(parents), "There must be at least two parents."); } // TODO: These calls to .Any() are slow - can we remove the error checking? if (parents.Any(p => p.GetContinuousElements().Count == 0)) { throw new ArgumentOutOfRangeException(nameof(parents), "Parents must have non-zero length decision vectors."); } if (parents.Any(p => p.GetContinuousElements().Count != parents.First().Count)) { throw new ArgumentOutOfRangeException(nameof(parents), "Parents must have the same length and fully continuous decision vectors."); } // 1: Pre-process var parentDVs = Matrix <double> .Build.DenseOfColumns(parents.Select(dv => dv.Select(d => (double)d))); var motherDV = Vector <double> .Build.DenseOfArray(parents.ElementAt(0).Select(d => (double)d).ToArray()); // 1a: centroid of all parents var centroid = parentDVs.RowSums().Divide(parents.Count()); // 1b: vector distance from centroid to mother (following Deb's C code, not paper) var motherCentroidVectorDistance = centroid - motherDV; var motherCentroidAbsoluteDistance = motherCentroidVectorDistance.L2Norm(); if (motherCentroidAbsoluteDistance < 1e-20) { return(DecisionVector.CreateForEmpty()); } // 1c: vector distance from other parents to mother var otherParentDVs = parentDVs.RemoveColumn(0); var parentMotherVectorDistances = otherParentDVs.EnumerateColumns() .Select(v => v - motherDV).ToArray(); var parentMotherAbsoluteDistances = parentMotherVectorDistances.Select(v => v.L2Norm()).ToArray(); if (parentMotherAbsoluteDistances.Any(d => d < 1e-20)) { return(DecisionVector.CreateForEmpty()); } // 1d: perpendicular distances from other parents to centroid-mother vector var orthogonalDistances = parentMotherVectorDistances .Select((v, i) => parentMotherAbsoluteDistances.ElementAt(i) * Math.Sqrt(1.0 - Math.Pow( v.DotProduct(motherCentroidVectorDistance) / (parentMotherAbsoluteDistances.ElementAt(i) * motherCentroidAbsoluteDistance), 2.0))); var meanOrthogonalDistance = orthogonalDistances.Mean(); // 2: Now create a new individual var normRnd = new MathNet.Numerics.Distributions.Normal(rngManager.Rng); var samplesEta = new double[motherDV.Count]; normRnd.Samples(samplesEta); var newRandomDv = Vector <double> .Build.DenseOfArray(samplesEta) .Multiply(sigmaEta * meanOrthogonalDistance); //Remove component of randomness in direction of ? var offset1 = motherCentroidVectorDistance .Multiply(newRandomDv.DotProduct(motherCentroidVectorDistance)) .Divide(Math.Pow(motherCentroidAbsoluteDistance, 2.0)); newRandomDv -= offset1; var offset2 = motherCentroidVectorDistance .Multiply(sigmaZeta * normRnd.Sample()); newRandomDv += offset2; // Modification of Deb2002 which should maintain stability. var finalDv = motherDV + newRandomDv.Divide(Math.Sqrt(motherDV.Count)); return(DecisionVector.CreateFromArray(parents.First().GetDecisionSpace(), finalDv.ToArray())); }
/// <summary> /// Creates an empty hyperparameter manager. /// </summary> public HyperParameterManager() { HyperParameters = DecisionVector.CreateForEmpty(); }