Newer
Older
/*WIKI*
A composite function is a function containing other functions. It combines the values calculated by the member functions by adding them. The members are indexed from 0 to the number of functions minus 1. The indices are defined by the order in which the functions were added. Composite functions do not have their own parameters, instead they use parameters of the member functions. Parameter names are formed from the member function's index and its parameter name: f[index].[name]. For example, name "f0.Sigma" would be given to the "Sigma" parameter of a Gaussian added first to the composite function. If a member function is a composite function itself the same principle applies: 'f[index].' is prepended to a name, e.g. "f0.f1.Sigma".
The input string to the Fit algorithm for a CompositeFunction is constructed by joining the inputs of the member functions using the semicolon ';' as a separator. For example, the string for two [[Gaussian]]s with tied sigma parameters may look like the following:
name=Gaussian,PeakCentre=0,Height=1,Sigma=0.1,constraints=(0<Sigma<1);name=Gaussian,PeakCentre=1,Height=1,Sigma=0.1;ties=(f1.Sigma=f0.Sigma)
Note that the ties clause is also separated by a semicolon. It is done because the parameters are from different functions. Ties between parameters of the same function can be placed inside the member definition in which the local parameter names must be used, for example:
name = FunctionType, P1=0, ties=( P2 = 2*P1 ); name = FunctionType, P1=0, ties=( P2 = 3 )
which is equivalent to
name = FunctionType, P1=0; name = FunctionType, P1=0; ties=( f0.P2 = 2*f0.P1, f1.P2 = 3 )
Boundary constraints usually make sense to put in a local function definition but they can also be moved to the composite function level, i.e. can be separated by ';'. In this case the full parameter name must be used, for example:
name=Gaussian,PeakCentre=0,Height=1,Sigma=0.1;name=Gaussian,PeakCentre=1,Height=1,Sigma=0.1;ties=(f1.Sigma=f0.Sigma);constraints=(0<f0.Sigma<1)
Mantid defines a number of fitting functions which extend CompositeFunction. These are functions which also include other functions but use different operations to combine them. Examples are [[ProductFunction]] and [[Convolution]]. Everything said about parameters of the CompositeFunction applies to these functions.
Input strings of an extended composite function must start with "composite=FunctionName;" and followed by the definitions of its members as described for CompositeFunction. For example,
composite=ProductFunction;name=LinearBackground;name=ExpDecay
To define a composite function inside a composite function enclose the inner one in brackets:
name=LinearBackground;(composite=Convolution;name=Resolution;name=Lorentzian)
*WIKI*/
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidKernel/Exception.h"
Roman Tolchenov
committed
#include "MantidAPI/CompositeFunction.h"
#include "MantidAPI/ParameterTie.h"
#include "MantidAPI/IConstraint.h"
#include "MantidAPI/FunctionFactory.h"
Peterson, Peter
committed
#include <boost/lexical_cast.hpp>
#include <boost/shared_array.hpp>
#include <sstream>
#include <iostream>
Roman Tolchenov
committed
#include <algorithm>
namespace Mantid
{
namespace API
{
DECLARE_FUNCTION(CompositeFunction)
/// Default constructor
CompositeFunction::CompositeFunction():
m_nParams(0)
{
declareAttribute("NumDeriv", Attribute(false));
}
///Destructor
CompositeFunction::~CompositeFunction()
{
}
/// Function initialization. Declare function parameters in this method.
void CompositeFunction::init()
{
}
Roman Tolchenov
committed
/**
* Writes itself into a string. Functions derived from CompositeFunction must
* override this method with something like this:
* std::string NewFunction::asString()const
* {
* ostr << "composite=" << this->name() << ';';
* // write NewFunction's own attributes and parameters
* ostr << CompositeFunction::asString();
* // write NewFunction's own ties and constraints
* // ostr << ";constraints=(" << ... <<")";
* }
* @return the string representation of the composite function
Roman Tolchenov
committed
*/
Roman Tolchenov
committed
std::string CompositeFunction::asString()const
{
std::ostringstream ostr;
// if empty just return function name
if (nFunctions() == 0)
{
return "name=" + name();
}
if ( name() != "CompositeFunction" || nAttributes() > 1 || getAttribute("NumDeriv").asBool() == true )
ostr << "composite=" <<name() ;
std::vector<std::string> attr = this->getAttributeNames();
for(size_t i=0;i<attr.size();i++)
{
std::string attName = attr[i];
std::string attValue = this->getAttribute(attr[i]).value();
if (!attValue.empty())
{
ostr<<','<<attName<<'='<<attValue;
}
}
ostr << ';';
Roman Tolchenov
committed
{
IFunction_sptr fun = getFunction(i);
bool isComp = boost::dynamic_pointer_cast<CompositeFunction>(fun) != 0;
Roman Tolchenov
committed
if (isComp) ostr << '(';
Roman Tolchenov
committed
ostr << fun->asString();
Roman Tolchenov
committed
if (isComp) ostr << ')';
Roman Tolchenov
committed
if (i < nFunctions() - 1)
{
ostr << ';';
}
}
std::string ties;
Roman Tolchenov
committed
for(size_t i=0;i<nParams();i++)
Roman Tolchenov
committed
{
const ParameterTie* tie = getTie(i);
if (tie)
{
IFunction_sptr fun = getFunction(functionIndex(i));
std::string tmp = tie->asString(fun.get());
Roman Tolchenov
committed
if (tmp.empty())
{
tmp = tie->asString(this);
if (!tmp.empty())
{
if (!ties.empty())
{
ties += ",";
}
ties += tmp;
}
}
}
}
if (!ties.empty())
{
ostr << ";ties=(" << ties << ")";
Roman Tolchenov
committed
}
return ostr.str();
}
/**
* @param ws A pointer to the workspace being fitted
*/
void CompositeFunction::setWorkspace(boost::shared_ptr<const Workspace> ws)
{
// Pass it on to each member
auto iend = m_functions.end();
for(auto it = m_functions.begin(); it != iend; ++it)
{
(*it)->setWorkspace(ws);
}
}
/** Function you want to fit to.
* @param domain :: An instance of FunctionDomain with the function arguments.
* @param values :: A FunctionValues instance for storing the calculated values.
*/
void CompositeFunction::function(const FunctionDomain& domain, FunctionValues& values)const
{
FunctionValues tmp(domain);
for(size_t iFun = 0; iFun < nFunctions(); ++iFun)
{
m_functions[ iFun ]->function(domain,tmp);
values += tmp;
}
}
/**
* Derivatives of function with respect to active parameters
* @param domain :: Function domain to get the arguments from.
* @param jacobian :: A Jacobian to store the derivatives.
*/
void CompositeFunction::functionDeriv(const FunctionDomain& domain, Jacobian& jacobian)
{
if ( getAttribute("NumDeriv").asBool() )
{
calNumericalDeriv(domain, jacobian);
}
else
for(size_t iFun = 0; iFun < nFunctions(); ++iFun)
{
PartialJacobian J(&jacobian,paramOffset(iFun));
getFunction(iFun)->functionDeriv(domain,J);
}
}
}
/** Sets a new value to the i-th parameter.
Janik Zikovsky
committed
* @param i :: The parameter index
* @param value :: The new value
* @param explicitlySet :: A boolean falgging the parameter as explicitly set (by user)
Roman Tolchenov
committed
void CompositeFunction::setParameter(size_t i, const double& value, bool explicitlySet)
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
m_functions[ iFun ]->setParameter(i - m_paramOffsets[iFun],value,explicitlySet);
Anders Markvardsen
committed
/** Sets a new description to the i-th parameter.
* @param i :: The parameter index
* @param description :: The new description
*/
void CompositeFunction::setParameterDescription(size_t i, const std::string& description)
{
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
Anders Markvardsen
committed
m_functions[ iFun ]->setParameterDescription(i - m_paramOffsets[iFun],description);
}
/** Get the i-th parameter.
Janik Zikovsky
committed
* @param i :: The parameter index
* @return value of the requested parameter
Roman Tolchenov
committed
double CompositeFunction::getParameter(size_t i)const
return m_functions[ iFun ]->getParameter(i - m_paramOffsets[iFun]);
/**
* Sets a new value to a parameter by name.
Janik Zikovsky
committed
* @param name :: The name of the parameter.
* @param value :: The new value
* @param explicitlySet :: A boolean falgging the parameter as explicitly set (by user)
*/
void CompositeFunction::setParameter(const std::string& name, const double& value, bool explicitlySet)
Peterson, Peter
committed
std::string pname;
Roman Tolchenov
committed
size_t index;
Peterson, Peter
committed
parseName(name,index,pname);
Roman Tolchenov
committed
getFunction(index)->setParameter(pname,value,explicitlySet);
Anders Markvardsen
committed
/**
* Sets a new description to a parameter by name.
* @param name :: The name of the parameter.
* @param description :: The new description
Anders Markvardsen
committed
*/
void CompositeFunction::setParameterDescription(const std::string& name, const std::string& description)
{
std::string pname;
Roman Tolchenov
committed
size_t index;
Anders Markvardsen
committed
parseName(name,index,pname);
Roman Tolchenov
committed
getFunction(index)->setParameterDescription(pname,description);
Anders Markvardsen
committed
}
/**
* Parameters by name.
Janik Zikovsky
committed
* @param name :: The name of the parameter.
* @return value of the requested named parameter
double CompositeFunction::getParameter(const std::string& name)const
{
Peterson, Peter
committed
std::string pname;
Roman Tolchenov
committed
size_t index;
Peterson, Peter
committed
parseName(name,index,pname);
Roman Tolchenov
committed
return getFunction(index)->getParameter(pname);
}
/// Total number of parameters
Roman Tolchenov
committed
size_t CompositeFunction::nParams()const
Janik Zikovsky
committed
* @param name :: The name of a parameter
* @return index of the requested named parameter
Roman Tolchenov
committed
size_t CompositeFunction::parameterIndex(const std::string& name)const
Peterson, Peter
committed
std::string pname;
Roman Tolchenov
committed
size_t index;
Peterson, Peter
committed
parseName(name,index,pname);
Russell Taylor
committed
return getFunction(index)->parameterIndex(pname) + m_paramOffsets[index];
Janik Zikovsky
committed
/// @param i :: The index
Roman Tolchenov
committed
std::string CompositeFunction::parameterName(size_t i)const
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
std::ostringstream ostr;
ostr << 'f' << iFun << '.' << m_functions[ iFun ]->parameterName(i - m_paramOffsets[iFun]);
return ostr.str();
Anders Markvardsen
committed
/// Returns the description of parameter
/// @param i :: The index
/// @return The description of the parameter
std::string CompositeFunction::parameterDescription(size_t i)const
{
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
Anders Markvardsen
committed
std::ostringstream ostr;
ostr << m_functions[ iFun ]->parameterDescription(i - m_paramOffsets[iFun]);
return ostr.str();
}
/**
* Get the fitting error for a parameter
* @param i :: The index of a parameter
* @return :: the error
*/
double CompositeFunction::getError(size_t i) const
{
size_t iFun = functionIndex(i);
return m_functions[ iFun ]->getError(i - m_paramOffsets[iFun]);
}
/**
* Set the fitting error for a parameter
* @param i :: The index of a parameter
* @param err :: The error value to set
*/
void CompositeFunction::setError(size_t i, double err)
{
size_t iFun = functionIndex(i);
m_functions[ iFun ]->setError(i - m_paramOffsets[iFun], err);
}
/// Value of i-th active parameter. Override this method to make fitted parameters different from the declared
Roman Tolchenov
committed
double CompositeFunction::activeParameter(size_t i)const
size_t iFun = functionIndex(i);
return m_functions[ iFun ]->activeParameter(i - m_paramOffsets[iFun]);
}
/// Set new value of i-th active parameter. Override this method to make fitted parameters different from the declared
Roman Tolchenov
committed
void CompositeFunction::setActiveParameter(size_t i, double value)
size_t iFun = functionIndex(i);
m_functions[ iFun ]->setActiveParameter(i - m_paramOffsets[iFun],value);
}
/// Returns the name of active parameter i
Roman Tolchenov
committed
std::string CompositeFunction::nameOfActive(size_t i)const
size_t iFun = functionIndex(i);
std::ostringstream ostr;
ostr << 'f' << iFun << '.' << m_functions[ iFun ]->nameOfActive(i - m_paramOffsets[iFun]);
Anders Markvardsen
committed
return ostr.str();
}
/// Returns the description of active parameter i
std::string CompositeFunction::descriptionOfActive(size_t i)const
{
size_t iFun = functionIndex(i);
Anders Markvardsen
committed
std::ostringstream ostr;
ostr << m_functions[ iFun ]->descriptionOfActive(i - m_paramOffsets[iFun]);
return ostr.str();
/**
* query to see in the function is active
* @param i :: The index of a declared parameter
* @return true if parameter i is active
*/
bool CompositeFunction::isActive(size_t i)const
{
size_t iFun = functionIndex(i);
return m_functions[ iFun ]->isActive(i - m_paramOffsets[iFun]);
}
* query to see in the function is active
Janik Zikovsky
committed
* @param i :: The index of a declared parameter
* @return true if parameter i is active
bool CompositeFunction::isFixed(size_t i)const
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
return m_functions[ iFun ]->isFixed(i - m_paramOffsets[iFun]);
Janik Zikovsky
committed
* @param i :: A declared parameter index to be removed from active
void CompositeFunction::fix(size_t i)
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
m_functions[ iFun ]->fix(i - m_paramOffsets[iFun]);
Roman Tolchenov
committed
/** Makes a parameter active again. It doesn't change the parameter's tie.
Janik Zikovsky
committed
* @param i :: A declared parameter index to be restored to active
Roman Tolchenov
committed
*/
void CompositeFunction::unfix(size_t i)
Roman Tolchenov
committed
{
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
m_functions[ iFun ]->unfix(i - m_paramOffsets[iFun]);
Roman Tolchenov
committed
}
/** Makes sure that the function is consistent.
*/
void CompositeFunction::checkFunction()
{
m_nParams = 0;
m_paramOffsets.clear();
m_IFunction.clear();
std::vector<IFunction_sptr> functions(m_functions.begin(),m_functions.end());
for(std::vector<IFunction_sptr>::size_type i=0;i<functions.size();i++)
IFunction_sptr f = functions[i];
CompositeFunction_sptr cf = boost::dynamic_pointer_cast<CompositeFunction>(f);
if (cf) cf->checkFunction();
Janik Zikovsky
committed
* @param f :: A pointer to the added function
* @return The function index
size_t CompositeFunction::addFunction(IFunction_sptr f)
m_IFunction.insert(m_IFunction.end(),f->nParams(), m_functions.size());
m_functions.push_back(f);
//?f->init();
if (m_paramOffsets.size() == 0)
{
m_paramOffsets.push_back(0);
m_nParams = f->nParams();
}
else
{
m_paramOffsets.push_back(m_nParams);
m_nParams += f->nParams();
}
Roman Tolchenov
committed
return m_functions.size() - 1;
Roman Tolchenov
committed
/** Remove a function
Janik Zikovsky
committed
* @param i :: The index of the function to remove
Roman Tolchenov
committed
*/
void CompositeFunction::removeFunction(size_t i)
Roman Tolchenov
committed
{
Roman Tolchenov
committed
if ( i >= nFunctions() )
Roman Tolchenov
committed
throw std::out_of_range("Function index out of range.");
IFunction_sptr fun = getFunction(i);
Roman Tolchenov
committed
Roman Tolchenov
committed
size_t dnp = fun->nParams();
Roman Tolchenov
committed
Roman Tolchenov
committed
for(size_t j=0;j<nParams();)
Roman Tolchenov
committed
{
ParameterTie* tie = getTie(j);
if (tie && tie->findParametersOf(fun.get()))
Roman Tolchenov
committed
{
removeTie(j);
}
else
{
j++;
}
}
// Shift down the function indeces for parameters
for(std::vector<size_t>::iterator it=m_IFunction.begin();it!=m_IFunction.end();)
Roman Tolchenov
committed
{
Roman Tolchenov
committed
Roman Tolchenov
committed
if (*it == i)
{
it = m_IFunction.erase(it);
Roman Tolchenov
committed
}
Roman Tolchenov
committed
else
Roman Tolchenov
committed
{
Roman Tolchenov
committed
if (*it > i)
{
*it -= 1;
}
Roman Tolchenov
committed
}
}
m_nParams -= dnp;
// Shift the parameter offsets down by the total number of i-th function's params
Roman Tolchenov
committed
for(size_t j=i+1;j<nFunctions();j++)
Roman Tolchenov
committed
{
m_paramOffsets[j] -= dnp;
}
m_paramOffsets.erase(m_paramOffsets.begin()+i);
m_functions.erase(m_functions.begin()+i);
}
Roman Tolchenov
committed
/** Replace a function with a new one. The old function is deleted.
* The new function must have already its workspace set.
Janik Zikovsky
committed
* @param f_old :: The pointer to the function to replace. If it's not
Roman Tolchenov
committed
* a member of this composite function nothing happens
Janik Zikovsky
committed
* @param f_new :: A pointer to the new function
Roman Tolchenov
committed
*/
void CompositeFunction::replaceFunctionPtr(const IFunction_sptr f_old,IFunction_sptr f_new)
Roman Tolchenov
committed
{
std::vector<IFunction_sptr>::const_iterator it =
Roman Tolchenov
committed
std::find(m_functions.begin(),m_functions.end(),f_old);
if (it == m_functions.end()) return;
std::vector<IFunction_sptr>::difference_type iFun = it - m_functions.begin();
Roman Tolchenov
committed
replaceFunction(iFun,f_new);
Roman Tolchenov
committed
}
Roman Tolchenov
committed
/** Replace a function with a new one. The old function is deleted.
Janik Zikovsky
committed
* @param i :: The index of the function to replace
* @param f :: A pointer to the new function
Roman Tolchenov
committed
*/
void CompositeFunction::replaceFunction(size_t i,IFunction_sptr f)
Roman Tolchenov
committed
{
Roman Tolchenov
committed
if ( i >= nFunctions() )
Roman Tolchenov
committed
throw std::out_of_range("Function index out of range.");
IFunction_sptr fun = getFunction(i);
Roman Tolchenov
committed
size_t np_old = fun->nParams();
Roman Tolchenov
committed
Roman Tolchenov
committed
size_t np_new = f->nParams();
Roman Tolchenov
committed
// Modify function indeces: The new function may have different number of parameters
{
std::vector<size_t>::iterator itFun = std::find(m_IFunction.begin(),m_IFunction.end(),i);
if(itFun != m_IFunction.end()) // functions must have at least 1 parameter
Roman Tolchenov
committed
{
if (np_old > np_new)
{
m_IFunction.erase(itFun,itFun + np_old - np_new);
}
else if (np_old < np_new)
{
m_IFunction.insert(itFun,np_new - np_old,i);
Roman Tolchenov
committed
}
Roman Tolchenov
committed
else if (np_new > 0) // it could happen if the old function is an empty CompositeFunction
{
itFun = std::find_if(m_IFunction.begin(),m_IFunction.end(),std::bind2nd(std::greater<size_t>(),i));
m_IFunction.insert(itFun,np_new,i);
Roman Tolchenov
committed
}
Roman Tolchenov
committed
}
Roman Tolchenov
committed
size_t dnp = np_new - np_old;
Roman Tolchenov
committed
m_nParams += dnp;
// Shift the parameter offsets down by the total number of i-th function's params
Roman Tolchenov
committed
for(size_t j=i+1;j<nFunctions();j++)
Roman Tolchenov
committed
{
m_paramOffsets[j] += dnp;
}
m_functions[i] = f;
}
Janik Zikovsky
committed
* @param i :: The index of the function
* @return function at the requested index
IFunction_sptr CompositeFunction::getFunction(std::size_t i)const
Roman Tolchenov
committed
{
throw std::out_of_range("Function index out of range.");
Roman Tolchenov
committed
}
/**
* Get the index of the function to which parameter i belongs
Janik Zikovsky
committed
* @param i :: The parameter index
* @return function index of the requested parameter
size_t CompositeFunction::functionIndex(std::size_t i)const
Roman Tolchenov
committed
if( i >= nParams() )
Roman Tolchenov
committed
{
throw std::out_of_range("Function parameter index out of range.");
Roman Tolchenov
committed
}
return m_IFunction[i];
Janik Zikovsky
committed
* @param varName :: The variable name which may contain function index ( [f<index.>]name )
Roman Tolchenov
committed
* @param index :: Receives function index or throws std::invalid_argument
Janik Zikovsky
committed
* @param name :: Receives the parameter name
Roman Tolchenov
committed
void CompositeFunction::parseName(const std::string& varName,size_t& index, std::string& name)
Peterson, Peter
committed
size_t i = varName.find('.');
if (i == std::string::npos)
{
Roman Tolchenov
committed
throw std::invalid_argument("Parameter " + varName + " not found.");
Peterson, Peter
committed
}
else
{
if (varName[0] != 'f')
throw std::invalid_argument("External function parameter name must start with 'f'");
Roman Tolchenov
committed
std::string sindex = varName.substr(1,i - 1);
Peterson, Peter
committed
index = boost::lexical_cast<int>(sindex);
if (i == varName.size() - 1)
throw std::invalid_argument("Name cannot be empty");
name = varName.substr(i+1);
}
Roman Tolchenov
committed
/** Returns the index of parameter i as it declared in its function
Janik Zikovsky
committed
* @param i :: The parameter index
Roman Tolchenov
committed
* @return The local index of the parameter
*/
Roman Tolchenov
committed
size_t CompositeFunction::parameterLocalIndex(size_t i)const
Roman Tolchenov
committed
{
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
Roman Tolchenov
committed
return i - m_paramOffsets[iFun];
}
/** Returns the name of parameter i as it declared in its function
Janik Zikovsky
committed
* @param i :: The parameter index
* @return The pure parameter name (without the function identifier f#.)
*/
Roman Tolchenov
committed
std::string CompositeFunction::parameterLocalName(size_t i)const
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
return m_functions[ iFun ]->parameterName(i - m_paramOffsets[iFun]);
}
Roman Tolchenov
committed
/**
Roman Tolchenov
committed
* Apply the ties.
Roman Tolchenov
committed
*/
void CompositeFunction::applyTies()
{
Roman Tolchenov
committed
{
getFunction(i)->applyTies();
}
}
/**
* Clear the ties.
*/
void CompositeFunction::clearTies()
{
Roman Tolchenov
committed
{
getFunction(i)->clearTies();
}
}
/** Removes i-th parameter's tie if it is tied or does nothing.
Janik Zikovsky
committed
* @param i :: The index of the tied parameter.
Roman Tolchenov
committed
* @return True if successfull
*/
Roman Tolchenov
committed
bool CompositeFunction::removeTie(size_t i)
Roman Tolchenov
committed
{
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
Roman Tolchenov
committed
bool res = m_functions[ iFun ]->removeTie(i - m_paramOffsets[iFun]);
return res;
}
/** Get the tie of i-th parameter
Janik Zikovsky
committed
* @param i :: The parameter index
* @return A pointer to the tie.
Roman Tolchenov
committed
*/
Roman Tolchenov
committed
ParameterTie* CompositeFunction::getTie(size_t i)const
Roman Tolchenov
committed
{
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
Roman Tolchenov
committed
return m_functions[ iFun ]->getTie(i - m_paramOffsets[iFun]);
}
/**
* Attaches a tie to this function. The attached tie is owned by the function.
Janik Zikovsky
committed
* @param tie :: A pointer to a new tie
Roman Tolchenov
committed
*/
void CompositeFunction::addTie(ParameterTie* tie)
{
Roman Tolchenov
committed
size_t i = getParameterIndex(*tie);
size_t iFun = functionIndex(i);
Roman Tolchenov
committed
m_functions[iFun]->addTie(tie);
}
/**
* Declare a new parameter. To used in the implementation'c constructor.
Janik Zikovsky
committed
* @param name :: The parameter name.
* @param initValue :: The initial value for the parameter
* @param description :: Parameter documentation
Roman Tolchenov
committed
*/
void CompositeFunction::declareParameter(const std::string& name, double initValue, const std::string& description)
Roman Tolchenov
committed
{
(void) name; //Avoid compiler warning
(void) initValue; //Avoid compiler warning
(void) description; //Avoid compiler warning
Roman Tolchenov
committed
throw Kernel::Exception::NotImplementedError("CompositeFunction cannot not have its own parameters.");
}
/** Add a constraint
Janik Zikovsky
committed
* @param ic :: Pointer to a constraint.
Roman Tolchenov
committed
*/
void CompositeFunction::addConstraint(IConstraint* ic)
{
Roman Tolchenov
committed
size_t i = getParameterIndex(*ic);
size_t iFun = functionIndex(i);
getFunction(iFun)->addConstraint(ic);
Roman Tolchenov
committed
}
/**
* Prepare the function for a fit.
*/
void CompositeFunction::setUpForFit()
Anders Markvardsen
committed
{
// set up the member functions
Anders Markvardsen
committed
{
getFunction(i)->setUpForFit();
// unfortuately the code below breaks some system tests (IRISFuryAndFuryFit)
// it looks as if using numeric derivatives can give different fit results
// to fit with analytical ones
//
// if parameters have non-constant ties enable numerical derivatives
//for(size_t i = 0; i < nParams(); ++i)
//{
// ParameterTie* tie = getTie( i );
// if ( tie && !tie->isConstant() )
// {
// useNumericDerivatives( true );
// break;
// }
//}
// instead of automatically switching to numeric derivatives
// log a warning about a danger of not using it
if ( !getAttribute("NumDeriv").asBool() )
for(size_t i = 0; i < nParams(); ++i)
ParameterTie* tie = getTie( i );
if ( tie && !tie->isConstant() )
{
g_log.warning() << "Numeric derivatives should be used when non-constant ties defined." << std::endl;
break;
}
Anders Markvardsen
committed
}
}
Janik Zikovsky
committed
/// @param i :: the index
Roman Tolchenov
committed
IConstraint* CompositeFunction::getConstraint(size_t i)const
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
return m_functions[ iFun ]->getConstraint(i - m_paramOffsets[iFun]);
/** Remove a constraint
Janik Zikovsky
committed
* @param parName :: The name of a parameter which constarint to remove.
*/
void CompositeFunction::removeConstraint(const std::string& parName)
{
Roman Tolchenov
committed
size_t iPar = parameterIndex(parName);
size_t iFun = functionIndex(iPar);
getFunction(iFun)->removeConstraint(parameterLocalName(iPar));
}
/** Checks if a constraint has been explicitly set
Janik Zikovsky
committed
* @param i :: The parameter index
* @return true if the function is explicitly set
Roman Tolchenov
committed
bool CompositeFunction::isExplicitlySet(size_t i)const
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
return m_functions[ iFun ]->isExplicitlySet(i - m_paramOffsets[iFun]);
}
Roman Tolchenov
committed
* Returns the index of parameter if the ref points to one of the member function
Janik Zikovsky
committed
* @param ref :: A reference to a parameter
Roman Tolchenov
committed
* @return Parameter index or number of nParams() if parameter not found
Roman Tolchenov
committed
size_t CompositeFunction::getParameterIndex(const ParameterReference& ref)const
Roman Tolchenov
committed
if (ref.getFunction() == this && ref.getIndex() < nParams())
Roman Tolchenov
committed
return ref.getIndex();
Roman Tolchenov
committed
{
IFunction_sptr fun = getFunction(iFun);
Roman Tolchenov
committed
size_t iLocalIndex = fun->getParameterIndex(ref);
if (iLocalIndex < fun->nParams())
Roman Tolchenov
committed
{
return m_paramOffsets[iFun] + iLocalIndex;
}
}
Roman Tolchenov
committed
return nParams();
* Returns the shrared pointer to the function conataining a parameter
Janik Zikovsky
committed
* @param ref :: The reference
* @return A function containing parameter pointed to by ref
*/
IFunction_sptr CompositeFunction::getContainingFunction(const ParameterReference& ref)const
IFunction_sptr fun = getFunction(iFun);
if (fun->getParameterIndex(ref) < fun->nParams())
return fun;
}
}
return IFunction_sptr();
}
} // namespace API
} // namespace Mantid