bpp-phyl3 3.0.0
MutationProcess.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: The Bio++ Development Group
2//
3// SPDX-License-Identifier: CECILL-2.1
4
7
8#include "MutationProcess.h"
9
10using namespace bpp;
11using namespace std;
12
13/******************************************************************************/
14
15size_t AbstractMutationProcess::mutate(size_t state) const
16{
18 for (size_t j = 0; j < size_; j++)
19 {
20 if (alea < repartition_[state][j])
21 return j;
22 }
23 throw Exception("AbstractMutationProcess::mutate. Repartition function is incomplete for state " + TextTools::toString(state));
24}
25
26/******************************************************************************/
27
28size_t AbstractMutationProcess::mutate(size_t state, unsigned int n) const
29{
30 size_t s = state;
31 for (unsigned int k = 0; k < n; k++)
32 {
34 for (size_t j = 1; j < size_ + 1; j++)
35 {
36 if (alea < repartition_[s][j])
37 {
38 s = j;
39 break;
40 }
41 }
42 }
43 return s;
44}
45
46/******************************************************************************/
47
49{
50 return RandomTools::randExponential(-model_->Qij(state, state));
51}
52
53/******************************************************************************/
54
55size_t AbstractMutationProcess::evolve(size_t initialState, double time) const
56{
57 double t = 0;
58 size_t currentState = initialState;
59 t += getTimeBeforeNextMutationEvent(currentState);
60 while (t < time)
61 {
62 currentState = mutate(currentState);
63 t += getTimeBeforeNextMutationEvent(currentState);
64 }
65 return currentState;
66}
67
68/******************************************************************************/
69
70MutationPath AbstractMutationProcess::detailedEvolve(size_t initialState, double time) const
71{
72 MutationPath mp(model_->getAlphabet(), initialState, time);
73 double t = 0;
74 size_t currentState = initialState;
75
76 t += getTimeBeforeNextMutationEvent(currentState);
77 while (t < time)
78 {
79 currentState = mutate(currentState);
80 mp.addEvent(currentState, t);
81 t += getTimeBeforeNextMutationEvent(currentState);
82 }
83
84 return mp;
85}
86
87/******************************************************************************/
88
89MutationPath AbstractMutationProcess::detailedEvolve(size_t initialState, size_t finalState, double time) const
90{
91 size_t maxIterNum = 1000; // max nb of tries
92 MutationPath mp(model_->getAlphabet(), initialState, time);
93
94 for (size_t i = 0; i < maxIterNum; ++i)
95 {
96 mp.clear();
97
98 double t = 0;
99
100 // if the father's state is not the same as the son's state -> use the correction corresponding to equation (11) in the paper
101 if (initialState != finalState)
102 { // sample timeTillChange conditional on it being smaller than time
104 double waitingTimeParam = model_->Qij(initialState, initialState); // get the parameter for the exponential distribution to draw the waiting time
105 double tmp = u * (1.0 - exp(time * waitingTimeParam));
106 t = log(1.0 - tmp) / waitingTimeParam;
107 }
108 else
109 {
110 t = getTimeBeforeNextMutationEvent(initialState); // draw the time until a transition from exponential distribution with the rate of leaving fatherState
111 }
112
113 size_t currentState = initialState;
114 while (t < time) // a jump occurred but not passed the whole time
115 {
116 currentState = mutate(currentState);
117 mp.addEvent(currentState, t); // add the current state and time to branch history
118 t += getTimeBeforeNextMutationEvent(currentState); // draw the time until a transition from exponential distribution with the rate of leaving currentState from initial state curState based on the relative transition rates distribution
119 }
120 // // the last jump passed the length of the branch -> finish the simulation and check if it's successful (i.e, mapping is finished at the son's state)
121 if (currentState != finalState) // if the simulation failed, try again
122 {
123 continue;
124 }
125 else
126 return mp;
127 }
128
129 // Emergency case when none simul reached finalState
130 mp.addEvent(finalState, time);
131 return mp;
132}
133
134
135/******************************************************************************/
136
138 shared_ptr<const SubstitutionModelInterface> model) :
140{
141 size_ = model->getNumberOfStates();
143 // Each element contains the probabilities concerning each character in the alphabet.
144
145 // We will now initiate each of these probability vector.
146 RowMatrix<double> Q = model->generator();
147 for (size_t i = 0; i < size_; i++)
148 {
149 repartition_[i] = Vdouble(size_, 0);
150 if (abs(Q(i, i)) > NumConstants::TINY())
151 {
152 double cum = 0;
153 double sum_Q = 0;
154 for (size_t j = 0; j < size_; j++)
155 {
156 if (j != i)
157 sum_Q += Q(i, j);
158 }
159
160 for (size_t j = 0; j < size_; j++)
161 {
162 if (j != i)
163 {
164 cum += model->Qij(i, j) / sum_Q;
165 repartition_[i][j] = cum;
166 }
167 else
168 repartition_[i][j] = -1;
169 // Forbidden value: does not correspond to a change.
170 }
171 }
172 }
173
174 // Note that I use cumulative probabilities in repartition_ (hence the name).
175 // These cumulative probabilities are useful for the 'mutate(...)' function.
176}
177
179
180/******************************************************************************/
181
182size_t SimpleMutationProcess::evolve(size_t initialState, double time) const
183{
184 // Compute all cumulative pijt:
185 Vdouble pijt(size_);
186 pijt[0] = model_->Pij_t(initialState, 0, time);
187 for (size_t i = 1; i < size_; i++)
188 {
189 pijt[i] = pijt[i - 1] + model_->Pij_t(initialState, i, time);
190 }
192 for (size_t i = 0; i < size_; i++)
193 {
194 if (rand < pijt[i])
195 return i;
196 }
197 throw Exception("SimpleSimulationProcess::evolve(intialState, time): error all pijt do not sum to one (total sum = " + TextTools::toString(pijt[size_ - 1]) + ").");
198}
199
200/******************************************************************************/
201
204{
205 size_ = alphabetSize;
207 // Each element contains the probabilities concerning each character in the alphabet.
208
209 // We will now initiate each of these probability vector.
210 for (size_t i = 0; i < size_; i++)
211 {
213 for (size_t j = 0; j < size_; j++)
214 {
215 repartition_[i][j] = static_cast<double>(j + 1) / static_cast<double>(size_);
216 }
217 }
218 // Note that I use cumulative probabilities in repartition_ (hence the name).
219 // These cumulative probabilities are useful for the 'mutate(...)' function.
220}
221
223
224/******************************************************************************/
Partial implementation of the MutationProcess interface.
size_t size_
The number of states allowed for the character to mutate.
size_t evolve(size_t initialState, double time) const
Simulation a character evolution during a specified time according to the given substitution model an...
std::shared_ptr< const SubstitutionModelInterface > model_
The substitution model to use:
size_t mutate(size_t state) const
Mutate a character in state i.
VVdouble repartition_
The repartition function for states probabilities.
double getTimeBeforeNextMutationEvent(size_t state) const
Get the time before next mutation event.
MutationPath detailedEvolve(size_t initialState, double time) const
Simulation a character evolution during a specified time according to the given substitution model an...
This class is used by MutationProcess to store detailed results of simulations.
void addEvent(size_t state, double time)
Add a new mutation event.
static double TINY()
static double giveRandomNumberBetweenZeroAndEntry(double entry)
static double randExponential(double mean)
SelfMutationProcess(size_t alphabetSize)
size_t evolve(size_t initialState, double time) const
Method redefinition for better performance.
SimpleMutationProcess(std::shared_ptr< const SubstitutionModelInterface > model)
Build a new SimpleMutationProcess object.
std::string toString(T t)
Defines the basic types of data flow nodes.
double log(const ExtendedFloat &ef)
std::vector< double > Vdouble
ExtendedFloat exp(const ExtendedFloat &ef)
std::vector< Vdouble > VVdouble
ExtendedFloat abs(const ExtendedFloat &ef)