Mantid
Loading...
Searching...
No Matches
ParameterTie.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
10
11#include <boost/lexical_cast.hpp>
12#include <boost/regex.hpp>
13
14namespace Mantid::API {
15
23ParameterTie::ParameterTie(IFunction *funct, const std::string &parName, const std::string &expr, bool isDefault)
24 : ParameterReference(funct, funct->parameterIndex(parName), isDefault), m_parser(std::make_unique<mu::Parser>()),
25 m_function1(funct) {
26 m_parser->DefineNameChars("0123456789_."
27 "abcdefghijklmnopqrstuvwxyz"
28 "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
29 m_parser->SetVarFactory(AddVariable, this);
30 if (!expr.empty()) {
31 set(expr);
32 }
33}
34
37 for (std::map<double *, ParameterReference>::const_iterator it = m_varMap.begin(); it != m_varMap.end(); ++it) {
38 delete it->first;
39 }
40}
41
47double *ParameterTie::AddVariable(const char *varName, void *palg) {
48 ParameterTie &tie = *reinterpret_cast<ParameterTie *>(palg);
49 ParameterReference ref(tie.m_function1, tie.m_function1->parameterIndex(std::string(varName)));
50
51 auto var = new double;
52 *var = 0;
53 tie.m_varMap[var] = ref;
54
55 return var;
56}
57
62void ParameterTie::set(const std::string &expr) {
63 for (std::map<double *, ParameterReference>::const_iterator it = m_varMap.begin(); it != m_varMap.end(); ++it) {
64 delete it->first;
65 }
66 if (!m_varMap.empty()) {
67 m_varMap.clear();
68 }
69 try { // Set the expression and initialize the variables
70 m_parser->SetExpr(expr);
71 m_parser->Eval();
73 throw std::invalid_argument("Function index was not specified in a parameter name");
74 } catch (std::exception &) {
75 throw;
76 } catch (...) {
77 throw std::runtime_error("Error in expresseion " + expr);
78 }
79
80 // Create the template m_expression
81 static const boost::regex rx(R"(\b(([[:alpha:]]|_)([[:alnum:]]|_|\.)*)\b(?!(\s*\‍()))");
82 std::string input = expr;
83 boost::smatch res;
84 std::string::const_iterator start = input.begin();
85 std::string::const_iterator end = input.end();
86
87 std::map<std::string, int> varNames;
88 int i = 0;
89 for (std::map<double *, ParameterReference>::const_iterator it = m_varMap.begin(); it != m_varMap.end(); ++it) {
90 varNames[m_function1->parameterName(m_function1->getParameterIndex(it->second))] = i;
91 i++;
92 }
93
94 m_expression = "";
95 while (boost::regex_search(start, end, res, rx)) {
96 m_expression.append(start, res[0].first);
97 m_expression += "#" + std::to_string(varNames[res[1]]);
98 start = res[0].second;
99 }
100 m_expression.append(start, end);
101}
102
103double ParameterTie::eval(bool setParameterValue) {
104 double res = 0;
105 try {
106 for (std::map<double *, ParameterReference>::const_iterator it = m_varMap.begin(); it != m_varMap.end(); ++it) {
107 *(it->first) = it->second.getParameter();
108 }
109 res = m_parser->Eval();
110 } catch (mu::ParserError &e) {
111 throw std::runtime_error("Error in expression: " + e.GetMsg());
112 }
113
114 if (setParameterValue)
115 setParameter(res);
116
117 return res;
118}
119
125std::string ParameterTie::asString(const IFunction *fun) const {
126 if (!fun) {
127 fun = m_function1;
128 }
129 std::string res_expression;
130 try {
131 res_expression = fun->parameterName(fun->getParameterIndex(*this)) + "=";
132
133 if (m_varMap.empty()) { // constants
134 return res_expression + m_expression;
135 ;
136 }
137
138 static const boost::regex rx(std::string("#(\\d+)"));
139 boost::smatch res;
140 std::string::const_iterator start = m_expression.begin();
141 std::string::const_iterator end = m_expression.end();
142
143 while (boost::regex_search(start, end, res, rx)) {
144 res_expression.append(start, res[0].first);
145
146 auto iTemp = boost::lexical_cast<int>(res[1]);
147 int i = 0;
148 for (const auto &var : m_varMap) {
149 if (i == iTemp) {
150 res_expression += fun->parameterName(fun->getParameterIndex(var.second));
151 break;
152 }
153 i++;
154 }
155
156 start = res[0].second;
157 }
158 res_expression.append(start, end);
159 } catch (...) { // parameters are not from function fun
160 throw std::logic_error("Corrupted tie " + m_expression + " in function " + getLocalFunction()->name());
161 }
162 return res_expression;
163}
164
172 if (getLocalFunction() == fun) {
173 return true;
174 }
175 return std::any_of(m_varMap.cbegin(), m_varMap.cend(),
176 [fun](const auto &element) { return element.second.isParameterOf(fun); });
177}
178
182bool ParameterTie::isConstant() const { return m_varMap.empty(); }
183
186std::vector<ParameterReference> ParameterTie::getRHSParameters() const {
187 std::vector<ParameterReference> out;
188 out.reserve(m_varMap.size());
189 std::transform(m_varMap.begin(), m_varMap.end(), std::back_inserter(out),
190 [](auto &&varPair) { return varPair.second; });
191 return out;
192}
193
194} // namespace Mantid::API
This is an interface to a fitting function - a semi-abstarct class.
Definition: IFunction.h:163
virtual size_t getParameterIndex(const ParameterReference &ref) const =0
Return parameter index from a parameter reference.
virtual std::string parameterName(size_t i) const =0
Returns the name of parameter i.
virtual size_t parameterIndex(const std::string &name) const =0
Returns the index of parameter name.
A reference to a parameter in a function.
void setParameter(const double &value, bool isExplicitlySet=true)
Set the parameter.
IFunction * getLocalFunction() const
Return pointer to the local function.
Ties fitting parameters.
Definition: ParameterTie.h:35
virtual void set(const std::string &expr)
Set the tie expression.
std::map< double *, ParameterReference > m_varMap
Store for parameters used in the tie.
Definition: ParameterTie.h:59
std::string m_expression
Keep the template for the input string passed to this->set(...) In the template CompositeFunction pre...
Definition: ParameterTie.h:64
std::unique_ptr< mu::Parser > m_parser
math parser
Definition: ParameterTie.h:56
bool isConstant() const
Check if the tie is a constant.
bool findParametersOf(const IFunction *fun) const
Check if the tie has any references to certain parameters.
~ParameterTie() override
Destructor.
virtual double eval(bool setParameterValue=true)
Evaluate the expression.
ParameterTie(IFunction *funct, const std::string &parName, const std::string &expr="", bool isDefault=false)
Constructor.
virtual std::string asString(const IFunction *fun=nullptr) const
Return the string that can be used to recreate this tie.
static double * AddVariable(const char *varName, void *palg)
MuParser callback function.
std::vector< ParameterReference > getRHSParameters() const
Get a list of parameters on the right-hand side of the equation.
IFunction * m_function1
Keep the function that was passed to the constructor.
Definition: ParameterTie.h:61
Marks code as not implemented yet.
Definition: Exception.h:138
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)