// determine the next event func (w *WFPopulation) nextEvent() (eventType int, eventTime float64) { k := float64(len(w.history.CurrentPool)) p := 2.0 * w.TransferRate * float64(w.Size) l := (k*p + k*(k-1.0)) / 2.0 v := randist.ExponentialRandomFloat64(w.rng, 1.0/l) eventTime = v r := randist.UniformRandomFloat64(w.rng) if r < p/(k-1.0+p) { eventType = TransferEvent } else { eventType = CoalescenceEvent } return }
// evolutionary operators: mutation and transfer func (pop *SeqPop) manipulate() { // calculate the number of events, which is poisson distribution lambda := float64(pop.Size) * float64(pop.Length) * (pop.Mutation + pop.Transfer) if pop.ExpTime { t := randist.ExponentialRandomFloat64(pop.rng, 1.0) lambda = t * lambda } k := randist.PoissonRandomInt(pop.rng, lambda) // given k, the number of mutations or transfers are following Binormial distribution. // therefore, we can do k times of Bernoulli test for i := 0; i < k; i++ { // determine whether this event is a mutation or transfer ratio := pop.Mutation / (pop.Mutation + pop.Transfer) // the ratio of mutation r := randist.UniformRandomFloat64(pop.rng) // randomly produce a probability if r <= ratio { // determin whether is a mutation or transfer pop.mutate() } else { pop.transfer() } } }