bpp-core  2.2.0
AbstractParameterAliasable.cpp
Go to the documentation of this file.
1 //
2 // File: AbstractParameterAliasable.cpp
3 // Created by: Julien Dutheil
4 // Created on: Sun Mar 29 09:10 2009
5 //
6 
7 /*
8  Copyright or © or Copr. Bio++ Development Team, (November 19, 2004)
9 
10  This software is a computer program whose purpose is to provide classes
11  for numerical calculus.
12 
13  This software is governed by the CeCILL license under French law and
14  abiding by the rules of distribution of free software. You can use,
15  modify and/ or redistribute the software under the terms of the CeCILL
16  license as circulated by CEA, CNRS and INRIA at the following URL
17  "http://www.cecill.info".
18 
19  As a counterpart to the access to the source code and rights to copy,
20  modify and redistribute granted by the license, users are provided only
21  with a limited warranty and the software's author, the holder of the
22  economic rights, and the successive licensors have only limited
23  liability.
24 
25  In this respect, the user's attention is drawn to the risks associated
26  with loading, using, modifying and/or developing or reproducing the
27  software by the user in light of its specific status of free software,
28  that may mean that it is complicated to manipulate, and that also
29  therefore means that it is reserved for developers and experienced
30  professionals having in-depth computer knowledge. Users are therefore
31  encouraged to load and test the software's suitability as regards their
32  requirements in conditions enabling the security of their systems and/or
33  data to be ensured and, more generally, to use and operate it in the
34  same conditions as regards security.
35 
36  The fact that you are presently reading this means that you have had
37  knowledge of the CeCILL license and that you accept its terms.
38  */
39 
41 #include "VectorTools.h"
42 
43 using namespace bpp;
44 using namespace std;
45 
48  independentParameters_(ap.independentParameters_),
49  aliasListenersRegister_()
50 {
51  // Actualize the register with adequate pointers:
52  for (map<string, AliasParameterListener*>::const_iterator it = ap.aliasListenersRegister_.begin();
53  it != ap.aliasListenersRegister_.end();
54  it++)
55  {
56  AliasParameterListener* listener = it->second->clone();
57  listener->setParameterList(&getParameters_());
58  aliasListenersRegister_[it->first] = listener;
59  //Now correct parameters with appropriate pointers:
60  for (unsigned int i = 0; i < getNumberOfParameters(); ++i) {
61  if (getParameters_()[i].hasParameterListener(it->first)) {
62  getParameters_()[i].removeParameterListener(it->first);
63  getParameters_()[i].addParameterListener(listener, false);
64  }
65  }
66  }
67 }
68 
70 {
72 
73  // Actualize the register with adequate pointers:
74  for (map<string, AliasParameterListener*>::const_iterator it = ap.aliasListenersRegister_.begin();
75  it != ap.aliasListenersRegister_.end();
76  it++)
77  {
78  AliasParameterListener* listener = it->second->clone();
79  listener->setParameterList(&getParameters_());
80  aliasListenersRegister_[it->first] = listener;
81  //Now correct parameters with appropriate pointers:
82  for (unsigned int i = 0; i < getNumberOfParameters(); ++i) {
83  if (getParameters_()[i].hasParameterListener(it->first)) {
84  getParameters_()[i].removeParameterListener(it->first);
85  getParameters_()[i].addParameterListener(listener, false);
86  }
87  }
88  }
89  return *this;
90 }
91 
93 {
94  // Delete the registry content:
95  for (map<string, AliasParameterListener*>::iterator it = aliasListenersRegister_.begin();
96  it != aliasListenersRegister_.end();
97  it++)
98  {
99  delete it->second;
100  }
101 }
102 
103 void AbstractParameterAliasable::aliasParameters(const std::string& p1, const std::string& p2)
105 {
106  // In case this is the first time we call this method:
107  if (getNumberOfParameters() > 0 && independentParameters_.size() == 0)
108  independentParameters_ = getParameters();
109 
110  if (!hasParameter(p1))
111  throw ParameterNotFoundException("AbstractParameterAliasable::aliasParameters", p1);
112  if (!hasParameter(p2))
113  throw ParameterNotFoundException("AbstractParameterAliasable::aliasParameters", p2);
114  if (!independentParameters_.hasParameter(getNamespace() + p2))
115  throw Exception("AbstractParameterAliasable::aliasParameters. Parameter " + p2 + " is already aliased to a parameter and can't be aliased twice.");
116 
117  string id = "__alias_" + p2 + "_to_" + p1;
118  string idCheck = "__alias_" + p1 + "_to_" + p2;
119 
120  if (aliasListenersRegister_.find(idCheck) != aliasListenersRegister_.end())
121  throw Exception("AbstractParameterAliasable::aliasParameters. Trying to alias parameter " + p2 + " to " + p1 + ", but parameter " + p1 + " is already aliased to parameter " + p2 + ".");
122  Parameter* param1 = &getParameter_(p1);
123  Parameter* param2 = &getParameter_(p2);
124 
125  if (!param1->hasConstraint())
126  {
127  if (param2->hasConstraint())
128  throw Exception("AbstractParameterAliasable::aliasParameters. Cannot alias parameter " + p2 + " to " + p1 + ", because the constraints attached to these two parameters are different.");
129  }
130  else
131  // We use a small trick here, we test the constraints on the basis of their string description (C++ does not provide a default operator==() :( ).
132  if (param2->hasConstraint() && (param1->getConstraint()->getDescription() != param2->getConstraint()->getDescription()))
133  throw Exception("AbstractParameterAliasable::aliasParameters. Cannot alias parameter " + p2 + " to " + p1 + ", because the constraints attached to these two parameters are different.");
134 
135  // Every thing seems ok, let's create the listener and register it:
136 
137  AliasParameterListener* aliasListener = new AliasParameterListener(id, getParameters().whichParameterHasName(getNamespace() + p2), &getParameters_(), p1);
138 
139  ParameterList pl=getParameters_();
140 
141  aliasListenersRegister_[id] = aliasListener;
142 
143  // Now we add it to the appropriate parameter, that is p1.
144  // The parameter will not own the listener, the bookkeeping being achieved by the register:
145  param1->addParameterListener(aliasListener, false);
146  // Finally we remove p2 from the list of independent parameters:
147  independentParameters_.deleteParameter(getNamespace() + p2);
148 
149 }
150 
151 void AbstractParameterAliasable::aliasParameters(map<string, string>& unparsedParams, bool verbose)
152 {
153  ParameterList plpars, pl=getParameters();
154 
155  for (size_t i=0; i< pl.size(); i++)
156  {
157  if (unparsedParams.find(pl[i].getName())==unparsedParams.end())
158  plpars.addParameter(*pl[i].clone());
159  }
160 
161  size_t unp_s=unparsedParams.size();
162  while (unp_s!=0)
163  {
164  map<string, string>::iterator it;
165  for (it=unparsedParams.begin(); it!=unparsedParams.end(); it++)
166  {
167  Parameter* pp=0;
168  try {
169  pp=&plpars.getParameter(it->second);
170  }
171  catch (ParameterNotFoundException& e){
172  if (!pl.hasParameter(it->second))
173  throw ParameterNotFoundException("Unknown aliasing parameter", it->second);
174  continue;
175  }
176  auto_ptr<Parameter> p2(pp->clone());
177  p2->setName(it->first);
178  plpars.addParameter(p2.release());
179  plpars.getParameter(it->first);
180  aliasParameters(it->second, it->first);
181  if (verbose)
182  ApplicationTools::displayResult("Parameter alias found", it->first + " -> " + it->second + " = " + TextTools::toString(pp->getValue()));
183  unparsedParams.erase(it);
184  }
185 
186  if (unparsedParams.size()==unp_s)
187  throw Exception("Error, there is a cycle in aliasing");
188  else
189  unp_s=unparsedParams.size();
190  }
191 
192  matchParametersValues(plpars);
193 }
194 
195 
196 
197 
198 void AbstractParameterAliasable::unaliasParameters(const std::string& p1, const std::string& p2)
200 {
201  if (!hasParameter(p1))
202  throw ParameterNotFoundException("AbstractParameterAliasable::unaliasParameters", p1);
203  if (!hasParameter(p2))
204  throw ParameterNotFoundException("AbstractParameterAliasable::unaliasParameters", p2);
205 
206  string id = "__alias_" + p2 + "_to_" + p1;
207  map<string, AliasParameterListener*>::iterator it = aliasListenersRegister_.find(id);
208  if (it == aliasListenersRegister_.end())
209  throw Exception("AbstractParameterAliasable::unaliasParameters. Parameter " + p2 + " is not aliased to parameter " + p1 + ".");
210  // Remove the listener:
211  getParameter_(p1).removeParameterListener(id);
212  delete it->second;
213  aliasListenersRegister_.erase(it);
214  // Finally we re-add p2 to the list of independent parameters:
215  independentParameters_.addParameter(getParameter(p2));
216 }
217 
218 void AbstractParameterAliasable::setNamespace(const std::string& prefix)
219 {
220  string currentName;
221  // First we correct the independent parameter list
222  for (unsigned int i = 0; i < independentParameters_.size(); i++)
223  {
224  currentName = independentParameters_[i].getName();
225  if (TextTools::startsWith(currentName, getNamespace()))
226  independentParameters_[i].setName(prefix + currentName.substr(getNamespace().size()));
227  else
228  independentParameters_[i].setName(prefix + currentName);
229  }
230  // Then we modify all the listeners
231  for (map<string, AliasParameterListener*>::iterator it = aliasListenersRegister_.begin();
232  it != aliasListenersRegister_.end();
233  it++)
234  {
235  currentName = it->second->getName();
236  if (TextTools::startsWith(currentName, getNamespace()))
237  it->second->rename(prefix + currentName.substr(getNamespace().size()));
238  else
239  it->second->rename(prefix + currentName);
240  }
241  // Finally we notify the mother class:
243 }
244 
245 vector<string> AbstractParameterAliasable::getAlias(const string& name) const
246 {
247  vector<string> aliases;
248 
249  for (map<string, AliasParameterListener*>::const_iterator it = aliasListenersRegister_.begin();
250  it != aliasListenersRegister_.end();
251  it++)
252  {
253  if (it->second->getFrom() == name)
254  {
255  string alias = it->second->getAlias();
256  aliases.push_back(alias);
257  if (alias!=name){
258  vector<string> chainAliases = getAlias(alias);
259  VectorTools::append(aliases, chainAliases);
260  }
261  }
262  }
263  return aliases;
264 }
265 
267 {
268  ParameterList aliases;
269  bool b=false;
270 
271  for (map<string, AliasParameterListener*>::const_iterator it = aliasListenersRegister_.begin();
272  it != aliasListenersRegister_.end();
273  it++)
274  {
275  if ((pl.hasParameter(it->second->getFrom()) ||
276  aliases.hasParameter(it->second->getFrom()))
277  && ! (aliases.hasParameter(it->second->getAlias()) ||
278  pl.hasParameter(it->second->getAlias())))
279  {
280  b=true;
281  aliases.addParameter(getParameter(it->second->getAlias()));
282  }
283  }
284 
285  while (b)
286  {
287  b=false;
288 
289  for (map<string, AliasParameterListener*>::const_iterator it = aliasListenersRegister_.begin();
290  it != aliasListenersRegister_.end();
291  it++)
292  {
293  if (aliases.hasParameter(it->second->getFrom())
294  && ! (aliases.hasParameter(it->second->getAlias()) ||
295  pl.hasParameter(it->second->getAlias())))
296  {
297  b=true;
298  aliases.addParameter(getParameter(it->second->getAlias()));
299  }
300  }
301  }
302 
303  return aliases;
304 }
305 
306 string AbstractParameterAliasable::getFrom(const string& name) const
307 {
308  string from="";
309 
310  for (map<string, AliasParameterListener*>::const_iterator it = aliasListenersRegister_.begin();
311  it != aliasListenersRegister_.end();
312  it++)
313  {
314  if (it->second->getName() == name)
315  {
316  from = it->second->getFrom();
317  break;
318  }
319  }
320 
321  return from;
322 }
323 
Exception thrown when a parameter is not found, for instance in a ParameterList.
std::vector< std::string > getAlias(const std::string &name) const
Parameter * clone() const
Create a copy of this object and send a pointer to it.
Definition: Parameter.h:199
virtual const Constraint * getConstraint() const
Return the constraint associated to this parameter if there is one.
Definition: Parameter.h:255
This class allows to perform a correspondence analysis.
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.
static void displayResult(const std::string &text, const T &result)
Print a result message.
size_t size() const
Definition: ParameterList.h:90
STL namespace.
This class is designed to facilitate the manipulation of parameters.
Definition: Parameter.h:135
virtual void addParameterListener(ParameterListener *listener, bool attachListener=true)
Add a new listener to this parameter.
Definition: Parameter.h:298
void aliasParameters(std::map< std::string, std::string > &unparsedParams, bool verbose)
alias the parameters following the links described in a map, and update the object accordingly...
size_t getNumberOfParameters() const
Get the number of parameters.
static std::string toString(T t)
General template method to convert to a string.
Definition: TextTools.h:189
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:1835
The parameter list object.
Definition: ParameterList.h:61
static bool startsWith(const std::string &s, const std::string &pattern)
Tell is a string begins with a certain motif.
Definition: TextTools.cpp:487
virtual bool hasConstraint() const
Tells if this parameter has a constraint.
Definition: Parameter.h:269
A partial implementation of the Parametrizable interface.
std::map< std::string, AliasParameterListener * > aliasListenersRegister_
AliasParameterListener * clone() const
Create a copy of this object and send a pointer to it.
ParameterList * clone() const
Create a copy of this object and send a pointer to it.
Definition: ParameterList.h:82
virtual bool hasParameter(const std::string &name) const
virtual std::string getDescription() const =0
Give a short description on the type of constraint.
std::string getFrom(const std::string &name) const
bool matchParametersValues(const ParameterList &parameters)
Update the parameters from parameters.
const Parameter & getParameter(const std::string &name) const
Get the parameter with specified name.
AbstractParameterAliasable & operator=(const AbstractParameterAliasable &ap)
virtual void addParameter(const Parameter &param)
Add a new parameter at the end of the list.
Exception base class.
Definition: Exceptions.h:57
const ParameterList & getParameters() const
Get all parameters available.
AbstractParameterAliasable(const std::string &prefix)
void setNamespace(const std::string &prefix)
Set the namespace for the parameter names.
virtual const Parameter & getParameter(const std::string &name) const
Get the parameter with name name.
virtual double getValue() const
Get the value of this parameter.
Definition: Parameter.h:241
void aliasParameters(const std::string &p1, const std::string &p2)
Set two parameters as &#39;aliased&#39;.
void setParameterList(ParameterList *pl)
void setNamespace(const std::string &prefix)
Set the namespace for the parameter names.
Inner listener class used by AbstractParameterAliasable.
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...