|
Unfit
3.1.1
Data fitting and optimization software
|
#include <GenericOptimizer.hpp>
Public Member Functions | |
| GenericOptimizer () | |
| virtual | ~GenericOptimizer () |
| virtual int | FindMin (GenericCostFunction &cost_function, std::vector< double > &coordinates)=0 |
| virtual void | Reset ()=0 |
| void | ResetGenericOptimizer () |
| virtual double | GetCost (std::size_t index=0) const noexcept |
| virtual bool | GetIsPopulationBased () const noexcept |
| virtual std::size_t | GetNumberOfIterations () const noexcept |
| virtual std::size_t | GetNumberOfFunctionEvaluations () const noexcept |
| virtual std::vector< std::vector< double > > | GetPopulation () const |
| virtual std::vector< double > | GetSolution (std::size_t index=0) const |
| virtual void | SetPopulation (const std::vector< std::vector< double >> &population) |
Public Attributes | |
| Unfit::Bounds | bounds |
| Unfit::Options | options |
Protected Member Functions | |
| virtual bool | CalculateCost (GenericCostFunction &CostFunction, std::vector< double > &x) |
| void | GeneratePopulation (GenericCostFunction &CostFunction, std::size_t dimensions) |
| void | GenerateRandomEngines () |
| virtual bool | IsConverged (const std::vector< double > &best_member, std::size_t truncated_index=0) const |
| Checks to see if the population has converged. More... | |
| virtual void | PrintInitialOutput (double best_cost) const |
| virtual void | PrintIterationOutput (double best_cost) const |
| virtual void | PrintFinalOutput () const |
| virtual void | SortPopulation () noexcept |
Protected Attributes | |
| std::vector< std::vector< double > > | population_ |
| std::vector< std::mt19937 > | random_engines_ |
| std::atomic< std::size_t > | function_evaluations_ |
| std::atomic< std::size_t > | iterations_ |
| bool | is_population_based_ |
Private Member Functions | |
| std::vector< double > | GeneratePopulationMember (GenericCostFunction &CostFunction, std::vector< std::uniform_real_distribution< double >> &distributions, std::size_t dimensions, std::size_t mem) |
A generic base class for optimization methods to derive from. This defines the FindMin interface through which the optimization is performed, but is not a pure interface class as it may also contains common features for the optimization algorithms.
| Unfit::GenericOptimizer::GenericOptimizer | ( | ) |
Default constructor. Here we override the generated one as we need to initialize the member variables to something sensible.
|
virtual |
As we are deriving from this class, the destructor should be virtual. In this case (at present) we have nothing that will not be deleted when the class goes out of scope so an empty destructor method is fine.
|
protectedvirtual |
This method calls a cost function that has been derived from GenericCostFunction with a specified set of parameters. GenericCostFunction returns a vector of residuals (as is needed by the LevenbergMarquardt algorithm) and this function uses a sum-of-squared residuals approach to convert the vector of residuals into a single cost value. This method also increments the number of function evaluations.
| CostFunction | The cost function to be evaluated |
| x | The parameters with which the cost function will be evaluated |
|
pure virtual |
All derived classes must implement the FindMin method. This is the main method that should be called to perform an optimization.
| cost_function | The cost function to be minimized |
| coordinates | On entry this is the initial guess of the coordinates that need fitting. On exit this is overwritten by the final result from the fitting procedure. |
Implemented in Unfit::ParticleSwarm, Unfit::SimulatedAnnealing, Unfit::NelderMead, Unfit::GeneticAlgorithm, Unfit::DifferentialEvolution, Unfit::LevenbergMarquardt, and Unfit::TestGenericOptimizer.
|
protected |
This method creates a population that follows a uniform random distribution between the specified bounds. It is recommended that you set sensible bounds as the defaults are +/- max double, which can make population generation take a very long time. Costs are calculated via the provided cost function and are appended to the end of each population member. Any member that does not compute a valid cost is automatically discarded and regenerated. The population is not sorted within this method.
| CostFunction | The function used to evaluate the cost of each member |
| dimensions | The number of dimensions for each member |
|
private |
This method generates a single population member for the GeneratePopulation method. Each parameter in the member is generated between the specified bounds (with the default bounds being +/- max(double), and each has its own random number generator (to allow parallel execution)
| CostFunction | The cost function to be optimised |
| distributions | A uniform distribution with the correct bounds for each dimension |
| dimensions | The number of dimensions in the generated member |
| mem | The index of the population member to be generated |
|
protected |
This method generates set of random number engines (one for each member of the population) based on a random seed. The random seed provided in the options.SetRandomSeed() is then used to generate random seeds for each of the engines. There needs to be one per member so all of the member calculations can be done in parallel.
|
virtualnoexcept |
This method which returns the cost of a particular member of the current solution. For optimizers where more than one cost is stored the optional parameter can be used to choose which cost to get. The costs are not guaranteed to be sorted. If an invalid member index is passed in as an argument the returned cost will be infinity.
DifferentialEvolution: Members are unsorted
GeneticAlgorithm: Members are sorted (best = 0, worst = n)
LevenbergMarquardt: Only one cost is stored (index = 0)
NelderMead: Members are sorted (best = 0, worst = n)
| index | The index of the member whose cost will be returned |
|
virtualnoexcept |
This method returns whether or not the current optimization method is population based (e.g. Differential Evolution) or not (e.g Nelder-Mead).
|
virtualnoexcept |
This method returns the number of function evaluations the optimizer has performed up to this point.
|
virtualnoexcept |
This method returns the number of iterations the optimizer has gone through up to this point.
|
virtual |
This method returns the stored population with the costs appended to each member. There is no guarantee that the population will be sorted.
|
virtual |
This method returns a member of the current solution. For optimizers where more than one solution is stored (e.g. a population) the optional parameter can be used to choose which solution to get. The solutions are not guaranteed to be sorted. If an invalid member index is passed in as an argument the returned member will be empty. The cost is not appended to the end of the member that is returned.
DifferentialEvolution: Members are unsorted
GeneticAlgorithm: Members are sorted (best = 0, worst = n)
LevenbergMarquardt: Only one member is stored (index = 0)
NelderMead: Members are sorted (best = 0, worst = n)
| index | The index of the member to be returned |
|
protectedvirtual |
Checks to see if the population has converged.
This method checks to see if the population has converged. In particular, it checks three things - the best cost, the spread of costs in the population, and the spread of the population coordinates in each dimension. In order to be considered converged, either the best cost has to be less than the cost tolerance, or BOTH the cost and the geometry have to be converged to the same point. Details on the second case are given below.
Cost: Uses options.GetCostTolerance(). If the best cost is < 1.0 then the difference between the best and worst costs must be less than the cost tolerance. If the best cost is > 1.0 then the difference between the best and worst costs must be less than the best_cost*cost_tolerance.
Geometry: Uses options.GetGeometricTolerance(). In each dimension, if the position with the best cost is < 1.0 then the difference between all member locations and the best member location must be less than the geometric tolerance. If the position with the best cost (again separately for each dimension) is > 1.0 then the difference between the best location and all other member locations must be less than best_location*geometric_tolerance.
| best_member | The best member of the current population (with cost) |
| truncated_index | This parameter should be used if you only want to check part of the population for convergence. An example of this is GeneticAlgorithm which only checks the surviving members of the population for convergence. If you have a population 0..7, and you want to check only members 0,1,2,3, then truncated_index will 3. A truncated_index of zero will check the whole population. |
|
protectedvirtual |
Upon completion, this method prints the final population if the output level has set to be greater than two.
|
protectedvirtual |
Prints the column headers relating to iteration by iteration output to the screen if the output level has been set to be >= 1.
| best_cost | The best cost after the initial setup |
Reimplemented in Unfit::NelderMead.
|
protectedvirtual |
At each iteration, prints nothing if the output level is zero, the iteration number if the output level is one, and the iteration number plus the number of function evaluations and the best cost if the output level is greater than one.
| best_cost | The best cost after the latest iteration |
Reimplemented in Unfit::NelderMead.
|
pure virtual |
Each optimization class must implement a Reset method to set all of their parameters back to their default values.
Implemented in Unfit::ParticleSwarm, Unfit::SimulatedAnnealing, Unfit::NelderMead, Unfit::GeneticAlgorithm, Unfit::DifferentialEvolution, Unfit::LevenbergMarquardt, and Unfit::TestGenericOptimizer.
| void Unfit::GenericOptimizer::ResetGenericOptimizer | ( | ) |
This method resets all of the GenericOptimizer parameters back to their default values and should therefore be called from the Reset method of all optimizers deriving from this class.
|
virtual |
This method allows the user to set the population directly, rather than having it generated internally. Different methods will have a different minimum population size. In NelderMead, for example, the population size must be exactly one more than your number of dimensions (to get a simplex). Here the population that is passed in is not tested. Each optimizer will implement its own checks to make sure the population that is passed in is valid. Note also that the population should be passed in with the costs appended.
| population | The population to be used (with costs appended) |
|
protectedvirtualnoexcept |
This method sorts the members of the population into ascending order by their cost, such that the first member (index = 0) contains the lowest cost and the last member contains the highest cost.
| Unfit::Bounds Unfit::GenericOptimizer::bounds |
Use this object to set and manipulate bounds for your problem, if any.
|
protected |
Variable to store the number of function evaluations
|
protected |
Variable to store if the optimizer is population based
|
protected |
Variable to store the current number of iterations
| Unfit::Options Unfit::GenericOptimizer::options |
Use this object to set and manipulate the optimization options, such as the maximum number of iterations, tolerances and output levels.
|
protected |
A vector of population member vectors. The cost of a given member is appended to that member, so the size will be the number of dimensions in the problem + 1.
|
protected |
A vector containing one random engine for each member of the population
1.8.13