/// <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);
        }
Example #3
0
        /// <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());
        }
Example #4
0
        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);
        }