bpp-phyl3  3.0.0
MixtureOfTransitionModels.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 <Bpp/Text/TextTools.h>
7 #include <string>
8 
10 
11 using namespace bpp;
12 using namespace std;
13 
15  std::shared_ptr<const Alphabet> alpha,
16  vector<std::unique_ptr<TransitionModelInterface>>& vpModel) :
17  AbstractParameterAliasable("Mixture."),
18  AbstractTransitionModel(alpha, vpModel.size() ? vpModel[0]->getStateMap() : 0, "Mixture."),
19  AbstractMixedTransitionModel(alpha, vpModel.size() ? vpModel[0]->getStateMap() : 0, "Mixture.")
20 {
21  size_t i, nbmod = vpModel.size();
22  if (nbmod == 0)
23  throw Exception("MixtureOfTransitionModels::MixtureOfTransitionModels : empty vector of models.");
24 
25  for (i = 0; i < nbmod; ++i)
26  {
27  if (!vpModel[i])
28  throw Exception("Empty model number " + TextTools::toString(i) + " in MixtureOfTransitionModels constructor");
29  for (size_t j = i + 1; j < nbmod; ++j)
30  {
31  if (vpModel[i] == vpModel[j])
32  throw Exception("Same model at positions " + TextTools::toString(i) + " and " +
33  TextTools::toString(j) + " in MixtureOfTransitionModels constructor");
34  }
35  }
36 
37  // Initialization of modelsContainer_.
38 
39  for (i = 0; i < nbmod; i++)
40  {
41  modelsContainer_.push_back(std::move(vpModel[i]));
42  vProbas_.push_back(1.0 / static_cast<double>(nbmod));
43  vRates_.push_back(1.0);
44  }
45 
46  // Initialization of parameters_.
47 
48  // relative rates and probas
49  for (i = 0; i < nbmod - 1; i++)
50  {
51  addParameter_(new Parameter("Mixture.relproba" + TextTools::toString(i + 1), 1.0 / static_cast<double>(nbmod - i), Parameter::PROP_CONSTRAINT_EX));
52  addParameter_(new Parameter("Mixture.relrate" + TextTools::toString(i + 1), 1.0 / static_cast<double>(nbmod - i), Parameter::PROP_CONSTRAINT_EX));
53  }
54 
55  // models parameters
56 
57  for (i = 0; i < nbmod; i++)
58  {
59  modelsContainer_[i]->setNamespace("Mixture." + TextTools::toString(i + 1) + "_" + modelsContainer_[i]->getNamespace());
61  }
62 
64 }
65 
67  std::shared_ptr<const Alphabet> alpha,
68  vector<std::unique_ptr<TransitionModelInterface>>& vpModel,
69  Vdouble& vproba,
70  Vdouble& vrate) :
71  AbstractParameterAliasable("Mixture."),
72  AbstractTransitionModel(alpha, vpModel.size() ? vpModel[0]->getStateMap() : 0, "Mixture."),
73  AbstractMixedTransitionModel(alpha, vpModel.size() ? vpModel[0]->getStateMap() : 0, "Mixture.")
74 {
75  size_t i, nbmod = vpModel.size();
76 
77  for (i = 0; i < nbmod; ++i)
78  {
79  if (!vpModel[i])
80  throw Exception("Empty model number " + TextTools::toString(i) + " in MixtureOfTransitionModels constructor");
81  for (size_t j = i + 1; j < nbmod; ++j)
82  {
83  if (vpModel[i] == vpModel[j])
84  throw Exception("Same model at positions " + TextTools::toString(i) + " and " +
85  TextTools::toString(j) + " in MixtureOfTransitionModels constructor");
86  }
87  }
88 
89  double x = 0;
90  double sumrates = 0;
91 
92  for (i = 0; i < nbmod; i++)
93  {
94  if (vrate[i] <= 0)
95  throw Exception("Non positive rate: " + TextTools::toString(vrate[i]) + " in MixtureOfTransitionModels constructor.");
96  if (vproba[i] <= 0)
97  throw Exception("Non positive probability: " + TextTools::toString(vproba[i]) + " in MixtureOfTransitionModels constructor.");
98  x += vproba[i];
99  sumrates += vrate[i];
100  }
101 
102  if (fabs(1. - x) > NumConstants::SMALL())
103  throw Exception("Probabilities must equal 1 (sum = " + TextTools::toString(x) + ").");
104 
105 
106  // Initialization of modelsContainer_.
107 
108  for (i = 0; i < nbmod; i++)
109  {
110  modelsContainer_.push_back(std::move(vpModel[i]));
111  }
112 
113  // rates & probas
114 
115  vProbas_.resize(nbmod);
116  vRates_.resize(nbmod);
117 
118  // Initialization of parameters_.
119 
120  // relative rates and probas
121  x = 0;
122  double y = 0;
123 
124  for (i = 0; i < nbmod - 1; ++i)
125  {
126  addParameter_(new Parameter("Mixture.relproba" + TextTools::toString(i + 1), vproba[i] / (1 - x), Parameter::PROP_CONSTRAINT_EX));
127  x += vproba[i];
128  addParameter_(new Parameter("Mixture.relrate" + TextTools::toString(i + 1), vrate[i] / (sumrates - y), Parameter::PROP_CONSTRAINT_EX));
129  y += vrate[i];
130  }
131 
132  // models parameters
133 
134  for (i = 0; i < nbmod; ++i)
135  {
136  modelsContainer_[i]->setNamespace("Mixture." + TextTools::toString(i + 1) + "_" + modelsContainer_[i]->getNamespace());
138  }
139 
140  updateMatrices_();
141 }
142 
147 {}
148 
150 {
152 
153  return *this;
154 }
155 
156 
158 {}
159 
161 {
162  size_t nbmod = getNumberOfModels();
163 
164  for (size_t i = 0; i < nbmod; ++i)
165  {
166  if (nModel(i).getName() == name)
167  return nModel(i);
168  }
169 
170  throw NullPointerException("MixtureOfTransitionModels::model. No model with name '" + name + "'.");
171 }
172 
174 {
175  size_t i, j, nbmod = modelsContainer_.size();
176 
177  double x, y;
178  x = 1.0;
179 
180  for (i = 0; i < nbmod - 1; i++)
181  {
182  y = getParameterValue("relproba" + TextTools::toString(i + 1));
183  vProbas_[i] = x * y;
184  x *= 1 - y;
185  }
186  vProbas_[nbmod - 1] = x;
187 
188  x = 1.0;
189  double s = 0;
190  for (i = 0; i < nbmod - 1; i++)
191  {
192  y = getParameterValue("relrate" + TextTools::toString(i + 1));
193  vRates_[i] = x * y;
194  x *= 1 - y;
195  s += vProbas_[i] * vRates_[i];
196  }
197 
198  vRates_[nbmod - 1] = x;
199  s += vProbas_[nbmod - 1] * vRates_[nbmod - 1];
200 
201  for (i = 0; i < nbmod; i++)
202  {
203  vRates_[i] /= s;
204  }
205 
206  // models
207 
208  for (i = 0; i < nbmod; i++)
209  {
210  modelsContainer_[i]->setRate(rate_ * vRates_[i]);
211  modelsContainer_[i]->matchParametersValues(getParameters());
212  }
213 
214  // / freq_
215 
216  for (i = 0; i < getNumberOfStates(); i++)
217  {
218  freq_[i] = 0;
219  for (j = 0; j < modelsContainer_.size(); j++)
220  {
221  freq_[i] += vProbas_[j] * modelsContainer_[j]->freq(i);
222  }
223  }
224 }
225 
226 
227 void MixtureOfTransitionModels::setFreq(std::map<int, double>& m)
228 {
229  ParameterList pl;
230  for (unsigned int n = 0; n < modelsContainer_.size(); n++)
231  {
232  modelsContainer_[n]->setFreq(m);
234  }
236 }
237 
239 {
241 
242  size_t i, nbmod = modelsContainer_.size();
243  double sP = 0;
244  for (const auto& rate:vRates_)
245  {
246  sP += rate;
247  }
248 
249  for (i = 0; i < nbmod - 1; i++)
250  {
251  setParameterValue("relrate" + TextTools::toString(i + 1), vRates_[i] / sP);
252  sP -= vRates_[i];
253  }
254 }
255 
257 {
258  size_t i;
259  for (i = 0; i < getNumberOfModels(); i++)
260  {
261  if (getNModel(i)->getName() == desc)
262  break;
263  }
264  if (i == getNumberOfModels())
265  throw Exception("MixtureOfTransitionModels::getSubmodelNumbers model description do not match " + desc);
266 
267  Vuint submodnb(1, uint(i));
268 
269  return submodnb;
270 }
Partial implementation for Mixed Transition models, defined as a mixture of "simple" substitution mod...
const TransitionModelInterface & nModel(size_t i) const override
Returns a specific model from the mixture.
std::shared_ptr< const TransitionModelInterface > getNModel(size_t i) const override
std::vector< double > vProbas_
vector of the probabilities of the models
virtual size_t getNumberOfModels() const override
returns the number of models in the mixture
virtual void setVRates(const Vdouble &vd) override
Sets the rates of the submodels to be proportional to a given vector, with the constraint that the me...
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 addParameters_(const ParameterList &parameters)
void addParameter_(Parameter *parameter)
void setParameterValue(const std::string &name, double value) override
bool matchParametersValues(const ParameterList &parameters) override
std::string getNamespace() 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.
double rate_
The rate of the model (default: 1). The generator (and all its vectorial components) is independent o...
size_t getNumberOfStates() const override
Get the number of states.
Transition models defined as a mixture of several substitution models.
virtual void setVRates(const Vdouble &vd) override
Sets the rates of the submodels to follow the constraint that the mean rate of the mixture equals rat...
void updateMatrices_() override
Diagonalize the matrix, and fill the eigenValues_, iEigenValues_, leftEigenVectors_ and rightEigenVe...
MixtureOfTransitionModels(std::shared_ptr< const Alphabet > alpha, std::vector< std::unique_ptr< TransitionModelInterface >> &vpModel)
Constructor of a MixtureOfTransitionModels, where all the models have rate 1 and equal probability.
MixtureOfTransitionModels & operator=(const MixtureOfTransitionModels &)
std::string getName() const override
Get the name of the model.
void setFreq(std::map< int, double > &) override
applies setFreq to all the models of the mixture and recovers the parameters values.
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...
const TransitionModelInterface & model(const std::string &name) const override
retrieve a pointer to the submodel with the given name.
static double SMALL()
virtual void addParameters(const ParameterList &params)
static const std::shared_ptr< IntervalConstraint > PROP_CONSTRAINT_EX
Interface for all transition models.
std::string toString(T t)
Defines the basic types of data flow nodes.
std::vector< double > Vdouble
std::vector< unsigned int > Vuint