You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
754 lines
20 KiB
754 lines
20 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkAmoebaMinimizer.cxx,v $
|
|
|
|
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.
|
|
|
|
=========================================================================*/
|
|
#include "vtkAmoebaMinimizer.h"
|
|
#include "vtkObjectFactory.h"
|
|
|
|
vtkCxxRevisionMacro(vtkAmoebaMinimizer, "$Revision: 1.4.14.1 $");
|
|
vtkStandardNewMacro(vtkAmoebaMinimizer);
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkAmoebaMinimizer::vtkAmoebaMinimizer()
|
|
{
|
|
this->Function = NULL;
|
|
this->FunctionArg = NULL;
|
|
this->FunctionArgDelete = NULL;
|
|
|
|
this->NumberOfParameters = 0;
|
|
this->ParameterNames = NULL;
|
|
this->ParameterValues = NULL;
|
|
this->ParameterScales = NULL;
|
|
|
|
this->FunctionValue = 0.0;
|
|
|
|
this->Tolerance = 1e-4;
|
|
this->MaxIterations = 1000;
|
|
this->Iterations = 0;
|
|
this->FunctionEvaluations = 0;
|
|
|
|
// specific to the amoeba
|
|
this->AmoebaVertices = NULL;
|
|
this->AmoebaValues = NULL;
|
|
this->AmoebaSum = NULL;
|
|
this->AmoebaNStepsNoImprovement = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkAmoebaMinimizer::~vtkAmoebaMinimizer()
|
|
{
|
|
this->TerminateAmoeba();
|
|
|
|
if ((this->FunctionArg) && (this->FunctionArgDelete))
|
|
{
|
|
(*this->FunctionArgDelete)(this->FunctionArg);
|
|
}
|
|
this->FunctionArg = NULL;
|
|
this->FunctionArgDelete = NULL;
|
|
this->Function = NULL;
|
|
|
|
if (this->ParameterNames)
|
|
{
|
|
for (int i = 0; i < this->NumberOfParameters; i++)
|
|
{
|
|
if (this->ParameterNames[i])
|
|
{
|
|
delete [] this->ParameterNames[i];
|
|
}
|
|
}
|
|
delete [] this->ParameterNames;
|
|
this->ParameterNames = NULL;
|
|
}
|
|
if (this->ParameterValues)
|
|
{
|
|
delete [] this->ParameterValues;
|
|
this->ParameterValues = NULL;
|
|
}
|
|
if (this->ParameterScales)
|
|
{
|
|
delete [] this->ParameterScales;
|
|
this->ParameterScales = NULL;
|
|
}
|
|
|
|
this->NumberOfParameters = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAmoebaMinimizer::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os, indent);
|
|
os << indent << "NumberOfParameters: " << this->GetNumberOfParameters() << "\n";
|
|
if (this->NumberOfParameters > 0)
|
|
{
|
|
int i;
|
|
|
|
os << indent << "ParameterValues: \n";
|
|
for (i = 0; i < this->NumberOfParameters; i++)
|
|
{
|
|
const char *name = this->GetParameterName(i);
|
|
os << indent << " ";
|
|
if (name)
|
|
{
|
|
os << name << ": ";
|
|
}
|
|
else
|
|
{
|
|
os << i << ": ";
|
|
}
|
|
os << this->GetParameterValue(i) << "\n";
|
|
}
|
|
|
|
os << indent << "ParameterScales: \n";
|
|
for (i = 0; i < this->NumberOfParameters; i++)
|
|
{
|
|
const char *name = this->GetParameterName(i);
|
|
os << indent << " ";
|
|
if (name)
|
|
{
|
|
os << name << ": ";
|
|
}
|
|
else
|
|
{
|
|
os << i << ": ";
|
|
}
|
|
os << this->GetParameterScale(i) << "\n";
|
|
}
|
|
}
|
|
|
|
os << indent << "FunctionValue: " << this->GetFunctionValue() << "\n";
|
|
os << indent << "FunctionEvaluations: " << this->GetFunctionEvaluations()
|
|
<< "\n";
|
|
os << indent << "Iterations: " << this->GetIterations() << "\n";
|
|
os << indent << "MaxIterations: " << this->GetMaxIterations() << "\n";
|
|
os << indent << "Tolerance: " << this->GetTolerance() << "\n";
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAmoebaMinimizer::SetFunction(void (*f)(void *), void *arg)
|
|
{
|
|
if ( f != this->Function || arg != this->FunctionArg )
|
|
{
|
|
// delete the current arg if there is one and a delete meth
|
|
if ((this->FunctionArg) && (this->FunctionArgDelete))
|
|
{
|
|
(*this->FunctionArgDelete)(this->FunctionArg);
|
|
}
|
|
this->Function = f;
|
|
this->FunctionArg = arg;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAmoebaMinimizer::SetFunctionArgDelete(void (*f)(void *))
|
|
{
|
|
if ( f != this->FunctionArgDelete)
|
|
{
|
|
this->FunctionArgDelete = f;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
double vtkAmoebaMinimizer::GetParameterValue(const char *name)
|
|
{
|
|
for (int i = 0; i < this->NumberOfParameters; i++)
|
|
{
|
|
if (this->ParameterNames[i] && strcmp(name,this->ParameterNames[i]) == 0)
|
|
{
|
|
return this->ParameterValues[i];
|
|
}
|
|
}
|
|
vtkErrorMacro("GetParameterValue: no parameter named " << name);
|
|
return 0.0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAmoebaMinimizer::SetParameterValue(const char *name, double val)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < this->NumberOfParameters; i++)
|
|
{
|
|
if (this->ParameterNames[i] && strcmp(name,this->ParameterNames[i]) == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
this->SetParameterValue(i, val);
|
|
|
|
if (!this->ParameterNames[i])
|
|
{
|
|
char *cp = new char[strlen(name)+8];
|
|
strcpy(cp,name);
|
|
this->ParameterNames[i] = cp;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAmoebaMinimizer::SetParameterValue(int i, double val)
|
|
{
|
|
if (i < this->NumberOfParameters)
|
|
{
|
|
if (this->ParameterValues[i] != val)
|
|
{
|
|
this->ParameterValues[i] = val;
|
|
this->Iterations = 0; // reset to start
|
|
this->FunctionEvaluations = 0;
|
|
this->Modified();
|
|
}
|
|
return;
|
|
}
|
|
|
|
int n = this->NumberOfParameters + 1;
|
|
|
|
char **newParameterNames = new char *[n];
|
|
double *newParameterValues = new double[n];
|
|
double *newParameterScales = new double[n];
|
|
|
|
for (int j = 0; j < this->NumberOfParameters; j++)
|
|
{
|
|
newParameterNames[j] = this->ParameterNames[j];
|
|
this->ParameterNames[j] = NULL; // or else it will be deleted in Initialize
|
|
newParameterValues[j] = this->ParameterValues[j];
|
|
newParameterScales[j] = this->ParameterScales[j];
|
|
}
|
|
|
|
newParameterNames[n-1] = 0;
|
|
newParameterValues[n-1] = val;
|
|
newParameterScales[n-1] = 1.0;
|
|
|
|
this->Initialize();
|
|
|
|
this->NumberOfParameters = n;
|
|
this->ParameterNames = newParameterNames;
|
|
this->ParameterValues = newParameterValues;
|
|
this->ParameterScales = newParameterScales;
|
|
|
|
this->Iterations = 0; // reset to start
|
|
this->FunctionEvaluations = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
double vtkAmoebaMinimizer::GetParameterScale(const char *name)
|
|
{
|
|
for (int i = 0; i < this->NumberOfParameters; i++)
|
|
{
|
|
if (this->ParameterNames[i] && strcmp(name,this->ParameterNames[i]) == 0)
|
|
{
|
|
return this->ParameterScales[i];
|
|
}
|
|
}
|
|
vtkErrorMacro("GetParameterScale: no parameter named " << name);
|
|
return 1.0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAmoebaMinimizer::SetParameterScale(const char *name, double scale)
|
|
{
|
|
for (int i = 0; i < this->NumberOfParameters; i++)
|
|
{
|
|
if (this->ParameterNames[i] && strcmp(name,this->ParameterNames[i]) == 0)
|
|
{
|
|
this->SetParameterScale(i, scale);
|
|
return;
|
|
}
|
|
}
|
|
vtkErrorMacro("SetParameterScale: no parameter named " << name);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAmoebaMinimizer::SetParameterScale(int i, double scale)
|
|
{
|
|
if (i < 0 || i > this->NumberOfParameters)
|
|
{
|
|
vtkErrorMacro("SetParameterScale: parameter number out of range: " << i);
|
|
return;
|
|
}
|
|
|
|
if (this->ParameterScales[i] != scale)
|
|
{
|
|
this->ParameterScales[i] = scale;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// reset the number of parameters to zero
|
|
void vtkAmoebaMinimizer::Initialize()
|
|
{
|
|
if (this->ParameterNames)
|
|
{
|
|
for (int i = 0; i < this->NumberOfParameters; i++)
|
|
{
|
|
if (this->ParameterNames[i])
|
|
{
|
|
delete [] this->ParameterNames[i];
|
|
}
|
|
}
|
|
delete [] this->ParameterNames;
|
|
this->ParameterNames = 0;
|
|
}
|
|
if (this->ParameterValues)
|
|
{
|
|
delete [] this->ParameterValues;
|
|
this->ParameterValues = 0;
|
|
}
|
|
if (this->ParameterScales)
|
|
{
|
|
delete [] this->ParameterScales;
|
|
this->ParameterScales = 0;
|
|
}
|
|
|
|
this->NumberOfParameters = 0;
|
|
this->Iterations = 0;
|
|
this->FunctionEvaluations = 0;
|
|
|
|
this->Modified();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAmoebaMinimizer::EvaluateFunction()
|
|
{
|
|
if (this->Function)
|
|
{
|
|
this->Function(this->FunctionArg);
|
|
}
|
|
this->FunctionEvaluations++;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkAmoebaMinimizer::Iterate()
|
|
{
|
|
if (this->Iterations == 0)
|
|
{
|
|
if (!this->Function)
|
|
{
|
|
vtkErrorMacro("Iterate: Function is NULL");
|
|
return 0;
|
|
}
|
|
this->InitializeAmoeba();
|
|
}
|
|
|
|
int improved = this->PerformAmoeba();
|
|
this->GetAmoebaParameterValues();
|
|
this->Iterations++;
|
|
|
|
return improved;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAmoebaMinimizer::Minimize()
|
|
{
|
|
if (this->Iterations == 0)
|
|
{
|
|
if (!this->Function)
|
|
{
|
|
vtkErrorMacro("Minimize: Function is NULL");
|
|
return;
|
|
}
|
|
this->InitializeAmoeba();
|
|
}
|
|
|
|
for (; this->Iterations < this->MaxIterations; this->Iterations++)
|
|
{
|
|
int improved = this->PerformAmoeba();
|
|
if (!improved)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
this->GetAmoebaParameterValues();
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
@COPYRIGHT :
|
|
Copyright 1993,1994,1995 David MacDonald,
|
|
McConnell Brain Imaging Centre,
|
|
Montreal Neurological Institute, McGill University.
|
|
Permission to use, copy, modify, and distribute this
|
|
software and its documentation for any purpose and without
|
|
fee is hereby granted, provided that the above copyright
|
|
notice appear in all copies. The author and McGill University
|
|
make no representations about the suitability of this
|
|
software for any purpose. It is provided "as is" without
|
|
express or implied warranty.
|
|
---------------------------------------------------------------------------- */
|
|
|
|
/* ------------------------------------------------
|
|
This code has been modified from the original. Several macros
|
|
have been expanded, functions have been renamed to match VTK
|
|
conventions, and the formatting has been changed.
|
|
*/
|
|
|
|
#define VTK_AMOEBA_FLIP_RATIO 1.0
|
|
#define VTK_AMOEBA_CONTRACT_RATIO 0.5
|
|
#define VTK_AMOEBA_STRETCH_RATIO 2.0
|
|
|
|
/* ----------------------------- MNI Header -----------------------------------
|
|
@NAME : vtkAmoebaNumericallyClose
|
|
@INPUT : n1
|
|
n2
|
|
threshold_ratio
|
|
@OUTPUT :
|
|
@RETURNS : true if the numbers are within the threshold ratio
|
|
@DESCRIPTION: Decides if two numbers are close to each other.
|
|
@METHOD :
|
|
@GLOBALS :
|
|
@CALLS :
|
|
@CREATED : 1993 David MacDonald
|
|
@MODIFIED : 2002 David Gobbi
|
|
---------------------------------------------------------------------------- */
|
|
|
|
#define VTK_AMOEBA_SMALLEST 1.0e-20
|
|
|
|
static int vtkAmoebaNumericallyClose(double n1,
|
|
double n2,
|
|
double threshold_ratio )
|
|
{
|
|
double avg, diff, abs_n1, abs_n2;
|
|
|
|
diff = n1 - n2;
|
|
if( diff < 0.0 )
|
|
{
|
|
diff = -diff;
|
|
}
|
|
|
|
abs_n1 = (n1 < 0.0 ? -n1 : n1);
|
|
abs_n2 = (n2 < 0.0 ? -n2 : n2);
|
|
|
|
if( abs_n1 < VTK_AMOEBA_SMALLEST || abs_n2 < VTK_AMOEBA_SMALLEST )
|
|
{
|
|
return( abs_n1 < threshold_ratio && abs_n2 < threshold_ratio );
|
|
}
|
|
|
|
avg = (n1 + n2) / 2.0;
|
|
|
|
if( avg == 0.0 )
|
|
{
|
|
return( diff <= threshold_ratio );
|
|
}
|
|
|
|
if( avg < 0.0 )
|
|
{
|
|
avg = -avg;
|
|
}
|
|
|
|
return( (diff / avg) <= threshold_ratio );
|
|
}
|
|
|
|
/* ----------------------------- MNI Header -----------------------------------
|
|
@NAME : InitializeAmoeba
|
|
@INPUT :
|
|
@OUTPUT :
|
|
@RETURNS :
|
|
@DESCRIPTION: Initializes the amoeba structure to minimize the function.
|
|
@METHOD :
|
|
@GLOBALS :
|
|
@CALLS :
|
|
@CREATED : 1993 David MacDonald
|
|
@MODIFIED : 2002 David Gobbi
|
|
---------------------------------------------------------------------------- */
|
|
|
|
void vtkAmoebaMinimizer::InitializeAmoeba()
|
|
{
|
|
int i, j;
|
|
|
|
this->TerminateAmoeba();
|
|
|
|
int n_parameters = this->NumberOfParameters;
|
|
this->AmoebaNStepsNoImprovement = 0;
|
|
this->AmoebaVertices = new double *[n_parameters+1];
|
|
this->AmoebaVertices[0] = new double[n_parameters*(n_parameters+1)];
|
|
|
|
for( i = 1 ; i < n_parameters+1 ; i++)
|
|
{
|
|
this->AmoebaVertices[i] = this->AmoebaVertices[i-1] + n_parameters;
|
|
}
|
|
|
|
this->AmoebaValues = new double[n_parameters+1];
|
|
|
|
this->AmoebaSum = new double[n_parameters];
|
|
|
|
for (j = 0; j < n_parameters; j++)
|
|
{
|
|
this->AmoebaSum[j] = 0.0;
|
|
}
|
|
|
|
for( i = 0 ; i < n_parameters+1 ; i++ )
|
|
{
|
|
for( j = 0; j < n_parameters ; j++ )
|
|
{
|
|
this->AmoebaVertices[i][j] = this->ParameterValues[j];
|
|
if( i > 0 && j == i - 1 )
|
|
{
|
|
this->AmoebaVertices[i][j] =
|
|
this->ParameterValues[j] + this->ParameterScales[j];
|
|
}
|
|
this->AmoebaSum[j] += this->ParameterValues[j];
|
|
}
|
|
}
|
|
for( i = 0 ; i < n_parameters+1 ; i++ )
|
|
{
|
|
for( j = 0; j < n_parameters; j++ )
|
|
{
|
|
this->ParameterValues[j] = this->AmoebaVertices[i][j];
|
|
}
|
|
this->EvaluateFunction();
|
|
this->AmoebaValues[i] = this->FunctionValue;
|
|
}
|
|
|
|
for ( j = 0 ; j < n_parameters ; j++ )
|
|
{
|
|
this->ParameterValues[j] = this->AmoebaVertices[0][j];
|
|
}
|
|
}
|
|
|
|
/* ----------------------------- MNI Header -----------------------------------
|
|
@NAME : GetAmoebaParameterValues
|
|
@INPUT :
|
|
@OUTPUT :
|
|
@RETURNS :
|
|
@DESCRIPTION: Passes back the current position of the amoeba (best value),
|
|
and returns the function value at that point.
|
|
@METHOD :
|
|
@GLOBALS :
|
|
@CALLS :
|
|
@CREATED : 1993 David MacDonald
|
|
@MODIFIED : 2002 David Gobbi
|
|
---------------------------------------------------------------------------- */
|
|
|
|
void vtkAmoebaMinimizer::GetAmoebaParameterValues()
|
|
{
|
|
int i, j, low;
|
|
|
|
low = 0;
|
|
for( i = 1 ; i < this->NumberOfParameters+1 ; i++ )
|
|
{
|
|
if( this->AmoebaValues[i] < this->AmoebaValues[low] )
|
|
{
|
|
low = i;
|
|
}
|
|
}
|
|
|
|
for( j = 0 ; j < this->NumberOfParameters ; j++ )
|
|
{
|
|
this->ParameterValues[j] = this->AmoebaVertices[low][j];
|
|
}
|
|
|
|
this->FunctionValue = this->AmoebaValues[low];
|
|
}
|
|
|
|
/* ----------------------------- MNI Header -----------------------------------
|
|
@NAME : TerminateAmoeba
|
|
@INPUT :
|
|
@OUTPUT :
|
|
@RETURNS :
|
|
@DESCRIPTION: Frees the amoeba.
|
|
@METHOD :
|
|
@GLOBALS :
|
|
@CALLS :
|
|
@CREATED : 1993 David MacDonald
|
|
@MODIFIED : 2002 David Gobbi
|
|
---------------------------------------------------------------------------- */
|
|
|
|
void vtkAmoebaMinimizer::TerminateAmoeba()
|
|
{
|
|
if (this->AmoebaVertices)
|
|
{
|
|
delete [] this->AmoebaVertices[0];
|
|
delete [] this->AmoebaVertices;
|
|
this->AmoebaVertices = NULL;
|
|
}
|
|
if (this->AmoebaValues)
|
|
{
|
|
delete [] this->AmoebaValues;
|
|
this->AmoebaValues = NULL;
|
|
}
|
|
if (this->AmoebaSum)
|
|
{
|
|
delete [] this->AmoebaSum;
|
|
this->AmoebaSum = NULL;
|
|
}
|
|
}
|
|
|
|
/* ----------------------------- MNI Header -----------------------------------
|
|
@NAME : TryAmoeba
|
|
@INPUT : sum
|
|
high
|
|
fac
|
|
@OUTPUT :
|
|
@RETURNS : value
|
|
@DESCRIPTION: Does a modification to the high vertex of the amoeba and
|
|
returns the value of the new point. If the new point is
|
|
better (smaller value), it replaces the high vertex of the
|
|
amoeba.
|
|
@METHOD :
|
|
@GLOBALS :
|
|
@CALLS :
|
|
@CREATED : 1993 David MacDonald
|
|
@MODIFIED : 2002 David Gobbi
|
|
---------------------------------------------------------------------------- */
|
|
|
|
double vtkAmoebaMinimizer::TryAmoeba(double sum[],
|
|
int high,
|
|
double fac )
|
|
{
|
|
int j;
|
|
double y_try, fac1, fac2;
|
|
double *parameters;
|
|
|
|
parameters = this->ParameterValues;
|
|
|
|
fac1 = (1.0 - fac) / this->NumberOfParameters;
|
|
fac2 = fac - fac1;
|
|
|
|
for( j = 0 ; j < this->NumberOfParameters ; j++ )
|
|
{
|
|
parameters[j] = (sum[j] * fac1 + this->AmoebaVertices[high][j] * fac2);
|
|
}
|
|
|
|
this->EvaluateFunction();
|
|
y_try = this->FunctionValue;
|
|
|
|
if( y_try < this->AmoebaValues[high] )
|
|
{
|
|
this->AmoebaValues[high] = y_try;
|
|
for( j = 0 ; j < this->NumberOfParameters ; j++ )
|
|
{
|
|
sum[j] += parameters[j] - this->AmoebaVertices[high][j];
|
|
this->AmoebaVertices[high][j] = parameters[j];
|
|
}
|
|
}
|
|
|
|
return( y_try );
|
|
}
|
|
|
|
#define N_STEPS_NO_IMPROVEMENT 20
|
|
|
|
/* ----------------------------- MNI Header -----------------------------------
|
|
@NAME : PerformAmoeba
|
|
@INPUT :
|
|
@OUTPUT :
|
|
|
|
@RETURNS : true if numerically significant improvement
|
|
@DESCRIPTION: Performs one iteration of an amoeba, returning true if a
|
|
numerically significant improvement has been found recently.
|
|
Even if it returns 0, you can keep calling this function,
|
|
since it may be contracting with no improvement, but will
|
|
eventually shrink small enough to get an improvment.
|
|
@METHOD :
|
|
@GLOBALS :
|
|
@CALLS :
|
|
@CREATED : 1993 David MacDonald
|
|
@MODIFIED : 2002 David Gobbi
|
|
---------------------------------------------------------------------------- */
|
|
|
|
int vtkAmoebaMinimizer::PerformAmoeba()
|
|
{
|
|
int i, j, low, high, next_high;
|
|
double y_try, y_save;
|
|
int improvement_found;
|
|
|
|
improvement_found = 1;
|
|
|
|
if( this->AmoebaValues[0] > this->AmoebaValues[1] )
|
|
{
|
|
high = 0;
|
|
next_high = 1;
|
|
}
|
|
else
|
|
{
|
|
high = 1;
|
|
next_high = 0;
|
|
}
|
|
|
|
low = next_high;
|
|
|
|
for( i = 2 ; i < this->NumberOfParameters+1 ; i++ )
|
|
{
|
|
if( this->AmoebaValues[i] < this->AmoebaValues[low] )
|
|
{
|
|
low = i;
|
|
}
|
|
else if( this->AmoebaValues[i] > this->AmoebaValues[high] )
|
|
{
|
|
next_high = high;
|
|
high = i;
|
|
}
|
|
else if( this->AmoebaValues[i] > this->AmoebaValues[next_high] )
|
|
{
|
|
next_high = i;
|
|
}
|
|
}
|
|
|
|
if( vtkAmoebaNumericallyClose( this->AmoebaValues[low],
|
|
this->AmoebaValues[high],
|
|
this->Tolerance ) )
|
|
{
|
|
++this->AmoebaNStepsNoImprovement;
|
|
if( this->AmoebaNStepsNoImprovement >= N_STEPS_NO_IMPROVEMENT )
|
|
{
|
|
improvement_found = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->AmoebaNStepsNoImprovement = 0;
|
|
}
|
|
|
|
y_try = this->TryAmoeba( this->AmoebaSum, high, -VTK_AMOEBA_FLIP_RATIO );
|
|
|
|
if( y_try <= this->AmoebaValues[low] )
|
|
{
|
|
y_try = TryAmoeba( this->AmoebaSum, high, VTK_AMOEBA_STRETCH_RATIO );
|
|
}
|
|
else if( y_try >= this->AmoebaValues[next_high] )
|
|
{
|
|
y_save = this->AmoebaValues[high];
|
|
y_try = TryAmoeba( this->AmoebaSum, high, VTK_AMOEBA_CONTRACT_RATIO );
|
|
|
|
if( y_try >= y_save )
|
|
{
|
|
for( i = 0 ; i < this->NumberOfParameters+1 ; i++)
|
|
{
|
|
if( i != low )
|
|
{
|
|
for( j = 0 ; j < this->NumberOfParameters ; j++ )
|
|
{
|
|
this->ParameterValues[j] = (this->AmoebaVertices[i][j] +
|
|
this->AmoebaVertices[low][j]) / 2.0;
|
|
this->AmoebaVertices[i][j] = this->ParameterValues[j];
|
|
}
|
|
|
|
this->EvaluateFunction();
|
|
this->AmoebaValues[i] = this->FunctionValue;
|
|
}
|
|
}
|
|
|
|
for( j = 0 ; j < this->NumberOfParameters ; j++ )
|
|
{
|
|
this->AmoebaSum[j] = 0.0;
|
|
for( i = 0 ; i < this->NumberOfParameters+1 ; i++ )
|
|
{
|
|
this->AmoebaSum[j] += this->AmoebaVertices[i][j];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return( improvement_found );
|
|
}
|
|
|
|
|