/// <summary> /// Runs a set of parameter sets and returns the results. /// </summary> /// <param name="functionToMinimize"></param> /// <param name="threshold"></param> /// <param name="parameterSets"></param> /// <param name="best"></param> /// <returns></returns> public List <OptimizerResult> RunParameterSets( Func <double[], OptimizerResult> functionToMinimize, double threshold, double[][] parameterSets, out OptimizerResult best) { OptimizerResult bestResult = null; var results = new List <OptimizerResult>(); foreach (var parameterSet in parameterSets) { // Get the current parameters for the current point var result = functionToMinimize(parameterSet); results.Add(result); if (bestResult == null) { bestResult = result; } else if (result.Error < bestResult.Error) { bestResult = result; } if (result.Error < threshold) { break; } } best = bestResult; return(results); }
private IReadOnlyCollection <OptimizerResult> Optimize( Func <double[], OptimizerResult> functionToMinimize, double threshold, out OptimizerResult best) { var initialParameterSets = ProposeParameterSets(m_randomStartingPointsCount, null); // Initialize the search var results = new List <OptimizerResult>(); var initializationResults = RunParameterSets(functionToMinimize, threshold, initialParameterSets, out best); if ((best != null) && (best.Error < threshold)) { return(results); } results.AddRange(initializationResults); for (var iteration = 0; iteration < m_iterations; iteration++) { var parameterSets = ProposeParameterSets(m_functionEvaluationsPerIterationCount, results); var iterationResults = RunParameterSets(functionToMinimize, threshold, parameterSets, out best); results.AddRange(iterationResults); if ((best != null) && (best.Error < threshold)) { return(results); } } return(results); }
/// <summary> /// Optimization using swarm optimization. Returns results for all particles. /// </summary> /// <param name="functionToMinimize"></param> /// <returns></returns> public OptimizerResult[] Optimize(Func <double[], OptimizerResult> functionToMinimize) { var particles = new double[m_numberOfParticles][]; var particleVelocities = Enumerable.Range(0, m_numberOfParticles) .Select(p => new double[m_parameters.Length]) .ToArray(); // initialize max and min velocities var maxParticleVelocities = new double[m_parameters.Length]; var minParticleVelocities = new double[m_parameters.Length]; for (int i = 0; i < m_parameters.Length; i++) { maxParticleVelocities[i] = Math.Abs(m_parameters[i].Max - m_parameters[i].Min); minParticleVelocities[i] = -maxParticleVelocities[i]; } // initialize max and min parameter bounds var maxParameters = new double[m_parameters.Length]; var minParameters = new double[m_parameters.Length]; for (int i = 0; i < m_parameters.Length; i++) { maxParameters[i] = m_parameters[i].Max; minParameters[i] = m_parameters[i].Min; } var pBest = Enumerable.Range(0, m_numberOfParticles) .Select(p => new double[m_parameters.Length]) .ToArray(); var pBestScores = Enumerable.Range(0, m_numberOfParticles) .Select(p => double.MaxValue) .ToArray(); var gBest = new OptimizerResult(new double[m_parameters.Length], double.MaxValue); // random initialize particles for (int i = 0; i < m_numberOfParticles; i++) { particles[i] = RandomSearchOptimizer.SampleParameterSet(m_parameters, m_sampler); } // iterate for find best for (int iterations = 0; iterations < m_maxIterations; iterations++) { Parallel.For(0, m_numberOfParticles, new ParallelOptions { MaxDegreeOfParallelism = m_maxDegreeOfParallelism }, (i) => { var result = functionToMinimize(particles[i]); lock (m_bestLocker) { if (result.Error < pBestScores[i]) { pBest[i] = result.ParameterSet; pBestScores[i] = result.Error; } if (result.Error < gBest.Error) { gBest = new OptimizerResult(result.ParameterSet.ToArray(), result.Error); //Trace.WriteLine(gBest.Error); } } }); for (int i = 0; i < m_numberOfParticles; i++) { //v[] = v[] + c1 * rand() * (pbest[] - present[]) + c2 * rand() * (gbest[] - present[]) particleVelocities[i] = particleVelocities[i].Add(pBest[i].Subtract(particles[i]).Multiply(m_c1 * m_random.NextDouble()) .Add(gBest.ParameterSet.Subtract(particles[i]).Multiply(m_c2 * m_random.NextDouble()))); BoundCheck(particleVelocities[i], maxParticleVelocities, minParticleVelocities); //present[] = persent[] + v[] particles[i] = particles[i].Add(particleVelocities[i]); BoundCheck(particles[i], maxParameters, minParameters); } } var results = new List <OptimizerResult>(); for (int i = 0; i < m_numberOfParticles; i++) { results.Add(new OptimizerResult(pBest[i], pBestScores[i])); } return(results.ToArray()); }
private IReadOnlyCollection <OptimizerResult> Optimize(Func <double[], OptimizerResult> functionToMinimize, double threshold, out OptimizerResult best) { OptimizerResult bestResult = null; // Generate the cartesian product between all parameters var grid = CartesianProduct(m_parameters); // Initialize the search var results = new ConcurrentBag <OptimizerResult>(); if (!m_runParallel) { foreach (var param in grid) { // Get the current parameters for the current point var result = functionToMinimize(param); results.Add(result); if (bestResult == null) { bestResult = result; } else if (result.Error < bestResult.Error) { bestResult = result; } if (result.Error < threshold) { break; } } } else { var rangePartitioner = Partitioner.Create(grid, true); var options = new ParallelOptions { MaxDegreeOfParallelism = m_maxDegreeOfParallelism }; Parallel.ForEach(rangePartitioner, options, (param, loopState) => { // Get the current parameters for the current point var result = functionToMinimize(param); results.Add(result); lock (results) { if (bestResult == null) { bestResult = result; } else if (result.Error < bestResult.Error) { bestResult = result; } } if (result.Error < threshold) { loopState.Break(); } }); } best = bestResult; return(results); }
/// <summary> /// Optimization using swarm optimization. /// Returns the final results ordered from best to worst (minimized). /// </summary> /// <param name="functionToMinimize"></param> /// <returns></returns> public OptimizerResult[] Optimize(Func <double[], OptimizerResult> functionToMinimize) { var particles = new double[m_numberOfParticles][]; var particleVelocities = Enumerable.Range(0, m_numberOfParticles) .Select(p => new double[m_parameters.Length]) .ToArray(); // initialize max and min velocities var maxParticleVelocities = new double[m_parameters.Length]; var minParticleVelocities = new double[m_parameters.Length]; for (int i = 0; i < m_parameters.Length; i++) { maxParticleVelocities[i] = Math.Abs(m_parameters[i].Max() - m_parameters[i].Min()); minParticleVelocities[i] = -maxParticleVelocities[i]; } // initialize max and min parameter bounds var maxParameters = new double[m_parameters.Length]; var minParameters = new double[m_parameters.Length]; for (int i = 0; i < m_parameters.Length; i++) { maxParameters[i] = m_parameters[i].Max(); minParameters[i] = m_parameters[i].Min(); } var pBest = Enumerable.Range(0, m_numberOfParticles) .Select(p => new double[m_parameters.Length]) .ToArray(); var pBestScores = Enumerable.Range(0, m_numberOfParticles) .Select(p => double.MaxValue) .ToArray(); var gBest = new OptimizerResult(new double[m_parameters.Length], double.MaxValue); // random initialize particles for (int i = 0; i < m_numberOfParticles; i++) { particles[i] = CreateParticle(); } // iterate for find best for (int iterations = 0; iterations < m_maxIterations; iterations++) { for (int i = 0; i < m_numberOfParticles; i++) { var result = functionToMinimize(particles[i]); if (result.Error < pBestScores[i]) { pBest[i] = result.ParameterSet; pBestScores[i] = result.Error; } if (result.Error < gBest.Error) { gBest = new OptimizerResult(result.ParameterSet.ToArray(), result.Error); //Trace.WriteLine(gBest.Error); } } for (int i = 0; i < m_numberOfParticles; i++) { //v[] = v[] + c1 * rand() * (pbest[] - present[]) + c2 * rand() * (gbest[] - present[]) particleVelocities[i] = particleVelocities[i].Add(pBest[i].Subtract(particles[i]).Multiply(m_c1 * m_random.NextDouble()) .Add(gBest.ParameterSet.Subtract(particles[i]).Multiply(m_c2 * m_random.NextDouble()))); BoundCheck(particleVelocities[i], maxParticleVelocities, minParticleVelocities); //present[] = persent[] + v[] particles[i] = particles[i].Add(particleVelocities[i]); BoundCheck(particles[i], maxParameters, minParameters); } } var results = new List <OptimizerResult>(); for (int i = 0; i < m_numberOfParticles; i++) { results.Add(new OptimizerResult(pBest[i], pBestScores[i])); } return(results.Where(v => !double.IsNaN(v.Error)).OrderBy(r => r.Error).ToArray()); }
private IReadOnlyCollection <OptimizerResult> Optimize(Func <double[], OptimizerResult> functionToMinimize, double threshold, out OptimizerResult best) { OptimizerResult bestResult = null; var dim = m_parameters.Length; var initialPoint = new double[dim]; var allResults = new List <OptimizerResult>(); m_totalFunctionEvaluations = 0; for (var restarts = 0; restarts < m_maxRestarts; restarts++) { RandomRestartPoint(initialPoint); var prevBest = EvaluateFunction(functionToMinimize, initialPoint); var iterationsWithoutImprovement = 0; var concurrentResults = new ConcurrentBag <OptimizerResult> { new OptimizerResult(prevBest.ParameterSet, prevBest.Error) }; var options = new ParallelOptions { MaxDegreeOfParallelism = m_maxDegreeOfParallelism }; Parallel.For(0, dim, options, (i, loopState) => { var a = (0.02 + (0.08 * m_random.NextDouble())) * (m_parameters[i].Max - m_parameters[i].Min); // % simplex size between 2%-8% of min(xrange) var p = (a * ((Math.Sqrt(dim + 1) + dim) - 1)) / (dim * Math.Sqrt(2)); var q = (a * (Math.Sqrt(dim + 1) - 1)) / (dim * Math.Sqrt(2)); var x = initialPoint.ToArray(); x[i] = x[i] + p; for (var j = 0; j < dim; j++) { if (j != i) { x[j] = x[j] + q; } } BoundCheck(x); var result = EvaluateFunction(functionToMinimize, x); concurrentResults.Add(result); lock (concurrentResults) { if (bestResult == null) { bestResult = result; } else if (result.Error < bestResult.Error) { bestResult = result; } } if (result.Error < threshold) { loopState.Break(); } }); var results = concurrentResults.ToList(); if (bestResult.Error < threshold) { allResults.AddRange(results); break; } // simplex iter var iterations = 0; while (true) { results = results.OrderBy(r => r.Error).ToList(); var iterationBest = results.First(); // break after m_maxIterationsPrRestart if ((iterations >= m_maxIterationsPrRestart) && (m_maxIterationsPrRestart != 0)) { allResults.AddRange(results); break; } iterations++; if (iterationBest.Error < (prevBest.Error - m_noImprovementThreshold)) { iterationsWithoutImprovement = 0; prevBest = iterationBest; } else { iterationsWithoutImprovement++; } // break after no_improv_break iterations with no improvement if (iterationsWithoutImprovement >= m_maxIterationsWithoutImprovement) { allResults.AddRange(results); break; } // check if m_maxFunctionEvaluations is reached if ((m_totalFunctionEvaluations >= m_maxFunctionEvaluations) && (m_maxFunctionEvaluations != 0)) { allResults.AddRange(results); break; } // centroid var x0 = new double[dim]; foreach (var tup in results.Take(results.Count - 1)) { var parameters = tup.ParameterSet; for (var i = 0; i < parameters.Length; i++) { x0[i] += parameters[i] / (results.Count - 1); } } BoundCheck(x0); // reflection var last = results.Last(); var xr = x0.Add(x0.Subtract(last.ParameterSet).Multiply(m_alpha)); BoundCheck(xr); var refelctionScore = EvaluateFunction(functionToMinimize, xr); var first = results.First().Error; if ((first <= refelctionScore.Error) && (refelctionScore.Error < results[results.Count - 2].Error)) { results.RemoveAt(results.Count - 1); results.Add(refelctionScore); continue; } // expansion if (refelctionScore.Error < first) { var xe = x0.Add(x0.Subtract(last.ParameterSet).Multiply(m_gamma)); BoundCheck(xe); var expansionScore = EvaluateFunction(functionToMinimize, xe); if (expansionScore.Error < refelctionScore.Error) { results.RemoveAt(results.Count - 1); results.Add(expansionScore); continue; } else { results.RemoveAt(results.Count - 1); results.Add(refelctionScore); continue; } } // contraction var xc = x0.Add(x0.Subtract(last.ParameterSet).Multiply(m_rho)); BoundCheck(xc); var contractionScore = EvaluateFunction(functionToMinimize, xc); if (contractionScore.Error < last.Error) { results.RemoveAt(results.Count - 1); results.Add(contractionScore); continue; } // shrink var x1 = results[0].ParameterSet; var nres = new List <OptimizerResult>(); foreach (var tup in results) { var xs = x1.Add(x1.Subtract(tup.ParameterSet).Multiply(m_sigma)); BoundCheck(xs); var score = EvaluateFunction(functionToMinimize, xs); nres.Add(score); } results = nres.ToList(); } // check if m_maxFunctionEvaluations is reached if ((m_totalFunctionEvaluations >= m_maxFunctionEvaluations) && (m_maxFunctionEvaluations != 0)) { allResults.AddRange(results); break; } } best = bestResult; return(allResults); }
/// <summary> /// Runs a set of parameter sets and returns the results. /// </summary> /// <param name="functionToMinimize"></param> /// <param name="threshold"></param> /// <param name="parameterSets"></param> /// <param name="best"></param> /// <returns></returns> public IReadOnlyCollection <OptimizerResult> RunParameterSets( Func <double[], OptimizerResult> functionToMinimize, double threshold, double[][] parameterSets, out OptimizerResult best) { OptimizerResult bestResult = null; var results = new ConcurrentBag <OptimizerResult>(); if (!m_runParallel) { foreach (var parameterSet in parameterSets) { // Get the current parameters for the current point var result = functionToMinimize(parameterSet); results.Add(result); if (bestResult == null) { bestResult = result; } else if (result.Error < bestResult.Error) { bestResult = result; } if (result.Error < threshold) { break; } } } else { var rangePartitioner = Partitioner.Create(parameterSets, true); var options = new ParallelOptions { MaxDegreeOfParallelism = m_maxDegreeOfParallelism }; Parallel.ForEach( rangePartitioner, options, (param, loopState) => { // Get the current parameters for the current point var result = functionToMinimize(param); results.Add(result); lock (results) { if (bestResult == null) { bestResult = result; } else if (result.Error < bestResult.Error) { bestResult = result; } } if (result.Error < threshold) { loopState.Break(); } } ); } best = bestResult; return(results); }