bpp-core3  3.0.0
AbstractParameterAliasable.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
6 #include "VectorTools.h"
7 
8 using namespace bpp;
9 using namespace std;
10 
13  independentParameters_(),
14  aliasListenersRegister_()
15 {
16  for (size_t i = 0; i < ap.independentParameters_.size(); ++i)
17  {
19  }
20 
21  // Actualize the register with adequate pointers:
22  for (auto it : ap.aliasListenersRegister_)
23  {
24  auto listener = shared_ptr<AliasParameterListener>(it.second->clone());
25  listener->setParameterList(&getParameters_());
26  aliasListenersRegister_[it.first] = listener;
27  // Now correct parameters with appropriate pointers:
28  for (unsigned int i = 0; i < getNumberOfParameters(); ++i)
29  {
30  if (getParameters_()[i].hasParameterListener(it.first))
31  {
32  getParameters_()[i].removeParameterListener(it.first);
33  getParameters_()[i].addParameterListener(listener);
34  }
35  }
36  }
37 }
38 
40 {
41  AbstractParametrizable::operator=(ap);
42 
43  for (size_t i = 0; i < ap.independentParameters_.size(); i++)
44  {
46  }
47 
48  // Actualize the register with adequate pointers:
49  for (auto it : ap.aliasListenersRegister_)
50  {
51  auto listener = shared_ptr<AliasParameterListener>(it.second->clone());
52  listener->setParameterList(&getParameters_());
53  aliasListenersRegister_[it.first] = listener;
54  // Now correct parameters with appropriate pointers:
55  for (unsigned int i = 0; i < getNumberOfParameters(); ++i)
56  {
57  if (getParameters_()[i].hasParameterListener(it.first))
58  {
59  getParameters_()[i].removeParameterListener(it.first);
60  getParameters_()[i].addParameterListener(listener);
61  }
62  }
63  }
64  return *this;
65 }
66 
67 void AbstractParameterAliasable::aliasParameters(const std::string& p1, const std::string& p2)
68 {
69  // In case this is the first time we call this method:
72 
73  if (!hasParameter(p1))
74  throw ParameterNotFoundException("AbstractParameterAliasable::aliasParameters", p1);
75  if (!hasParameter(p2))
76  throw ParameterNotFoundException("AbstractParameterAliasable::aliasParameters", p2);
78  throw Exception("AbstractParameterAliasable::aliasParameters. Parameter " + p2 + " does not exist in independent parameters. Perhaps it is already aliased to a parameter and can't be aliased twice.");
79 
80  string id = "__alias_" + p2 + "_to_" + p1;
81  string idCheck = "__alias_" + p1 + "_to_" + p2;
82 
83  if (aliasListenersRegister_.find(idCheck) != aliasListenersRegister_.end())
84  throw Exception("AbstractParameterAliasable::aliasParameters. Trying to alias parameter " + p2 + " to " + p1 + ", but parameter " + p1 + " is already aliased to parameter " + p2 + ".");
85  Parameter* param1 = &getParameter_(p1);
86  Parameter* param2 = &getParameter_(p2);
87 
88  if (!param1->hasConstraint())
89  {
90  if (param2->hasConstraint())
91  {
92  ApplicationTools::displayWarning("Aliasing parameter " + p2 + " to " + p1 + ". " + p1 + " gets the constraints of " + p2 + ": " + param2->getConstraint()->getDescription());
93  param1->setConstraint(param2->getConstraint());
94  }
95  }
96  else
97  // We use a small trick here, we test the constraints on the basis of their string description (C++ does not provide a default operator==() :( ).
98  if (param2->hasConstraint() && (param1->getConstraint()->getDescription() != param2->getConstraint()->getDescription()))
99  {
100  std::shared_ptr<ConstraintInterface> nc(*param2->getConstraint() & *param1->getConstraint());
101  ApplicationTools::displayWarning("Aliasing parameter " + p2 + " to " + p1 + " with different constraints. They get the intersection of both constraints : " + nc->getDescription());
102 
103  param2->setConstraint(nc);
104  param1->setConstraint(nc);
105  }
106 
107  // Every thing seems ok, let's create the listener and register it:
108 
109  auto aliasListener = make_shared<AliasParameterListener>(id, getParameters().whichParameterHasName(getNamespace() + p2), &getParameters_(), p1);
110 
111  aliasListenersRegister_[id] = aliasListener;
112 
113  // Now we add it to the appropriate parameter, that is p1.
114  param1->addParameterListener(aliasListener);
115 
116  // Finally we remove p2 from the list of independent parameters:
118 }
119 
120 void AbstractParameterAliasable::aliasParameters(map<string, string>& unparsedParams, bool verbose)
121 {
122  const ParameterList& pl = getParameters();
123  ParameterList plpars;
124 
125  for (size_t i = 0; i < pl.size(); i++)
126  {
127  if (unparsedParams.find(pl[i].getName()) == unparsedParams.end())
128  plpars.addParameter(pl[i].clone());
129  }
130 
131  size_t unp_s = unparsedParams.size();
132  while (unp_s != 0)
133  {
134  auto it = unparsedParams.begin();
135  while (it != unparsedParams.end())
136  {
137  Parameter* pp = 0;
138  try
139  {
140  pp = &plpars.parameter(it->second);
141  }
142  catch (ParameterNotFoundException& e)
143  {
144  if (!pl.hasParameter(it->second))
145  throw ParameterNotFoundException("Unknown aliasing parameter", it->first + "->" + it->second);
146  continue;
147  }
148  unique_ptr<Parameter> p2(pp->clone());
149  p2->setName(it->first);
150  plpars.addParameter(p2.release());
151  plpars.parameter(it->first);
152  aliasParameters(it->second, it->first);
153  if (verbose)
154  ApplicationTools::displayResult("Parameter alias found", it->first + " -> " + it->second + " = " + TextTools::toString(pp->getValue()));
155  it = unparsedParams.erase(it);
156  }
157 
158  if (unparsedParams.size() == unp_s)
159  throw Exception("Error, there is a cycle in aliasing starting with " + unparsedParams.begin()->first);
160  else
161  unp_s = unparsedParams.size();
162  }
163 
164  matchParametersValues(plpars);
165 }
166 
167 
168 void AbstractParameterAliasable::unaliasParameters(const std::string& p1, const std::string& p2)
169 {
170  if (!hasParameter(p1))
171  throw ParameterNotFoundException("AbstractParameterAliasable::unaliasParameters", p1);
172  if (!hasParameter(p2))
173  throw ParameterNotFoundException("AbstractParameterAliasable::unaliasParameters", p2);
174 
175  string id = "__alias_" + p2 + "_to_" + p1;
176  auto it = aliasListenersRegister_.find(id);
177  if (it == aliasListenersRegister_.end())
178  throw Exception("AbstractParameterAliasable::unaliasParameters. Parameter " + p2 + " is not aliased to parameter " + p1 + ".");
179  // Remove the listener:
181  aliasListenersRegister_.erase(it);
182  // Finally we re-add p2 to the list of independent parameters:
184 }
185 
186 void AbstractParameterAliasable::setNamespace(const std::string& prefix)
187 {
188  string currentName;
189 
190  // We modify all the listeners
191  for (auto& it : aliasListenersRegister_)
192  {
193  currentName = it.second->getName();
194  if (TextTools::startsWith(currentName, getNamespace()))
195  it.second->rename(prefix + currentName.substr(getNamespace().size()));
196  else
197  it.second->rename(prefix + currentName);
198  }
199 
200  // Finally we notify the mother class:
202 }
203 
204 vector<string> AbstractParameterAliasable::getAlias(const string& name) const
205 {
206  vector<string> aliases;
207 
208  for (const auto& it : aliasListenersRegister_)
209  {
210  if (it.second->getFrom() == name)
211  {
212  string alias = it.second->getAlias();
213  aliases.push_back(alias);
214  if (alias != name)
215  {
216  vector<string> chainAliases = getAlias(alias);
217  VectorTools::append(aliases, chainAliases);
218  }
219  }
220  }
221  return aliases;
222 }
223 
224 
225 std::map<std::string, std::string> AbstractParameterAliasable::getAliases() const
226 {
227  map<string, string> aliases;
228 
229  for (const auto& it : aliasListenersRegister_)
230  {
231  string name = it.second->getFrom();
232 
233  vector<string> alias = getAlias(name);
234 
235  for (auto a : alias)
236  {
237  aliases[a] = name;
238  }
239  }
240 
241  return aliases;
242 }
243 
245 {
246  ParameterList aliases;
247  bool b = false;
248 
249  for (const auto& it : aliasListenersRegister_)
250  {
251  if ((pl.hasParameter(it.second->getFrom()) ||
252  aliases.hasParameter(it.second->getFrom()))
253  && !(aliases.hasParameter(it.second->getAlias()) ||
254  pl.hasParameter(it.second->getAlias())))
255  {
256  b = true;
257  aliases.addParameter(parameter(it.second->getAlias()));
258  }
259  }
260 
261  while (b)
262  {
263  b = false;
264 
265  for (const auto& it : aliasListenersRegister_)
266  {
267  if (aliases.hasParameter(it.second->getFrom())
268  && !(aliases.hasParameter(it.second->getAlias()) ||
269  pl.hasParameter(it.second->getAlias())))
270  {
271  b = true;
272  aliases.addParameter(parameter(it.second->getAlias()));
273  }
274  }
275  }
276 
277  return aliases;
278 }
279 
280 string AbstractParameterAliasable::getFrom(const string& name) const
281 {
282  string from = "";
283 
284  for (const auto& it : aliasListenersRegister_)
285  {
286  if (it.second->getName() == name)
287  {
288  from = it.second->getFrom();
289  break;
290  }
291  }
292 
293  return from;
294 }
295 
296 
298 {
299  ParameterList from;
300  bool b = false;
301 
302  for (const auto& it : aliasListenersRegister_)
303  {
304  if ((pl.hasParameter(it.second->getAlias()) ||
305  from.hasParameter(it.second->getAlias()))
306  && !(from.hasParameter(it.second->getFrom()) ||
307  pl.hasParameter(it.second->getFrom())))
308  {
309  b = true;
310  from.addParameter(parameter(it.second->getFrom()));
311  }
312  }
313 
314  while (b)
315  {
316  b = false;
317 
318  for (const auto& it : aliasListenersRegister_)
319  {
320  if (from.hasParameter(it.second->getAlias())
321  && !(from.hasParameter(it.second->getFrom()) ||
322  pl.hasParameter(it.second->getFrom())))
323  {
324  b = true;
325  from.addParameter(parameter(it.second->getFrom()));
326  }
327  }
328  }
329 
330  return from;
331 }
Exception thrown when a parameter is not found, for instance in a ParameterList.
static void displayWarning(const std::string &text)
Print a warning message.
virtual std::vector< std::string > getAlias(const std::string &name) const
std::string getNamespace() const override
virtual const Parameter & parameter(const std::string &name) const
Get the parameter with name name.
Parameter * clone() const
Create a copy of this object and send a pointer to it.
Definition: Parameter.h:140
virtual void addParameterListener(std::shared_ptr< ParameterListener > listener)
Add a new listener to this parameter.
Definition: Parameter.h:261
void unaliasParameters(const std::string &p1, const std::string &p2)
Detach two parameters previously set as &#39;aliased&#39;.
A partial implementation of the Parametrizable interface.
void setNamespace(const std::string &prefix) override
Set the namespace for the parameter names.
virtual void shareParameter(const std::shared_ptr< Parameter > &param)
Share a parameter at the end of the list.
const std::shared_ptr< Parameter > & getParameter(const std::string &name) const
static void displayResult(const std::string &text, const T &result)
Print a result message.
size_t size() const
Definition: ParameterList.h:56
STL namespace.
This class is designed to facilitate the manipulation of parameters.
Definition: Parameter.h:97
ParameterList getFromParameters(const ParameterList &pl) const
Return the list of the names of the parameters from which the parameters of the list are aliased (dir...
virtual void setConstraint(std::shared_ptr< ConstraintInterface > constraint)
Set a constraint to this parameter.
Definition: Parameter.cpp:76
virtual void deleteParameter(const std::string &name)
Delete a parameter from the list.
static void append(std::vector< T > &vec1, const std::vector< T > &vec2)
Append the content of a std::vector to another one.
Definition: VectorTools.h:1899
The parameter list object.
Definition: ParameterList.h:27
virtual bool hasConstraint() const
Tells if this parameter has a constraint.
Definition: Parameter.h:238
virtual std::shared_ptr< const ConstraintInterface > getConstraint() const
Return the constraint associated to this parameter if there is one.
Definition: Parameter.h:196
virtual void removeParameterListener(const std::string &listenerId)
Remove all listeners with a given id from this parameter.
Definition: Parameter.cpp:94
A partial implementation of the Parametrizable interface.
bool matchParametersValues(const ParameterList &parameters) override
Update the parameters from parameters.
virtual std::map< std::string, std::string > getAliases() const
std::map< std::string, std::shared_ptr< AliasParameterListener > > aliasListenersRegister_
ParameterList * clone() const
Create a copy of this object and send a pointer to it.
Definition: ParameterList.h:48
virtual bool hasParameter(const std::string &name) const
bool hasParameter(const std::string &name) const override
Tell if there is a parameter with specified name.
std::string getFrom(const std::string &name) const
virtual void shareParameters(const ParameterList &params)
Share parameters with a given list. They are added the end of this list.
virtual size_t whichParameterHasName(const std::string &name) const
Get the position of a given parameter according to its name.
ParameterList & getParameters_() override
Get all parameters available.
AbstractParameterAliasable & operator=(const AbstractParameterAliasable &ap)
virtual void addParameter(const Parameter &param)
Add a new parameter at the end of the list.
Exception base class. Overload exception constructor (to control the exceptions mechanism). Destructor is already virtual (from std::exception)
Definition: Exceptions.h:20
std::string getParameterNameWithoutNamespace(const std::string &name) const override
Resolves a parameter name according to the current namespace.
AbstractParameterAliasable(const std::string &prefix)
void setNamespace(const std::string &prefix)
Set the namespace for the parameter names.
virtual double getValue() const
Get the value of this parameter.
Definition: Parameter.h:181
void aliasParameters(const std::string &p1, const std::string &p2)
alias the parameters.
Parameter & getParameter_(const std::string &name)
std::string toString(T t)
General template method to convert to a string.
Definition: TextTools.h:115
size_t getNumberOfParameters() const override
Get the number of parameters.
bool startsWith(const std::string &s, const std::string &pattern)
Tell is a string begins with a certain motif.
Definition: TextTools.cpp:402
ParameterList getAliasedParameters(const ParameterList &pl) const
Return the list of the names of the parameters that are aliased (directly or not) to one of the param...
const Parameter & parameter(const std::string &name) const override
Get the parameter with specified name.
const ParameterList & getParameters() const override
Get all parameters available.