public static ItemArray <IItem> Apply(IItem initiator, IItem guide, IntValue k, PercentValue n) { if (!(initiator is RealVector) || !(guide is RealVector)) { throw new ArgumentException("Cannot relink path because one of the provided solutions or both have the wrong type."); } if (n.Value <= 0.0) { throw new ArgumentException("RelinkingAccuracy must be greater than 0."); } RealVector v1 = initiator.Clone() as RealVector; RealVector v2 = guide as RealVector; if (v1.Length != v2.Length) { throw new ArgumentException("The solutions are of different length."); } IList <RealVector> solutions = new List <RealVector>(); for (int i = 0; i < k.Value; i++) { RealVector solution = v1.Clone() as RealVector; for (int j = 0; j < solution.Length; j++) { solution[j] = v1[j] + 1 / (k.Value - i) * (v2[j] - v1[j]); } solutions.Add(solution); } IList <IItem> selection = new List <IItem>(); if (solutions.Count > 0) { int noSol = (int)(solutions.Count * n.Value); if (noSol <= 0) { noSol++; } double stepSize = (double)solutions.Count / (double)noSol; for (int i = 0; i < noSol; i++) { selection.Add(solutions.ElementAt((int)((i + 1) * stepSize - stepSize * 0.5))); } } return(new ItemArray <IItem>(selection)); }
public override IOperation Apply() { RealVector bestSol = CurrentScope.Variables[SolutionParameter.ActualName].Value as RealVector; if (bestSol == null) { throw new ArgumentException("Cannot improve solution because it has the wrong type."); } var evaluator = Evaluator; double bestSolQuality = evaluator.Evaluate(bestSol); // create perturbed solutions RealVector[] simplex = new RealVector[bestSol.Length]; for (int i = 0; i < simplex.Length; i++) { simplex[i] = bestSol.Clone() as RealVector; simplex[i][i] += 0.1 * (Bounds[0, 1] - Bounds[0, 0]); if (simplex[i][i] > Bounds[0, 1]) { simplex[i][i] = Bounds[0, 1]; } if (simplex[i][i] < Bounds[0, 0]) { simplex[i][i] = Bounds[0, 0]; } } // improve solutions for (int i = 0; i < ImprovementAttempts.Value; i++) { // order according to their objective function value Array.Sort(simplex, (x, y) => evaluator.Evaluate(x).CompareTo(evaluator.Evaluate(y))); // calculate centroid RealVector centroid = new RealVector(bestSol.Length); foreach (var vector in simplex) { for (int j = 0; j < centroid.Length; j++) { centroid[j] += vector[j]; } } for (int j = 0; j < centroid.Length; j++) { centroid[j] /= simplex.Length; } // reflection RealVector reflectionPoint = new RealVector(bestSol.Length); for (int j = 0; j < reflectionPoint.Length; j++) { reflectionPoint[j] = centroid[j] + Alpha.Value * (centroid[j] - simplex[simplex.Length - 1][j]); } double reflectionPointQuality = evaluator.Evaluate(reflectionPoint); if (evaluator.Evaluate(simplex[0]) <= reflectionPointQuality && reflectionPointQuality < evaluator.Evaluate(simplex[simplex.Length - 2])) { simplex[simplex.Length - 1] = reflectionPoint; } // expansion if (reflectionPointQuality < evaluator.Evaluate(simplex[0])) { RealVector expansionPoint = new RealVector(bestSol.Length); for (int j = 0; j < expansionPoint.Length; j++) { expansionPoint[j] = centroid[j] + Beta.Value * (reflectionPoint[j] - centroid[j]); } simplex[simplex.Length - 1] = evaluator.Evaluate(expansionPoint) < reflectionPointQuality ? expansionPoint : reflectionPoint; } // contraction if (evaluator.Evaluate(simplex[simplex.Length - 2]) <= reflectionPointQuality && reflectionPointQuality < evaluator.Evaluate(simplex[simplex.Length - 1])) { RealVector outsideContractionPoint = new RealVector(bestSol.Length); for (int j = 0; j < outsideContractionPoint.Length; j++) { outsideContractionPoint[j] = centroid[j] + Gamma.Value * (reflectionPoint[j] - centroid[j]); } if (evaluator.Evaluate(outsideContractionPoint) <= reflectionPointQuality) { simplex[simplex.Length - 1] = outsideContractionPoint; if (evaluator.Evaluate(reflectionPoint) >= evaluator.Evaluate(simplex[simplex.Length - 1])) { RealVector insideContractionPoint = new RealVector(bestSol.Length); for (int j = 0; j < insideContractionPoint.Length; j++) { insideContractionPoint[j] = centroid[j] - Gamma.Value * (reflectionPoint[j] - centroid[j]); } if (evaluator.Evaluate(insideContractionPoint) < evaluator.Evaluate(simplex[simplex.Length - 1])) { simplex[simplex.Length - 1] = insideContractionPoint; } } } } // reduction for (int j = 1; j < simplex.Length; j++) { for (int k = 0; k < simplex[j].Length; k++) { simplex[j][k] = simplex[0][k] + Delta.Value * (simplex[j][k] - simplex[0][k]); } } } for (int i = 0; i < simplex[0].Length; i++) { if (simplex[0][i] > Bounds[0, 1]) { simplex[0][i] = Bounds[0, 1]; } if (simplex[0][i] < Bounds[0, 0]) { simplex[0][i] = Bounds[0, 0]; } } CurrentScope.Variables[SolutionParameter.ActualName].Value = simplex[0]; CurrentScope.Variables.Add(new Variable("LocalEvaluatedSolutions", ImprovementAttempts)); return(base.Apply()); }