Commit 769bc5dc authored by Roman Tolchenov's avatar Roman Tolchenov
Browse files

Added CompositeFunction. re #965

parent cf1b7bbb
......@@ -212,6 +212,10 @@
RelativePath=".\src\ColumnFactory.cpp"
>
</File>
<File
RelativePath=".\src\CompositeFunction.cpp"
>
</File>
<File
RelativePath=".\src\FrameworkManager.cpp"
>
......@@ -378,6 +382,10 @@
RelativePath=".\inc\MantidAPI\ColumnFactory.h"
>
</File>
<File
RelativePath=".\inc\MantidAPI\CompositeFunction.h"
>
</File>
<File
RelativePath=".\inc\MantidAPI\DeclareUserAlg.h"
>
......
#ifndef MANTID_API_COMPOSITEFUNCTION_H_
#define MANTID_API_COMPOSITEFUNCTION_H_
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/IFunction.h"
namespace Mantid
{
namespace API
{
/** A composite function.
@author Roman Tolchenov, Tessella Support Services plc
@date 20/10/2009
Copyright &copy; 2008 STFC Rutherford Appleton Laboratory
This file is part of Mantid.
Mantid is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Mantid is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>.
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
class DLLExport CompositeFunction : public IFunction
{
public:
/// Default constructor
CompositeFunction():m_nActive(0),m_nParams(0){}
/// Copy contructor
CompositeFunction(const CompositeFunction&);
///Assignment operator
CompositeFunction& operator=(const CompositeFunction&);
///Destructor
~CompositeFunction();
/// Function initialization. Declare function parameters in this method.
void init();
/// Function you want to fit to.
void function(double* out, const double* xValues, const int& nData);
/// Derivatives of function with respect to active parameters
void functionDeriv(Jacobian* out, const double* xValues, const int& nData);
/// Derivatives to be used in covariance matrix calculation.
void calJacobianForCovariance(Jacobian* out, const double* xValues, const int& nData);
/// Address of i-th parameter
double& parameter(int);
/// Address of i-th parameter
double parameter(int i)const;
/// Get parameter by name.
double& getParameter(const std::string& name);
/// Get parameter by name.
double getParameter(const std::string& name)const;
/// Total number of parameters
int nParams()const;
/// Returns the name of parameter i
std::string parameterName(int i)const;
/// Number of active (in terms of fitting) parameters
int nActive()const;
/// Value of i-th active parameter. Override this method to make fitted parameters different from the declared
double activeParameter(int i)const;
/// Set new value of i-th active parameter. Override this method to make fitted parameters different from the declared
void setActiveParameter(int i, double value);
/// Update parameters after a fitting iteration
void updateActive(const double* in);
/// Returns "global" index of active parameter i
int indexOfActive(int i)const;
/// Returns the name of active parameter i
std::string nameOfActive(int i)const;
/// Add a function
void addFunction(IFunction* f);
/// Returns the pointer to i-th function
IFunction* getFunction(int i);
/// Number of functions
int nFunctions(){return m_functions.size();}
private:
double m_tst;
/// Pointers to the included funtions
std::vector<IFunction*> m_functions;
/// Individual function parameter offsets
std::vector<int> m_activeOffsets;
/// Individual function parameter offsets
std::vector<int> m_paramOffsets;
/// Keeps the function number for each parameter
std::vector<int> m_iFunction;
/// Number of active parameters
int m_nActive;
/// Total number of parameters
int m_nParams;
};
} // namespace API
} // namespace Mantid
#endif /*MANTID_API_COMPOSITEFUNCTION_H_*/
......@@ -54,49 +54,59 @@ class Jacobian;
class DLLExport IFunction
{
public:
/// Default constructor
IFunction(){}
/// Copy contructor
IFunction(const IFunction&);
///Assignment operator
IFunction& operator=(const IFunction&);
/// Function initialization. Declare function parameters in this method.
virtual void init() = 0;
/// Function you want to fit to.
virtual void function(double* out, const double* xValues, const int& nData) = 0;
/// Derivatives of function with respect to active parameters
virtual void functionDeriv(Jacobian* out, const double* xValues, const int& nData) = 0;
/// Derivatives to be used in covariance matrix calculation
/// Derivatives to be used in covariance matrix calculation. Override this method some of the fitted parameters
/// are different form the declared ones.
virtual void calJacobianForCovariance(Jacobian* out, const double* xValues, const int& nData);
/// Address of i-th parameter
double& parameter(int);
virtual double& parameter(int);
/// Address of i-th parameter
double parameter(int i)const;
virtual double parameter(int i)const;
/// Get parameter by name.
double& getParameter(const std::string& name);
virtual double& getParameter(const std::string& name);
/// Get parameter by name.
double getParameter(const std::string& name)const;
virtual double getParameter(const std::string& name)const;
/// Total number of parameters
int nParams()const{return m_parameters.size();};
virtual int nParams()const{return m_parameters.size();};
/// Returns the name of parameter i
std::string parameterName(int i)const;
virtual std::string parameterName(int i)const;
/// Number of active (in terms of fitting) parameters
int nActive()const{return m_indexMap.size() ? m_indexMap.size() : nParams();}
/// Value of i-th active parameter
virtual double activeParameter(int i);
/// Set new value of i-th active parameter
virtual int nActive()const{return m_indexMap.size() ? m_indexMap.size() : nParams();}
/// Value of i-th active parameter. Override this method to make fitted parameters different from the declared
virtual double activeParameter(int i)const;
/// Set new value of i-th active parameter. Override this method to make fitted parameters different from the declared
virtual void setActiveParameter(int i, double value);
/// Update parameters after a fitting iteration
void updateActive(const double* in);
virtual void updateActive(const double* in);
/// Returns "global" index of active parameter i
int indexOfActive(int i)const;
virtual int indexOfActive(int i)const;
/// Returns the name of active parameter i
std::string nameOfActive(int i)const;
virtual std::string nameOfActive(int i)const;
protected:
/// Declare a new parameter
void declareParameter(const std::string& name,double initValue = 0);
virtual void declareParameter(const std::string& name,double initValue = 0);
private:
/// The index map. m_indexMap[i] gives the total index for active parameter i
std::vector<int> m_indexMap;
/// Keeps parameter names
std::vector<std::string> m_parameterNames;
/// Keeps parameter values
std::vector<double> m_parameters;
};
......
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/CompositeFunction.h"
#include "MantidKernel/Exception.h"
#include <boost/shared_array.hpp>
#include <sstream>
#include <iostream>
namespace Mantid
{
namespace API
{
/// Copy contructor
CompositeFunction::CompositeFunction(const CompositeFunction& f)
:m_nActive(f.m_nParams),m_nParams(f.m_nParams)
{
m_functions.assign(f.m_functions.begin(),f.m_functions.end());
m_activeOffsets.assign(f.m_activeOffsets.begin(),f.m_activeOffsets.end());
m_paramOffsets.assign(f.m_paramOffsets.begin(),f.m_paramOffsets.end());
}
///Assignment operator
CompositeFunction& CompositeFunction::operator=(const CompositeFunction& f)
{
m_nActive = f.m_nActive;
m_nParams = f.m_nParams;
m_functions.assign(f.m_functions.begin(),f.m_functions.end());
m_activeOffsets.assign(f.m_activeOffsets.begin(),f.m_activeOffsets.end());
m_paramOffsets.assign(f.m_paramOffsets.begin(),f.m_paramOffsets.end());
return *this;
}
///Destructor
CompositeFunction::~CompositeFunction()
{
for(int i=0;i<nFunctions();i++)
if (m_functions[i]) delete m_functions[i];
}
/// Function initialization. Declare function parameters in this method.
void CompositeFunction::init()
{
}
/// Function you want to fit to.
void CompositeFunction::function(double* out, const double* xValues, const int& nData)
{
if (nData <= 0) return;
boost::shared_array<double> tmpOut(new double[nData]);
for(int i=0;i<nFunctions();i++)
{
if (i == 0)
m_functions[i]->function(out,xValues,nData);
else
{
m_functions[i]->function(tmpOut.get(),xValues,nData);
std::transform(out,out+nData,tmpOut.get(),out,std::plus<double>());
}
}
}
/** A Jacobian for individual functions
*/
class PartialJacobian: public Jacobian
{
Jacobian* m_J;///< pointer to the overall Jacobian
int m_iP0; ///< offset in the overall Jacobian for a particular function
public:
/** Constructor
* @param J A pointer to the overall Jacobian
*/
PartialJacobian(Jacobian* J,int iP0):m_J(J),m_iP0(iP0){}
/**
* Overridden Jacobian::set(...).
* @param iY The index of the data point
* @param iP The parameter index of an individual function.
*/
void set(int iY, int iP, double value)
{
m_J->set(iY,m_iP0 + iP,value);
}
};
/// Derivatives of function with respect to active parameters
void CompositeFunction::functionDeriv(Jacobian* out, const double* xValues, const int& nData)
{
if (nData <= 0) return;
for(int i=0;i<nFunctions();i++)
{
PartialJacobian J(out,m_activeOffsets[i]);
m_functions[i]->functionDeriv(&J,xValues,nData);
}
}
/// Derivatives to be used in covariance matrix calculation.
void CompositeFunction::calJacobianForCovariance(Jacobian* out, const double* xValues, const int& nData)
{
if (nData <= 0) return;
for(int i=0;i<nFunctions();i++)
{
PartialJacobian J(out,m_activeOffsets[i]);
m_functions[i]->calJacobianForCovariance(&J,xValues,nData);
}
}
/// Address of i-th parameter
double& CompositeFunction::parameter(int i)
{
if (i >= nParams())
throw std::out_of_range("Function parameter index out of range.");
int iFun = m_iFunction[i];
return m_functions[ iFun ]->parameter(i - m_activeOffsets[iFun]);
}
/// Address of i-th parameter
double CompositeFunction::parameter(int i)const
{
if (i >= nParams())
throw std::out_of_range("Function parameter index out of range.");
int iFun = m_iFunction[i];
return m_functions[ iFun ]->parameter(i - m_activeOffsets[iFun]);
}
/// Get parameter by name.
double& CompositeFunction::getParameter(const std::string& name)
{
throw Kernel::Exception::NotImplementedError("CompositeFunction::getParameter is not implemented");
return m_tst;
}
/// Get parameter by name.
double CompositeFunction::getParameter(const std::string& name)const
{
throw Kernel::Exception::NotImplementedError("CompositeFunction::getParameter is not implemented");
return m_tst;
}
/// Total number of parameters
int CompositeFunction::nParams()const
{
return m_nParams;
}
/// Returns the name of parameter i
std::string CompositeFunction::parameterName(int i)const
{
if (i >= nParams())
throw std::out_of_range("Function parameter index out of range.");
int iFun = m_iFunction[i];
return m_functions[ iFun ]->parameterName(i - m_activeOffsets[iFun]);
}
/// Number of active (in terms of fitting) parameters
int CompositeFunction::nActive()const
{
return m_nActive;
}
/// Value of i-th active parameter. Override this method to make fitted parameters different from the declared
double CompositeFunction::activeParameter(int i)const
{
if (i >= nParams())
throw std::out_of_range("Function parameter index out of range.");
int iFun = m_iFunction[i];
return m_functions[ iFun ]->activeParameter(i - m_activeOffsets[iFun]);
}
/// Set new value of i-th active parameter. Override this method to make fitted parameters different from the declared
void CompositeFunction::setActiveParameter(int i, double value)
{
if (i >= nParams())
throw std::out_of_range("Function parameter index out of range.");
int iFun = m_iFunction[i];
return m_functions[ iFun ]->setActiveParameter(i - m_activeOffsets[iFun],value);
}
/// Update parameters after a fitting iteration
void CompositeFunction::updateActive(const double* in)
{
for(int iFun = 0; iFun < int(m_functions.size()); iFun++)
{
m_functions[ iFun ]->updateActive(in + m_activeOffsets[ iFun ]);
}
}
/// Returns "global" index of active parameter i
int CompositeFunction::indexOfActive(int i)const
{
if (i >= nParams())
throw std::out_of_range("Function parameter index out of range.");
int iFun = m_iFunction[i];
return m_paramOffsets[ iFun ] + m_functions[ iFun ]->indexOfActive(i - m_activeOffsets[iFun]);
}
/// Returns the name of active parameter i
std::string CompositeFunction::nameOfActive(int i)const
{
if (i >= nParams())
throw std::out_of_range("Function parameter index out of range.");
int iFun = m_iFunction[i];
return m_functions[ iFun ]->nameOfActive(i - m_activeOffsets[iFun]);
}
/** Add a function
* @param f A pointer to the added function
*/
void CompositeFunction::addFunction(IFunction* 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_activeOffsets.push_back(0);
m_nParams = f->nParams();
m_nActive = f->nActive();
}
else
{
m_paramOffsets.push_back(m_nParams);
m_activeOffsets.push_back(m_nActive);
m_nParams += f->nParams();
m_nActive += f->nActive();
}
}
IFunction* CompositeFunction::getFunction(int i)
{
if ( i >= nFunctions() )
throw std::out_of_range("Function index out of range.");
return m_functions[i];
}
} // namespace API
} // namespace Mantid
......@@ -12,6 +12,23 @@ namespace Mantid
namespace API
{
/// Copy contructor
IFunction::IFunction(const IFunction& f)
{
m_indexMap.assign(f.m_indexMap.begin(),f.m_indexMap.end());
m_parameterNames.assign(f.m_parameterNames.begin(),f.m_parameterNames.end());
m_parameters.assign(f.m_parameters.begin(),f.m_parameters.end());
}
///Assignment operator
IFunction& IFunction::operator=(const IFunction& f)
{
m_indexMap.assign(f.m_indexMap.begin(),f.m_indexMap.end());
m_parameterNames.assign(f.m_parameterNames.begin(),f.m_parameterNames.end());
m_parameters.assign(f.m_parameters.begin(),f.m_parameters.end());
return *this;
}
/** Update parameters
* @param in Pointer to an array with active parameters values.
*/
......@@ -31,7 +48,7 @@ void IFunction::setActiveParameter(int i,double value)
parameter(j) = value;
}
double IFunction::activeParameter(int i)
double IFunction::activeParameter(int i)const
{
int j = indexOfActive(i);
return parameter(j);
......
......@@ -62,7 +62,7 @@ namespace Mantid
/// Default constructor
Fit() : API::Algorithm(),m_function(NULL) {};
/// Destructor
virtual ~Fit() {};
virtual ~Fit();
/// Algorithm's name for identification overriding a virtual method
virtual const std::string name() const { return "Fit";}
/// Algorithm's version for identification overriding a virtual method
......@@ -106,7 +106,6 @@ namespace Mantid
/// Pointer to the fitting function
API::IFunction* m_function;
friend struct FitData;
};
......
......@@ -168,6 +168,12 @@ namespace CurveFitting
return retVal;
}
///Destructor
Fit::~Fit()
{
if (m_function) delete m_function;
}
/** Initialisation method
*/
void Fit::init()
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment