Commit 7c8c308d authored by Roman Tolchenov's avatar Roman Tolchenov
Browse files

Re #18518. Changed tie setting in composite functions.

parent 66f246b1
......@@ -130,8 +130,6 @@ public:
std::string nameOfActive(size_t i) const override;
/// Returns the name of active parameter i
std::string descriptionOfActive(size_t i) const override;
/// Check if an active parameter i is actually active
bool isActive(size_t i) const override;
/// Return parameter index from a parameter reference.
size_t getParameterIndex(const ParameterReference &ref) const override;
......@@ -149,11 +147,7 @@ public:
bool removeTie(size_t i) override;
/// Get the tie of i-th parameter
ParameterTie *getTie(size_t i) const override;
/// Add a new tie
void addTie(std::unique_ptr<ParameterTie> tie) override;
/// Overwrite IFunction methods
void addConstraint(std::unique_ptr<IConstraint> ic) override;
/// Get constraint of i-th parameter
IConstraint *getConstraint(size_t i) const override;
/// Prepare function for a fit
......
......@@ -4,8 +4,8 @@
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/IFunction.h"
#include "MantidAPI/ParameterReference.h"
#include <string>
namespace Mantid {
namespace API {
......
......@@ -7,7 +7,9 @@
#include "MantidAPI/DllConfig.h"
#include "MantidAPI/FunctionDomain.h"
#include "MantidAPI/FunctionValues.h"
#include "MantidAPI/IConstraint.h"
#include "MantidAPI/Jacobian.h"
#include "MantidAPI/ParameterTie.h"
#include "MantidKernel/Matrix.h"
#include "MantidKernel/Unit.h"
......@@ -33,9 +35,6 @@ class ProgressBase;
namespace API {
class Workspace;
class MatrixWorkspace;
class ParameterTie;
class IConstraint;
class ParameterReference;
class FunctionHandler;
/** This is an interface to a fitting function - a semi-abstarct class.
......@@ -449,7 +448,7 @@ public:
/// Returns the name of active parameter i
virtual std::string descriptionOfActive(size_t i) const;
/// Check if an active parameter i is actually active
virtual bool isActive(size_t i) const { return !isFixed(i); }
virtual bool isActive(size_t i) const;
//@}
/** @name Ties */
......@@ -460,17 +459,17 @@ public:
/// Add several ties
virtual void addTies(const std::string &ties, bool isDefault = false);
/// Apply the ties
virtual void applyTies() = 0;
virtual void applyTies();
/// Removes the tie off a parameter
virtual void removeTie(const std::string &parName);
/// Remove all ties
virtual void clearTies() = 0;
virtual void clearTies();
/// Removes i-th parameter's tie
virtual bool removeTie(size_t i) = 0;
virtual bool removeTie(size_t i);
/// Get the tie of i-th parameter
virtual ParameterTie *getTie(size_t i) const = 0;
virtual ParameterTie *getTie(size_t i) const;
/// Add a new tie. Derived classes must provide storage for ties
virtual void addTie(std::unique_ptr<ParameterTie> tie) = 0;
virtual void addTie(std::unique_ptr<ParameterTie> tie);
/// Write a parameter tie to a string
virtual std::string writeTie(size_t iParam) const;
//@}
......@@ -480,13 +479,15 @@ public:
/// Add a list of conatraints from a string
virtual void addConstraints(const std::string &str, bool isDefault = false);
/// Add a constraint to function
virtual void addConstraint(std::unique_ptr<IConstraint> ic) = 0;
virtual void addConstraint(std::unique_ptr<IConstraint> ic);
/// Get constraint of i-th parameter
virtual IConstraint *getConstraint(size_t i) const = 0;
virtual IConstraint *getConstraint(size_t i) const;
/// Remove a constraint
virtual void removeConstraint(const std::string &parName) = 0;
virtual void removeConstraint(const std::string &parName);
/// Write a parameter constraint to a string
virtual std::string writeConstraint(size_t iParam) const;
/// Remove all constraints.
virtual void clearConstraints();
//@}
/** @name Attributes */
......@@ -511,7 +512,7 @@ public:
//@}
/// Set up the function for a fit.
virtual void setUpForFit() = 0;
virtual void setUpForFit();
/// Get number of values for a given domain.
virtual size_t getValuesSize(const FunctionDomain &domain) const;
/// Get number of domains required by this function
......@@ -593,6 +594,10 @@ private:
boost::shared_ptr<Kernel::Matrix<double>> m_covar;
/// The chi-squared of the last fit
double m_chiSquared;
/// Holds parameter ties as <parameter index,tie pointer>
std::vector<std::unique_ptr<ParameterTie>> m_ties;
/// Holds the constraints added to function
std::vector<std::unique_ptr<IConstraint>> m_constraints;
};
/// shared pointer to the function base class
......
......@@ -50,8 +50,6 @@ class MANTID_API_DLL ParamFunction : public virtual IFunction {
public:
/// Default constructor
ParamFunction() {}
/// Virtual destructor
~ParamFunction() override;
/// Set i-th parameter
void setParameter(size_t, const double &value,
......@@ -98,29 +96,6 @@ public:
/// Get the containing function
IFunction_sptr getContainingFunction(IFunction_sptr fun);
/// Apply the ties
void applyTies() override;
/// Remove all ties
void clearTies() override;
void removeTie(const std::string &parName) override {
IFunction::removeTie(parName);
}
/// Removes i-th parameter's tie
bool removeTie(size_t i) override;
/// Get the tie of i-th parameter
ParameterTie *getTie(size_t i) const override;
/// Add a new tie
void addTie(std::unique_ptr<ParameterTie> tie) override;
/// Add a constraint to function
void addConstraint(std::unique_ptr<IConstraint> ic) override;
/// Get constraint of i-th parameter
IConstraint *getConstraint(size_t i) const override;
/// Remove a constraint
void removeConstraint(const std::string &parName) override;
/// Set parameters to satisfy constraints
void setUpForFit() override;
protected:
/// Declare a new parameter
void declareParameter(const std::string &name, double initValue = 0,
......@@ -141,10 +116,6 @@ private:
std::vector<double> m_parameters;
/// Keeps parameter errors
std::vector<double> m_errors;
/// Holds parameter ties as <parameter index,tie pointer>
std::vector<std::unique_ptr<ParameterTie>> m_ties;
/// Holds the constraints added to function
std::vector<std::unique_ptr<IConstraint>> m_constraints;
/// Flags of explicitly set parameters
std::vector<bool> m_explicitlySet;
/// parameter descriptions
......
......@@ -5,14 +5,10 @@
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/DllConfig.h"
#include "MantidAPI/IFunction.h"
namespace mu {
class Parser;
}
namespace Mantid {
namespace API {
class IFunction;
/**
A reference to a parameter in a function. To uniquely identify a parameter
in a composite function
......@@ -51,14 +47,14 @@ public:
double getParameter() const;
IFunction *getFunction() const;
bool isDefault() const;
bool isParameterOf(const IFunction *fun) const;
virtual ~ParameterReference() = default;
private:
IFunction *m_function; ///< pointer to the function
std::size_t m_index; ///< parameter index
/// Flag to mark as default the value of an object associated with this
/// reference:
/// a tie or a constraint.
/// reference: a tie or a constraint.
bool m_isDefault;
};
......
......@@ -5,8 +5,8 @@
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/DllConfig.h"
#include "MantidAPI/IFunction.h"
#include "MantidAPI/ParameterReference.h"
#include <map>
namespace mu {
class Parser;
......
......@@ -329,16 +329,6 @@ std::string CompositeFunction::descriptionOfActive(size_t i) const {
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
* @param i :: The index of a declared parameter
......@@ -600,12 +590,14 @@ void CompositeFunction::applyTies() {
for (size_t i = 0; i < nFunctions(); i++) {
getFunction(i)->applyTies();
}
IFunction::applyTies();
}
/**
* Clear the ties.
*/
void CompositeFunction::clearTies() {
IFunction::clearTies();
for (size_t i = 0; i < nFunctions(); i++) {
getFunction(i)->clearTies();
}
......@@ -616,9 +608,13 @@ void CompositeFunction::clearTies() {
* @return True if successfull
*/
bool CompositeFunction::removeTie(size_t i) {
size_t iFun = functionIndex(i);
bool res = m_functions[iFun]->removeTie(i - m_paramOffsets[iFun]);
return res;
bool foundAndRemovedTie = IFunction::removeTie(i);
if (!foundAndRemovedTie) {
size_t iFun = functionIndex(i);
bool res = m_functions[iFun]->removeTie(i - m_paramOffsets[iFun]);
return res;
}
return foundAndRemovedTie;
}
/** Get the tie of i-th parameter
......@@ -626,18 +622,12 @@ bool CompositeFunction::removeTie(size_t i) {
* @return A pointer to the tie.
*/
ParameterTie *CompositeFunction::getTie(size_t i) const {
size_t iFun = functionIndex(i);
return m_functions[iFun]->getTie(i - m_paramOffsets[iFun]);
}
/**
* Attaches a tie to this function. The attached tie is owned by the function.
* @param tie :: A pointer to a new tie
*/
void CompositeFunction::addTie(std::unique_ptr<ParameterTie> tie) {
size_t i = getParameterIndex(*tie);
size_t iFun = functionIndex(i);
m_functions[iFun]->addTie(std::move(tie));
auto tie = IFunction::getTie(i);
if (tie == nullptr) {
size_t iFun = functionIndex(i);
tie = m_functions[iFun]->getTie(i - m_paramOffsets[iFun]);
}
return tie;
}
/**
......@@ -656,19 +646,11 @@ void CompositeFunction::declareParameter(const std::string &name,
"CompositeFunction cannot not have its own parameters.");
}
/** Add a constraint
* @param ic :: Pointer to a constraint.
*/
void CompositeFunction::addConstraint(std::unique_ptr<IConstraint> ic) {
size_t i = getParameterIndex(*ic);
size_t iFun = functionIndex(i);
getFunction(iFun)->addConstraint(std::move(ic));
}
/**
* Prepare the function for a fit.
*/
void CompositeFunction::setUpForFit() {
IFunction::setUpForFit();
// set up the member functions
for (size_t i = 0; i < nFunctions(); i++) {
getFunction(i)->setUpForFit();
......@@ -706,17 +688,27 @@ void CompositeFunction::setUpForFit() {
/// @param i :: the index
/// @return A pointer to the constraint
IConstraint *CompositeFunction::getConstraint(size_t i) const {
size_t iFun = functionIndex(i);
return m_functions[iFun]->getConstraint(i - m_paramOffsets[iFun]);
auto constraint = IFunction::getConstraint(i);
if (constraint == nullptr) {
size_t iFun = functionIndex(i);
constraint = m_functions[iFun]->getConstraint(i - m_paramOffsets[iFun]);
}
return constraint;
}
/** Remove a constraint
* @param parName :: The name of a parameter which constarint to remove.
*/
void CompositeFunction::removeConstraint(const std::string &parName) {
size_t iPar = parameterIndex(parName);
size_t iFun = functionIndex(iPar);
getFunction(iFun)->removeConstraint(parameterLocalName(iPar));
auto i = parameterIndex(parName);
auto constraint = IFunction::getConstraint(i);
if (constraint != nullptr) {
IFunction::removeConstraint(parName);
} else {
size_t iPar = parameterIndex(parName);
size_t iFun = functionIndex(iPar);
getFunction(iFun)->removeConstraint(parameterLocalName(iPar));
}
}
/** Checks if a constraint has been explicitly set
......
......@@ -103,6 +103,13 @@ void IFunction::functionDeriv(const FunctionDomain &domain,
calNumericalDeriv(domain, jacobian);
}
/** Check if an active parameter i is actually active
* @param i :: Index of a parameter.
*/
bool IFunction::isActive(size_t i) const {
return !(isFixed(i) || getTie(i) != nullptr);
}
/**
* Ties a parameter to other parameters
* @param parName :: The name of the parameter to tie.
......@@ -114,13 +121,12 @@ void IFunction::functionDeriv(const FunctionDomain &domain,
void IFunction::tie(const std::string &parName, const std::string &expr,
bool isDefault) {
auto ti = Kernel::make_unique<ParameterTie>(this, parName, expr, isDefault);
this->fix(getParameterIndex(*ti));
if (!isDefault && ti->isConstant()) {
setParameter(parName, ti->eval());
fix(getParameterIndex(*ti));
} else {
addTie(std::move(ti));
}
// return ti.get();
}
/**
......@@ -174,6 +180,157 @@ std::string IFunction::writeTie(size_t iParam) const {
return tieStream.str();
}
/**
* Attaches a tie to this ParamFunction. The attached tie is owned by the
* ParamFunction.
* @param tie :: A pointer to a new tie
*/
void IFunction::addTie(std::unique_ptr<ParameterTie> tie) {
auto iPar = getParameterIndex(*tie);
bool found = false;
for (auto &m_tie : m_ties) {
auto mPar = getParameterIndex(*m_tie);
if (mPar == iPar) {
found = true;
m_tie = std::move(tie);
break;
}
}
if (!found) {
m_ties.push_back(std::move(tie));
}
}
/**
* Apply the ties.
*/
void IFunction::applyTies() {
for (auto &m_tie : m_ties) {
m_tie->eval();
}
}
/**
* Used to find ParameterTie for a parameter i
*/
class ReferenceEqual {
/// The function that has the tie
const IFunction &m_fun;
/// index to find
const size_t m_i;
public:
/// Constructor
explicit ReferenceEqual(const IFunction &fun, size_t i) : m_fun(fun), m_i(i) {}
/// Bracket operator
/// @param p :: the element you are looking for
/// @return True if found
template <class T> bool operator()(const std::unique_ptr<T> &p) {
return m_fun.getParameterIndex(*p) == m_i;
}
};
/** Removes i-th parameter's tie if it is tied or does nothing.
* @param i :: The index of the tied parameter.
* @return True if successfull
*/
bool IFunction::removeTie(size_t i) {
if (i >= nParams()) {
throw std::out_of_range("Function parameter index out of range.");
}
auto it = std::find_if(m_ties.begin(), m_ties.end(), ReferenceEqual(*this, i));
if (it != m_ties.end()) {
m_ties.erase(it);
unfix(i);
return true;
}
unfix(i);
return false;
}
/** Get tie of parameter number i
* @param i :: The index of a declared parameter.
* @return A pointer to the tie
*/
ParameterTie *IFunction::getTie(size_t i) const {
if (i >= nParams()) {
throw std::out_of_range("Function parameter index out of range.");
}
auto it = std::find_if(m_ties.cbegin(), m_ties.cend(), ReferenceEqual(*this, i));
if (it != m_ties.cend()) {
return it->get();
}
return nullptr;
}
/** Remove all ties
*/
void IFunction::clearTies() {
for (size_t i = 0; i < nParams(); ++i) {
unfix(i);
}
m_ties.clear();
}
/** Add a constraint
* @param ic :: Pointer to a constraint.
*/
void IFunction::addConstraint(std::unique_ptr<IConstraint> ic) {
size_t iPar = ic->getIndex();
bool found = false;
for (auto &constraint : m_constraints) {
if (constraint->getIndex() == iPar) {
found = true;
constraint = std::move(ic);
break;
}
}
if (!found) {
m_constraints.push_back(std::move(ic));
}
}
/** Get constraint of parameter number i
* @param i :: The index of a declared parameter.
* @return A pointer to the constraint or NULL
*/
IConstraint *IFunction::getConstraint(size_t i) const {
if (i >= nParams()) {
throw std::out_of_range("ParamFunction parameter index out of range.");
}
auto it = std::find_if(m_constraints.cbegin(), m_constraints.cend(),
ReferenceEqual(*this, i));
if (it != m_constraints.cend()) {
return it->get();
}
return nullptr;
}
/** Remove a constraint
* @param parName :: The name of a parameter which constarint to remove.
*/
void IFunction::removeConstraint(const std::string &parName) {
size_t iPar = parameterIndex(parName);
for (auto it = m_constraints.begin(); it != m_constraints.end(); ++it) {
if (iPar == (**it).getIndex()) {
m_constraints.erase(it);
break;
}
}
}
/// Remove all constraints.
void IFunction::clearConstraints() {
m_constraints.clear();
}
void IFunction::setUpForFit() {
for (auto &constraint : m_constraints) {
constraint->setParamToSatisfyConstraint();
}
}
/// Write a parameter constraint to a string
/// @param iParam :: An index of a parameter.
/// @return A constraint string for the parameter.
......@@ -636,8 +793,7 @@ void IFunction::Attribute::fromString(const std::string &str) {
/// Value of i-th active parameter. Override this method to make fitted
/// parameters different from the declared
double IFunction::activeParameter(size_t i) const {
if (!isActive(i)) {
throw std::runtime_error("Attempt to use an inactive parameter " +
if (!isActive(i)) { throw std::runtime_error("Attempt to use an inactive parameter " +
parameterName(i));
}
return getParameter(i);
......
......@@ -15,12 +15,6 @@ namespace {
Kernel::Logger g_log("ParamFunction");
}
/// Destructor
ParamFunction::~ParamFunction() {
m_ties.clear();
m_constraints.clear();
}
/** Sets a new value to the i-th parameter.
* @param i :: The parameter index
* @param value :: The new value
......@@ -263,152 +257,10 @@ void ParamFunction::unfix(size_t i) {
m_isFixed[i] = false;
}
/**
* Attaches a tie to this ParamFunction. The attached tie is owned by the
* ParamFunction.
* @param tie :: A pointer to a new tie
*/
void ParamFunction::addTie(std::unique_ptr<ParameterTie> tie) {
size_t iPar = tie->getIndex();
bool found = false;
for (auto &m_tie : m_ties) {
if (m_tie->getIndex() == iPar) {
found = true;
m_tie = std::move(tie);
break;
}
}
if (!found) {
m_ties.push_back(std::move(tie));
}
}
/**
* Apply the ties.
*/
void ParamFunction::applyTies() {
for (auto &m_tie : m_ties) {
m_tie->eval();
}
}
/**
* Used to find ParameterTie for a parameter i
*/
class ReferenceEqual {
/// index to find
const size_t m_i;
public:
/// Constructor
explicit ReferenceEqual(size_t i) : m_i(i) {}
/// Bracket operator
/// @param p :: the element you are looking for
/// @return True if found
template <class T> bool operator()(const std::unique_ptr<T> &p) {
return p->getIndex() == m_i;
}
};
/** Removes i-th parameter's tie if it is tied or does nothing.
* @param i :: The index of the tied parameter.
* @return True if successfull
*/
bool ParamFunction::removeTie(size_t i) {
if (i >= nParams()) {
throw std::out_of_range("ParamFunction parameter index out of range.");
}
auto it = std::find_if(m_ties.begin(), m_ties.end(), ReferenceEqual(i));
if (it != m_ties.end()) {