bpp-phyl3  3.0.0
MixtureOfATransitionModel.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
5 #include <Bpp/Exceptions.h>
9 #include <string>
10 
12 
13 using namespace bpp;
14 using namespace std;
15 
16 
18  std::shared_ptr<const Alphabet> alpha,
19  std::unique_ptr<TransitionModelInterface> model,
20  std::map<std::string, std::unique_ptr<DiscreteDistributionInterface>>& parametersDistributionsList,
21  int ffrom,
22  int tto) :
23  AbstractParameterAliasable(model->getNamespace()),
24  AbstractTransitionModel(alpha, model->getStateMap(), model->getNamespace()),
25  AbstractMixedTransitionModel(alpha, getStateMap(), model->getNamespace()),
26  distributionMap_(),
27  from_(ffrom),
28  to_(tto)
29 {
30  if (to_ >= int(alpha->getSize()))
31  throw BadIntegerException("Bad state in alphabet", to_);
32  if (from_ >= int(alpha->getSize()))
33  throw BadIntegerException("Bad state in alphabet", from_);
34 
35  size_t c, i;
36  string s1, s2, t;
37 
38  // Initialization of distributionMap_.
39 
40  vector<string> parnames = model->getParameters().getParameterNames();
41 
42  for (i = 0; i < model->getNumberOfParameters(); i++)
43  {
44  s1 = parnames[i];
46 
47  if (parametersDistributionsList.find(s2) != parametersDistributionsList.end())
48  distributionMap_[s1].reset(parametersDistributionsList.find(s2)->second->clone());
49  else
51 
52 
53  if (dynamic_cast<ConstantDistribution*>(distributionMap_[s1].get()) == nullptr)
54  distributionMap_[s1]->setNamespace(s1 + "_" + distributionMap_[s1]->getNamespace());
55  else
56  distributionMap_[s1]->setNamespace(s1 + "_");
57 
58  auto constr = model->parameter(s2).getConstraint();
59  if (constr)
60  distributionMap_[s1]->restrictToConstraint(*constr);
61  }
62 
63  // Initialization of modelsContainer_.
64 
65  c = 1;
66 
67  for (auto& it : distributionMap_)
68  {
69  c *= it.second->getNumberOfCategories();
70  }
71 
72  for (i = 0; i < c; i++)
73  {
74  modelsContainer_.push_back(std::unique_ptr<TransitionModelInterface>(model->clone()));
75  vProbas_.push_back(1.0 / static_cast<double>(c));
76  vRates_.push_back(1.0);
77  }
78  // Initialization of parameters_.
79 
80 
82 
83  for (auto& it : distributionMap_)
84  {
86  pd = it.second.get();
87  if (pm.hasConstraint())
88  {
90  }
91 
92  if (!dynamic_cast<ConstantDistribution*>(it.second.get()))
93  {
94  const ParameterList pl = pd->getParameters();
95  for (i = 0; i != it.second->getNumberOfParameters(); ++i)
96  {
97  addParameter_(pl[i].clone());
98  }
99  }
100  else
101  {
102  // addParameter_(new Parameter(it.first, pd->getCategory(0), (pd->parameter("value").getConstraint()) ? shared_ptr<ConstraintInterface>(pd->parameter("value").getConstraint()->clone()) : nullptr));
103  addParameter_(new Parameter(it.first, pd->getCategory(0), pm.hasConstraint() ? shared_ptr<ConstraintInterface>(pm.getConstraint()->clone()) : nullptr));
104  }
105  }
106  updateMatrices_();
107 }
108 
113  distributionMap_(),
114  from_(msm.from_),
115  to_(msm.to_)
116 {
117  for (auto& it : msm.distributionMap_)
118  {
119  distributionMap_[it.first].reset(it.second->clone());
120  }
121 }
122 
124 {
127  from_ = msm.from_;
128  to_ = msm.to_;
129 
130  // Clear existing containers:
131  distributionMap_.clear();
132 
133  // Now copy new containers:
134  for (auto& it : msm.distributionMap_)
135  {
136  distributionMap_[it.first].reset(it.second->clone());
137  }
138  return *this;
139 }
140 
141 
143 
145 {
146  string s, t;
147  size_t j, l;
148  double d;
149  ParameterList pl;
150 
151  // Update of distribution parameters from the parameters_ member
152  // data. (reverse operation compared to what has been done in the
153  // constructor).
154  // vector<string> v=getParameters().getParameterNames();
155 
156  for (auto& distrib : distributionMap_)
157  {
158  if (dynamic_cast<ConstantDistribution*>(distrib.second.get()) == nullptr)
159  {
160  vector<string> vDistnames = distrib.second->getParameters().getParameterNames();
161  for (auto& parname : vDistnames)
162  {
164  pl.addParameter(Parameter(parname, d));
165  }
166  distrib.second->matchParametersValues(pl);
167  pl.reset();
168  }
169  else
170  {
171  t = distrib.second->getNamespace();
172  d = parameter(getParameterNameWithoutNamespace(t.substr(0, t.length() - 1))).getValue();
173  distrib.second->setParameterValue("value", d);
174  }
175  }
176 
177  for (size_t i = 0; i < modelsContainer_.size(); i++)
178  {
179  vProbas_[i] = 1;
180  j = i;
181  for (auto& distrib : distributionMap_)
182  {
183  s = distrib.first;
184  l = j % distrib.second->getNumberOfCategories();
185 
186  d = distrib.second->getCategory(l);
187  vProbas_[i] *= distrib.second->getProbability(l);
188  if (pl.hasParameter(s))
189  pl.setParameterValue(s, d);
190  else
191  pl.addParameter(Parameter(s, d));
192 
193  j = j / distrib.second->getNumberOfCategories();
194  }
195 
196  modelsContainer_[i]->matchParametersValues(pl);
197  }
198 
199  // setting the equilibrium freqs
200  for (size_t i = 0; i < getNumberOfStates(); i++)
201  {
202  freq_[i] = 0;
203  for (j = 0; j < modelsContainer_.size(); j++)
204  {
205  freq_[i] += vProbas_[j] * modelsContainer_[j]->freq(i);
206  }
207  }
208 }
209 
210 void MixtureOfATransitionModel::setFreq(std::map<int, double>& m)
211 {
212  modelsContainer_[0]->setFreq(m);
214 }
215 
217 {
218  vector<string> parnames = modelsContainer_[0]->getParameters().getParameterNames();
219  std::map<std::string, size_t> msubn;
220 
221  StringTokenizer st(desc, ",");
222  while (st.hasMoreToken())
223  {
224  string param = st.nextToken();
225  string::size_type index = param.rfind("_");
226  if (index == string::npos)
227  throw Exception("MixtureOfATransitionModel::getSubmodelNumbers parameter description should contain a number " + param);
228  msubn[param.substr(0, index)] = TextTools::to<size_t>(param.substr(index + 1, 4)) - 1;
229  }
230 
231  Vuint submodnb;
232  size_t l;
233  string s;
234 
235  for (size_t i = 0; i < modelsContainer_.size(); ++i)
236  {
237  size_t stopped = 0;
238  size_t j = i;
239  for (auto& it : distributionMap_)
240  {
241  s = it.first;
242  l = j % it.second->getNumberOfCategories();
243 
244  if (msubn.find(s) != msubn.end())
245  {
246  if (msubn[s] == l)
247  {
248  stopped++;
249  }
250  }
251 
252  j = j / it.second->getNumberOfCategories();
253  }
254  if (stopped == msubn.size())// All requests are fulfilled
255  submodnb.push_back(uint(i));
256  }
257 
258  return submodnb;
259 }
Partial implementation for Mixed Transition models, defined as a mixture of "simple" substitution mod...
std::vector< double > vProbas_
vector of the probabilities of the models
AbstractMixedTransitionModel & operator=(const AbstractMixedTransitionModel &)
std::vector< double > vRates_
vector of the rates of the models.
std::vector< std::shared_ptr< TransitionModelInterface > > modelsContainer_
vector of pointers to TransitionModels.
void addParameter_(Parameter *parameter)
AbstractParameterAliasable & operator=(const AbstractParameterAliasable &ap)
const Parameter & parameter(const std::string &name) const override
bool matchParametersValues(const ParameterList &parameters) override
std::string getNamespace() const override
std::string getParameterNameWithoutNamespace(const std::string &name) const override
const ParameterList & getParameters() const override
double getParameterValue(const std::string &name) const override
Partial implementation of the TransitionModel interface.
Vdouble freq_
The vector of equilibrium frequencies.
size_t getNumberOfStates() const override
Get the number of states.
virtual double getCategory(size_t categoryIndex) const=0
virtual void restrictToConstraint(const ConstraintInterface &c)=0
Transition models defined as a mixture of nested substitution models.
void updateMatrices_() override
Diagonalize the matrix, and fill the eigenValues_, iEigenValues_, leftEigenVectors_ and rightEigenVe...
Vuint getSubmodelNumbers(const std::string &desc) const override
Returns the vector of numbers of the submodels in the mixture that match a description of the paramet...
MixtureOfATransitionModel & operator=(const MixtureOfATransitionModel &)
void setFreq(std::map< int, double > &) override
sets the eq frequencies of the first nested model, and adapts the parameters at best to it (surely th...
std::map< std::string, std::unique_ptr< DiscreteDistributionInterface > > distributionMap_
MixtureOfATransitionModel(std::shared_ptr< const Alphabet > alpha, std::unique_ptr< TransitionModelInterface > model, std::map< std::string, std::unique_ptr< DiscreteDistributionInterface >> &parametersDistributionsList, int ffrom=-1, int tto=-1)
const TransitionModelInterface & model(const std::string &name) const override
retrieve a pointer to the submodel with the given name.
MixtureOfATransitionModel * clone() const override
virtual bool hasParameter(const std::string &name) const
virtual std::vector< std::string > getParameterNames() const
virtual void setParameterValue(const std::string &name, double value)
virtual void addParameter(const Parameter &param)
virtual void reset()
virtual double getValue() const
virtual std::shared_ptr< const ConstraintInterface > getConstraint() const
virtual bool hasConstraint() const
virtual std::string getParameterNameWithoutNamespace(const std::string &name) const=0
virtual size_t getNumberOfParameters() const=0
virtual double getParameterValue(const std::string &name) const=0
virtual const ParameterList & getParameters() const=0
virtual const Parameter & parameter(const std::string &name) const=0
const std::string & nextToken()
bool hasMoreToken() const
TransitionModelInterface * clone() const =0
Defines the basic types of data flow nodes.
std::vector< unsigned int > Vuint