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
13using namespace bpp;
14using namespace std;
15
16
17MixtureOfATransitionModel::MixtureOfATransitionModel(
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 }
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
210void 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...
const TransitionModelInterface & model(const std::string &name) const override
retrieve a pointer to the submodel with the given name.
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...
MixtureOfATransitionModel * clone() const override
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)
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