You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

242 lines
7.0 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkAmoebaMinimizer.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/**
* @class vtkAmoebaMinimizer
* @brief nonlinear optimization with a simplex
*
* vtkAmoebaMinimizer will modify a set of parameters in order to find
* the minimum of a specified function. The method used is commonly
* known as the amoeba method, it constructs an n-dimensional simplex
* in parameter space (i.e. a tetrahedron if the number or parameters
* is 3) and moves the vertices around parameter space until a local
* minimum is found. The amoeba method is robust, reasonably efficient,
* but is not guaranteed to find the global minimum if several local
* minima exist.
*/
#ifndef vtkAmoebaMinimizer_h
#define vtkAmoebaMinimizer_h
#include "vtkCommonMathModule.h" // For export macro
#include "vtkObject.h"
class VTKCOMMONMATH_EXPORT vtkAmoebaMinimizer : public vtkObject
{
public:
static vtkAmoebaMinimizer* New();
vtkTypeMacro(vtkAmoebaMinimizer, vtkObject);
void PrintSelf(ostream& os, vtkIndent indent) override;
/**
* Specify the function to be minimized. When this function
* is called, it must get the parameter values by calling
* GetParameterValue() for each parameter, and then must
* call SetFunctionValue() to tell the minimizer what the result
* of the function evaluation was. The number of function
* evaluations used for the minimization can be retrieved
* using GetFunctionEvaluations().
*/
void SetFunction(void (*f)(void*), void* arg);
/**
* Set a function to call when a void* argument is being discarded.
*/
void SetFunctionArgDelete(void (*f)(void*));
//@{
/**
* Set the initial value for the specified parameter. Calling
* this function for any parameter will reset the Iterations
* and the FunctionEvaluations counts to zero. You must also
* use SetParameterScale() to specify the step size by which the
* parameter will be modified during the minimization. It is
* preferable to specify parameters by name, rather than by
* number.
*/
void SetParameterValue(const char* name, double value);
void SetParameterValue(int i, double value);
//@}
//@{
/**
* Set the scale to use when modifying a parameter, i.e. the
* initial amount by which the parameter will be modified
* during the search for the minimum. It is preferable to
* identify scalars by name rather than by number.
*/
void SetParameterScale(const char* name, double scale);
double GetParameterScale(const char* name);
void SetParameterScale(int i, double scale);
double GetParameterScale(int i) { return this->ParameterScales[i]; }
//@}
//@{
/**
* Get the value of a parameter at the current stage of the minimization.
* Call this method within the function that you are minimizing in order
* to get the current parameter values. It is preferable to specify
* parameters by name rather than by index.
*/
double GetParameterValue(const char* name);
double GetParameterValue(int i) { return this->ParameterValues[i]; }
//@}
/**
* For completeness, an unchecked method to get the name for particular
* parameter (the result will be nullptr if no name was set).
*/
const char* GetParameterName(int i) { return this->ParameterNames[i]; }
/**
* Get the number of parameters that have been set.
*/
int GetNumberOfParameters() { return this->NumberOfParameters; }
/**
* Initialize the minimizer. This will reset the number of parameters to
* zero so that the minimizer can be reused.
*/
void Initialize();
/**
* Iterate until the minimum is found to within the specified tolerance,
* or until the MaxIterations has been reached.
*/
virtual void Minimize();
/**
* Perform one iteration of minimization. Returns zero if the tolerance
* stopping criterion has been met.
*/
virtual int Iterate();
//@{
/**
* Get the function value resulting from the minimization.
*/
vtkSetMacro(FunctionValue, double);
double GetFunctionValue() { return this->FunctionValue; }
//@}
//@{
/**
* Set the amoeba contraction ratio. The default value of 0.5 gives
* fast convergence, but larger values such as 0.6 or 0.7 provide
* greater stability.
*/
vtkSetClampMacro(ContractionRatio, double, 0.5, 1.0);
vtkGetMacro(ContractionRatio, double);
//@}
//@{
/**
* Set the amoeba expansion ratio. The default value is 2.0, which
* provides rapid expansion. Values between 1.1 and 2.0 are valid.
*/
vtkSetClampMacro(ExpansionRatio, double, 1.0, 2.0);
vtkGetMacro(ExpansionRatio, double);
//@}
//@{
/**
* Specify the value tolerance to aim for during the minimization.
*/
vtkSetMacro(Tolerance, double);
vtkGetMacro(Tolerance, double);
//@}
//@{
/**
* Specify the parameter tolerance to aim for during the minimization.
*/
vtkSetMacro(ParameterTolerance, double);
vtkGetMacro(ParameterTolerance, double);
//@}
//@{
/**
* Specify the maximum number of iterations to try before giving up.
*/
vtkSetMacro(MaxIterations, int);
vtkGetMacro(MaxIterations, int);
//@}
//@{
/**
* Return the number of iterations that have been performed. This
* is not necessarily the same as the number of function evaluations.
*/
vtkGetMacro(Iterations, int);
//@}
//@{
/**
* Return the number of times that the function has been evaluated.
*/
vtkGetMacro(FunctionEvaluations, int);
//@}
/**
* Evaluate the function. This is usually called internally by the
* minimization code, but it is provided here as a public method.
*/
void EvaluateFunction();
protected:
vtkAmoebaMinimizer();
~vtkAmoebaMinimizer() override;
void (*Function)(void*);
void (*FunctionArgDelete)(void*);
void* FunctionArg;
int NumberOfParameters;
char** ParameterNames;
double* ParameterValues;
double* ParameterScales;
double FunctionValue;
double ContractionRatio;
double ExpansionRatio;
double Tolerance;
double ParameterTolerance;
int MaxIterations;
int Iterations;
int FunctionEvaluations;
private:
// specific to amoeba simplex minimization
double** AmoebaVertices;
double* AmoebaValues;
double* AmoebaSum;
double AmoebaSize;
double AmoebaHighValue;
int AmoebaNStepsNoImprovement;
void InitializeAmoeba();
void GetAmoebaParameterValues();
void TerminateAmoeba();
double TryAmoeba(double sum[], int high, double fac);
int PerformAmoeba();
int CheckParameterTolerance();
vtkAmoebaMinimizer(const vtkAmoebaMinimizer&) = delete;
void operator=(const vtkAmoebaMinimizer&) = delete;
};
#endif