Simulating Mating Alliances as a Reproductive Tactic for Populations
 All Classes Functions Variables Friends
population.h
1 #ifndef DEF_POPULATION_H
2 #define DEF_POPULATION_H
3 #include <iterator>
4 #include <algorithm>
5 #include "humandna.h"
6 #include "demographic_function.h"
7 #include "boost/utility/enable_if.hpp"
8  #include "boost/type_traits/is_base_of.hpp"
9 
10 /* Population is a class that contains 2 array of human: female and male
11 // humans can be of type human, humanmt, humandna -> we use template on those type
12 this population evolve through non overlapping generation with cycles of Mutation - Reproduction*/
13 template <class T>
14 class Population // <> indicates a template specification defintion in the .cpp file
15 {
16  private:
17  std::ostream& print(std::ostream&)const;
18  void random_shuffle_pop(); // handwritten shuffling of indiv of current generation: fast handy and efficient
20  void initiate_pop(int N);
22  void initiate_pop(int N,int mt,int xL, int xS,int y,int aL,int aS);
24  void reinitiate_ID_table();
25  std::vector<int> femaleIDtable;
26  std::vector<int> maleIDtable;
27  int nbHuman;
28  int nbFemale;
29  int generation;
30  int nbCrumbMt;
31  int nbCrumbA;
32  int nbCrumbY;
33  int nbCrumbX;
34  int nbCrumbNuc;
35  int nbCellPerA;
36  int nbCellPerX;
37  int nbChromosomesA;
38  int nbChromosomesX;
39  int sizeMt;
40  int sizeY;
41  int sizePerX;
42  int sizePerA;
43  double popsizeDemo;
44  T tmpmale; // handy and fast
45  T tmpfemale; // handy and fast
46  double muMt1;
48  double muMt2;
50  double muX1;
52  double muX2;
54  double muY1;
56  double muY2;
58  double muA1; // Transition A<->G C<->T i.e. change on 1 bit
60  double muA2; // Transversion A<->C A<->T G<->C G<->T i.e. change on 2 bits
62  std::vector<double> growthFactor; // exponential growth factor
64  int matingSystem;
65  // 1 : completely random, monogamy
66  // 2 : polygamy, still poisson law with mean nb of child ~2 for the nb of child per women
67  // 3 : polygyny, males can mate several female (without restriction), but female mate only one male
68  // 4 : polyandry -> high variance in the nb of children / women
69  // 5 : true random matig -> no more poisson in the nb of children
70  int inbreeding; // 1 : no inbreeding between brothers and sisters
71 
72  public:
73  // *** Public attributes ***
74  std::vector<T> female[2];
75  std::vector<T> male[2];
76  // *** Constructor / destructor ***
77  Population() // dull
78  { initiate_pop(0);}
79  explicit Population(int N,int mt,int xL, int xS,int y,int aL,int aS)
80  {
81  initiate_pop(N,mt,xL,xS,y,aL,aS);
82  } // assume mu=0
84  {
85  initiate_pop(a.nbHuman,a.sizeMt,a.nbChromosomesX,a.sizePerX,a.sizeY,a.nbChromosomesA/2,a.sizePerA);
86  generation = a.generation;
87  nbFemale = a.nbFemale;
88  popsizeDemo = a.popsizeDemo;
89  matingSystem = a.matingSystem;
90  inbreeding = a.inbreeding;
91  muA1 = a.muA1;
92  muA2 = a.muA2;
93  muX1 = a.muX1;
94  muX2 = a.muX2;
95  muY1 = a.muY1;
96  muY2 = a.muY2;
97  muMt1 = a.muMt1;
98  muMt2 = a.muMt2;
99  female[0] = a.female[0];
100  male[0] = a.male[0];
101  female[1] = a.female[1];
102  male[1] = a.male[1];
103  femaleIDtable = a.femaleIDtable;
104  maleIDtable = a.maleIDtable;
105  growthFactor = a.growthFactor;
106  }
107  explicit Population(std::string const& filename); // <>
109  };
111  // *** std get/set ***
112  std::vector<T> get_pop(int current) const;
114  friend std::ostream& operator << (std::ostream& os, Population const&a)
115  {
116  a.print(os);
117  return os;
118  }
119  void reset(int N);
120  void set_mating_system(int);
121  int get_matingSystem() const;
122  void set_inbreeding(int);
123  int get_inbreeding() const;
124  void set_mu(double,double,double,double);
125  // mt x y a
126  void set_mu(double,double,double,double,double,double,double,double);
127  void set_growthFactor(double,double,double);
128  void set_growthFactor(std::vector<double>);
129  void resize(int);
130  double get_muMt1() const;
131  double get_muMt2() const;
132  double get_muA1() const;
133  double get_muA2() const;
134  double get_muX1() const;
135  double get_muX2() const;
136  double get_muY1() const;
137  double get_muY2() const;
138  int get_generation() const;
139  int get_nbHuman() const;
140  int get_nbFemale() const;
141  int get_nbMale() const;
142  double get_popsizeDemo() const;
143  int get_sizeMt() const;
144  int get_sizeY() const;
145  int get_sizePerX() const;
146  int get_sizePerA() const;
147  int get_crumbA() const;
148  int get_crumbY() const;
149  int get_crumbX() const;
150  int get_crumbMt() const;
151  int get_nbCellPerA() const;
152  int get_nbCellPerX() const;
153  int get_nbChromosomesA() const;
154  int get_nbChromosomesX() const;
155  std::vector<double> get_growthFactor() const;
156  std::vector<int> get_nb_mates();
157  std::vector<int> get_nb_children();
158  // *** Sub sample ***
159  Population subsample(int sampleSize, int nbWomen);
160  Population subsample_female(); // fast and easy, if want to subsample a # of women use subsample(#,#)
161  Population subsample_male(); // idem subsample(#,0)
162  void analyse(); // TODO
163  // *** Evolution functions ***
164  void evolve(int gen);
165  void evolve_gene(int gen,std::string filename);
166  // *** Outputs ***
167  void write_txt_pop(std::string const&) const;
168  void output_pop_size() const;
169  void write_nexus(std::string const& file_name) const; // <>
170  void write_fasta(std::string const& file_name) const; // <>
171  void output_genealogy(std::ofstream & fs); // for the current generation output id of mother and father in a file, format : generation \t mother \t father \n one line per indiv
172  // private:
173  void write_smartFormat(std::string const& filename) const; // <>
174  void output_diversity();
175  void output_arlequin(std::string const& filename);
176  void output_nb_child();
177  void output_nb_mates();
178  void test(int); // dummy but <> can test on humanmt ror humanddna some stuff
179  // *** Evolution functions ***
180  int burnin(int gen,double facMu); // <> // output the number of gen run under the burnin
181  int burnin(double diversityTreshold,int gen,double facMu); // <> // output the number of gen run under the burnin
182  void evolve_one();
183  typeDNA polySites(int nuclear) const; // <>
184  typeDNA polySites_mtdna() const; // <>
185  double pairwise_distance_mtdna() const; // <>
186  double diversity_A() const; // <>
187  double diversity_Y() const; // <>
188  double diversity_X() const; // <>
189  double diversity_mtdna() const; // <>
190 
191  private:
192  void mutation();
193  void reproduction();
194  void birth_boy(int indexfemale,int indexmale,int nbBabyMale); // <>
195  void birth_girl(int indexfemale,int indexmale,int nbBabyFemale); // <>
196  void selection();
197  // *** Diversity estimators ***
198 };
199 
200 template <class T>
202 {
203  int k = 0;
204  for (std::vector<int>::iterator it = femaleIDtable.begin(); it != femaleIDtable.end(); ++it)
205  {
206  *it=k;
207  k++;
208  }
209  k=nbFemale;
210  for (std::vector<int>::iterator it = maleIDtable.begin(); it != maleIDtable.end(); ++it)
211  {
212  *it=k;
213  k++;
214  }
215 }
216 
217 template <class T>
219 {
220  matingSystem = a;
221 }
222 
223 template <class T>
225 {
226  return matingSystem;
227 }
228 
229 template <class T>
231 {
232  inbreeding = a;
233 }
234 
235 template <class T>
237 {
238  return inbreeding;
239 }
240 
241 template <class T>
242 void Population<T>::set_mu(double a, double b, double c,double d)
243 {
244  muMt1 = a;
245  muMt2 = a;
246  muX1 = b;
247  muX2 = b;
248  muY1 = c;
249  muY2 = c;
250  muA1 = d;
251  muA2 = d;
252 }
253 
254 template <class T>
255 void Population<T>::set_mu(double a, double b, double c,double d,double e, double f, double g,double h)
256 {
257  muMt1 = a;
258  muMt2 = b;
259  muX1 = c;
260  muX2 = d;
261  muY1 = e;
262  muY2 = f;
263  muA1 = g;
264  muA2 = h;
265 }
266 
267 template <class T>
268 void Population<T>::set_growthFactor(double a,double b,double c)
269 {
270  growthFactor[0] = a;
271  growthFactor[1] = b;
272  growthFactor[2] = c;
273 }
274 
275 template <class T>
276 void Population<T>::set_growthFactor(std::vector<double> a)
277 {
278  growthFactor = a;
279 }
280 
281 template <class T>
283 {
284  return muA1;
285 }
286 
287 template <class T>
289 {
290  return muA2;
291 }
292 
293 template <class T>
295 {
296  return muX1;
297 }
298 
299 template <class T>
301 {
302  return muX2;
303 }
304 
305 template <class T>
307 {
308  return muY1;
309 }
310 
311 template <class T>
313 {
314  return muY2;
315 }
316 
317 template <class T>
319 {
320  return muMt1;
321 }
322 
323 template <class T>
325 {
326  return muMt2;
327 }
328 
329 
330 template <class T>
332 {
333  return generation;
334 }
335 
336 template <class T>
338 {
339  return nbHuman;
340 }
341 
342 template <class T>
344 {
345  return nbFemale;
346 }
347 
348 template <class T>
350 {
351  return nbHuman-nbFemale;
352 }
353 
354 template <class T>
356 {
357  return popsizeDemo;
358 }
359 
360 template <class T>
361 int Population<T>::get_crumbMt() const
362 {
363  return nbCrumbMt;
364 }
365 
366 template <class T>
367 int Population<T>::get_crumbA() const
368 {
369  return nbCrumbA;
370 }
371 
372 template <class T>
373 int Population<T>::get_crumbY() const
374 {
375  return nbCrumbY;
376 }
377 
378 template <class T>
379 int Population<T>::get_crumbX() const
380 {
381  return nbCrumbX;
382 }
383 
384 template <class T>
386 {
387  return nbCellPerX;
388 }
389 
390 template <class T>
392 {
393  return nbCellPerA;
394 }
395 
396 template <class T>
398 {
399  return nbChromosomesA;
400 }
401 
402 template <class T>
404 {
405  return nbChromosomesX;
406 }
407 
408 template <class T>
410 {
411  return sizeMt;
412 }
413 
414 template <class T>
415 int Population<T>::get_sizePerA() const
416 {
417  return sizePerA;
418 }
419 
420 template <class T>
421 int Population<T>::get_sizePerX() const
422 {
423  return sizePerX;
424 }
425 
426 template <class T>
427 int Population<T>::get_sizeY() const
428 {
429  return sizeY;
430 }
431 
432 template <class T>
433 std::vector<int> Population<T>::get_nb_mates()
434 {
435  int parentG = !(generation&1);
436  std::vector<int> mates(nbHuman);
437  for(int i=0; i<nbFemale; ++i)
438  mates[i] = female[parentG][i].getNbMate(); // careful we have to look at the parent generation
439  for(int i=0; i<(nbHuman-nbFemale); ++i)
440  mates[i+nbFemale] = male[parentG][i].getNbMate();
441  return mates;
442 }
443 
444 template <class T>
446 {
447  int parentG = (generation&1)^1;
448  std::vector<int> children(nbHuman);
449  for(int i=0; i<nbFemale; ++i)
450  children[i] = female[parentG][i].getNbChild(); // careful we have to look at the parent generation
451  for(int i=0; i<(nbHuman-nbFemale); ++i)
452  children[i+nbFemale] = male[parentG][i].getNbChild();
453  return children;
454 }
455 
456 template<class T>
457 std::vector<double> Population<T>::get_growthFactor() const
458 {
459  return growthFactor;
460 }
461 
462 template <class T>
463 Population<T> Population<T>::subsample(int sampleSize, int nbWomen)
464 {
465  // Subsample the Population for analysis
466  // Create a new object of he class Population
467  int currentG = generation&1;
468  if(sampleSize>nbHuman)
469  {
470  std::cerr << "ERROR : attempt to subsample more individuals than the Population size\n";
471  sampleSize = nbHuman;
472  }
473  if(nbWomen>nbFemale)
474  {
475  std::cerr << "ERROR : attempt to subsample more female than the Population size "<< nbWomen<< " versus" << nbFemale<< "\n";
476  nbWomen = nbFemale;
477  }
478  Population sample(sampleSize,sizeMt,nbChromosomesX,sizePerX,sizeY,nbChromosomesA,sizePerA);
479  // NB : the Population sample will start at generation 0 -> must initiate at 0 and not currentG
480  random_shuffle_pop();
481  sample.nbFemale=nbWomen;
482  sample.matingSystem=matingSystem;
483  for(int i(0);i<nbWomen;++i)
484  {
485  sample.female[0][i].reborn(female[currentG][i]);
486  }
487  for(int i(0);i<sampleSize-nbWomen;++i)
488  {
489  sample.male[0][i].reborn(male[currentG][i]);
490  }
491  return sample;
492 }
493 
494  template <class T>
496 {
497  // Subsample the Population for analysis
498  // Create a new object of he class Population
499  int currentG = generation&1;
500  Population sample(2*nbFemale,sizeMt,nbChromosomesX,sizePerX,sizeY,nbChromosomesA,sizePerA); // Default attribute for parameters - 2times female because we need female tab big enough
501  sample.nbHuman = nbFemale; // then restore population size equals to female -> 'kill' the men
502  for(int i(0);i<nbFemale;++i)
503  {
504  sample.female[0][i].reborn(female[currentG][i]);
505  // To not resample twice the same individual we swap the sampled ones and check somewhere else
506  }
507  return sample;
508 }
509 
510 template <class T>
512 {
513  int currentG = generation&1;
514  int nbMale = nbHuman-nbFemale;
515  Population sample(2*nbMale,sizeMt,nbChromosomesX,sizePerX,sizeY,nbChromosomesA,sizePerA); // Default attribute for parameters -2times male because we need male tab big enough
516  sample.nbHuman = nbMale; // then we 'kill' the female
517  sample.nbFemale = 0;
518  for(int i(0);i<(nbHuman-nbFemale);++i)
519  {
520  sample.male[0][i].reborn(male[currentG][i]);
521  // To not resample twice the same individual we swap the sampled ones and check somewhere else
522  }
523  return sample;
524 }
525 
526 
527 template <class T>
529 {
530  for(int i(0);i<gen;++i){
531  if(nbHuman>0)
532  evolve_one();
533  }
534  if(nbHuman==0)
535  std::cout << "Population is extinct" << std::endl;
536 }
537 
538 template <class T>
539 void Population<T>::evolve_gene(int gen,std::string filename)
540 {
541  std::ofstream fs;
542  fs.open(filename.c_str(),std::ios::trunc);
543  for(int i(0);i<gen;++i){
544  evolve_one();
545  output_genealogy(fs);
546  }
547  fs.close();
548 }
549 
550 template <class T>
552 {
553  random_shuffle_pop();
554  mutation();
555  selection();
556  reproduction();
557  ++generation;
558 }
559 
560 
561 template <class T>
563 {
564  int currentG = (generation&1);
565  int nbMating(0),nbBabyToMake(floor(popsizeDemo));
566  int randomNbChildren,nbBabyFemale(0),nbBabyMale(0);
567  int indexmale(-1),indexfemale(-1);// force the segfault if not initialized
568  int randomIndivSwap(0),testloop(0);
569  bool sexChild;
570  if((nbFemale>0)&&(nbHuman-nbFemale>0))
571  { // if not no mating necessary population go to extinction
572  switch(matingSystem)
573  {
574  case 1: // random monogamy
575  {
576  if(nbFemale>nbHuman/2){
577  nbMating = nbHuman-nbFemale; }
578  else{
579  nbMating = nbFemale;}
580  for(int i(0);i<nbMating;++i)
581  {
582  indexmale = i;
583  indexfemale = i;
584  if(inbreeding==1)
585  if(generation!=0){
586  testloop = 0;
587  while((female[currentG][indexfemale].shared_parents2(male[currentG][indexmale])) && (testloop<100))
588  // WARNING : to prevent infinite loop -> test loop
589  {
590  randomIndivSwap = myrand(nbHuman-nbFemale-i);
591  tmpmale.reborn(male[currentG][randomIndivSwap + i]);
592  male[currentG][randomIndivSwap + i].reborn(male[currentG][indexmale]);
593  male[currentG][indexmale].reborn(tmpmale);
594  ++testloop;
595  }}
596  randomNbChildren = rBinom(nbBabyToMake,1/(double)(nbMating-i));
597  if(TRACK_MATE_AND_CHILDREN)
598  {
599  female[currentG][indexfemale].newMate();
600  male[currentG][indexmale].newMate();
601  female[currentG][indexfemale].hadChild(randomNbChildren);
602  male[currentG][indexmale].hadChild(randomNbChildren);
603  }
604  for(int j(0);j<randomNbChildren;++j)
605  {
606  sexChild = rand2;
607  if(sexChild == true)
608  {
609  birth_girl(indexfemale,indexmale,nbBabyFemale);
610  ++nbBabyFemale;
611  }
612  else
613  {
614  birth_boy(indexfemale,indexmale,nbBabyMale);
615  ++nbBabyMale;
616  }
617  --nbBabyToMake;
618  }
619  }
620  break;
621  }
622  case 2: // polygamy
623  {
624  nbMating = nbFemale;
625  for(int i(0);i<nbMating;++i) // first suppose we have as many male as female, not any more
626  // if male and female have been well sorted (or randomly shuffled) gives us the proper way ...
627  {
628  indexfemale = i;
629  randomNbChildren = rBinom(nbBabyToMake,1/(double)(nbMating-i));
630  if(TRACK_MATE_AND_CHILDREN)
631  {
632  female[currentG][indexfemale].hadChild(randomNbChildren);
633  }
634  for(int j(0);j<randomNbChildren;++j)
635  {
636  {
637  indexmale = myrand(nbHuman-nbFemale);
638  if(inbreeding==1)
639  if(generation!=0){
640  testloop = 0;
641  while((female[currentG][indexfemale].shared_parents2(male[currentG][indexmale])) && (testloop<100))
642  {
643  randomIndivSwap = myrand(nbHuman-nbFemale);
644  tmpmale.reborn(male[currentG][randomIndivSwap + i]);
645  male[currentG][randomIndivSwap + i].reborn(male[currentG][indexmale]);
646  male[currentG][indexmale].reborn(tmpmale);
647  ++testloop;
648  }}
649  if(TRACK_MATE_AND_CHILDREN)
650  {
651  female[currentG][indexfemale].newMate();
652  male[currentG][indexmale].newMate();
653  male[currentG][indexmale].hadChild(1);
654  }
655  if(indexmale == nbHuman-nbFemale)
656  {
657  std::cerr << "RANDOM FAILURE" << std::endl;
658  exit(2);
659  }
660  sexChild = rand2;
661  if(sexChild == true)
662  {
663  birth_girl(indexfemale,indexmale,nbBabyFemale);
664  ++nbBabyFemale;
665  }
666  else
667  {
668  birth_boy(indexfemale,indexmale,nbBabyMale);
669  ++nbBabyMale;
670  }
671  }
672  --nbBabyToMake;
673  }
674  }
675  break;
676  }
677  case 3: // polygyny, male polygames but not women
678  {
679  nbMating = nbFemale;
680  for(int i(0);i<nbMating;++i) // first suppose we have as many male as female, not any more
681  // if male and female have been well sorted (or randomly shuffled) gives us the proper way ...
682  {
683  indexfemale = i;
684  randomNbChildren = rBinom(nbBabyToMake,1/(double)(nbMating-i));
685  if(TRACK_MATE_AND_CHILDREN)
686  {
687  female[currentG][indexfemale].newMate();
688  female[currentG][indexfemale].hadChild(randomNbChildren);
689  }
690  for(int j(0);j<randomNbChildren;++j)
691  {
692  indexmale = myrand(nbHuman-nbFemale);
693  if(inbreeding==1)
694  if(generation!=0){
695  testloop = 0;
696  while((female[currentG][indexfemale].shared_parents2(male[currentG][indexmale])) && (testloop<100))
697  {
698  randomIndivSwap = myrand(nbHuman-nbFemale-i);
699  tmpmale.reborn(male[currentG][randomIndivSwap + i]);
700  male[currentG][randomIndivSwap + i].reborn(male[currentG][indexmale]);
701  male[currentG][indexmale].reborn(tmpmale);
702  ++testloop;
703  }}
704  if(TRACK_MATE_AND_CHILDREN)
705  {
706  male[currentG][indexmale].newMate();
707  male[currentG][indexmale].hadChild(1);
708  }
709  sexChild = rand2;
710  if(sexChild == true)
711  {
712  birth_girl(indexfemale,indexmale,nbBabyFemale);
713  ++nbBabyFemale;
714  }
715  else
716  {
717  birth_boy(indexfemale,indexmale,nbBabyMale);
718  ++nbBabyMale;
719  }
720  --nbBabyToMake;
721  }
722  }
723  break;
724  }
725  case 4: // polyandry, female polygames but not men
726  {
727  nbMating = nbHuman - nbFemale;
728  for(int i(0);i<nbMating;++i)
729  {
730  indexmale = i;
731  randomNbChildren = rBinom(nbBabyToMake,1/(double)(nbHuman-nbFemale));
732  if(TRACK_MATE_AND_CHILDREN)
733  {
734  male[currentG][indexmale].newMate();
735  male[currentG][indexmale].hadChild(randomNbChildren);
736  }
737  for(int j(0);j<randomNbChildren;++j)
738  {
739  indexfemale = myrand(nbFemale);
740  if(inbreeding==1)
741  if(generation!=0){
742  testloop = 0;
743  while((female[currentG][indexfemale].shared_parents2(male[currentG][indexmale])) && (testloop<100))
744  {
745  randomIndivSwap = myrand(nbFemale);
746  tmpfemale.reborn(female[currentG][randomIndivSwap + i]);
747  female[currentG][randomIndivSwap + i].reborn(female[currentG][indexfemale]);
748  female[currentG][indexfemale].reborn(tmpfemale);
749  ++testloop;
750  }}
751  if(TRACK_MATE_AND_CHILDREN)
752  {
753 
754  female[currentG][indexfemale].newMate();
755  female[currentG][indexfemale].hadChild(1);
756  }
757  sexChild = rand2;
758  if(sexChild == true)
759  {
760  birth_girl(indexfemale,indexmale,nbBabyFemale);
761  ++nbBabyFemale;
762  }
763  else
764  {
765  birth_boy(indexfemale,indexmale,nbBabyMale);
766  ++nbBabyMale;
767  }
768  --nbBabyToMake;
769  }
770  }
771  break;
772  }
773  case 5: // random mating
774  {
775  nbMating = std::floor(popsizeDemo);
776  for(int i(0);i<nbMating;++i)
777  { // 1 baby at a time, as many as nneded to fill up to popsizeDemo
778  indexfemale = myrand(nbFemale);
779  indexmale = myrand(nbHuman-nbFemale);
780  if(TRACK_MATE_AND_CHILDREN)
781  {
782  female[currentG][indexfemale].hadChild(1);
783  male[currentG][indexmale].hadChild(1);
784  female[currentG][indexfemale].newMate();
785  male[currentG][indexmale].newMate();
786  }
787  if(indexmale == nbHuman-nbFemale)
788  {
789  std::cerr << "ERROR in the creation of the new generation" << std::endl;
790  exit(2);
791  }
792  sexChild = rand2;
793  if(sexChild == true)
794  {
795  birth_girl(indexfemale,indexmale,nbBabyFemale);
796  ++nbBabyFemale;
797  }
798  else
799  {
800  birth_boy(indexfemale,indexmale,nbBabyMale);
801  ++nbBabyMale;
802  }
803  --nbBabyToMake;
804  }
805  break;
806  }
807  default:
808  {
809  std::cout << "Non existing mating system !" << std::endl;
810  exit(2);
811  }
812  }
813  nbFemale = nbBabyFemale;
814  nbHuman = nbBabyMale+nbBabyFemale;
815  }
816  else
817  { // exctinction
818  nbFemale = 0;
819  nbHuman = 0;
820  }
821  if(nbHuman > popsizeDemo)
822  {
823  std::cerr << "ERROR : reproduction scheme is not working, too many baby were created" << std::endl;
824  exit(2);
825  }
826  reinitiate_ID_table();
827 }
828 
829 template <class T>
830 void Population<T>::selection() // in this step we just kill people to follow our demographic function - shoudl not append but safeguard
831 {
832  if(nbHuman>popsizeDemo)
833  {
834  std::cerr << "TROUBLE Nb of children not working !" << std::endl;
835  int nbDead,nbFemaleDead;
836  nbDead = nbHuman - std::floor(popsizeDemo); // nb people that we should kill to get that our pop is out growing
837  nbFemaleDead = rBinom(nbDead,(double)nbFemale/(double)nbHuman); // random distribution of the dead between female & male, can have diff probability to die
838  nbFemale -= nbFemaleDead;
839  nbHuman -= nbDead;
840  }
841  // update popsizeDemo as a function of time -> demographic model
842  popsizeDemo = demographic_function(popsizeDemo,growthFactor[0],growthFactor[1],growthFactor[2]);
843 }
844 
845 template <class T>
847 {
848  female[0] = a.female[0];
849  male[0] = a.male[0];
850  female[1] = a.female[1];
851  male[1] = a.male[1];
852  femaleIDtable = a.femaleIDtable;
853  maleIDtable = a.maleIDtable;
854  popsizeDemo = a.popsizeDemo;
855  nbHuman = a.nbHuman;
856  nbFemale = a.nbFemale;
857  generation = a.generation;
858  growthFactor = a.growthFactor;
859  matingSystem = a.matingSystem;
860  nbCrumbMt = a.nbCrumbMt;
861  nbCrumbA = a.nbCrumbA;
862  nbCrumbY = a.nbCrumbY;
863  nbCrumbNuc = a.nbCrumbNuc;
864  nbCellPerA = a.nbCellPerA;
865  nbCellPerX = a.nbCellPerX;
866  nbCrumbX = a.nbCrumbX;
867  nbChromosomesA= a.nbChromosomesA;
868  nbChromosomesX= a.nbChromosomesX;
869  sizeMt= a.sizeMt;
870  sizeY = a.sizeY;
871  sizePerA = a.sizePerA;
872  sizePerX = a.sizePerX;
873  muA1 = a.muA1;
874  muA2 = a.muA2;
875  muX1 = a.muX1;
876  muX2 = a.muX2;
877  muY1 = a.muY1;
878  muY2 = a.muY2;
879  muMt1 = a.muMt1;
880  muMt2 = a.muMt2;
881  return *this;
882 }
883 
884 
885 template <class T>
886 std::ostream& Population<T>::print(std::ostream & os) const
887 {
888  int currentG = (generation&1);
889  os << "Pop with " << nbHuman << "individuals with a sex ratio of " << nbFemale/nbHuman << std::endl;
890  for(int i(0);i<nbFemale;++i)
891  {
892  os << female[currentG][i];
893  }
894  for(int i(0);i<(nbHuman-nbFemale);++i)
895  {
896  os << male[currentG][i];
897  }
898  return os;
899 }
900 
901 
902 template <class T>
903 void Population<T>::write_txt_pop(std::string const& file_name) const
904 {
905  int currentG = (generation&1);
906  std::ofstream fs(file_name.std::string::c_str());
907  fs << "generation " << generation << " -- nb humans " << nbHuman << " -- Sex ratio " << nbFemale/nbHuman << std::endl;
908  if(nbHuman>0)
909  {
910  for(int i(0);i<nbFemale;++i)
911  {
912  fs << female[currentG][i];
913  }
914  for(int i(0);i<(nbHuman-nbFemale);++i)
915  {
916  fs << male[currentG][i];
917  }
918  fs << "---" << std::endl;
919  }
920 }
921 
922 template <class T>
924 {
925  std::cout << "generation " << generation << " -- nb humans " << nbHuman << " -- Sex ratio " << (double)nbFemale/(double)nbHuman << std::endl;
926 }
927 
928 template <class T>
929 void Population<T>::output_genealogy(std::ofstream & fs)
930 {
931  int currentG = (generation&1);
932  for(int i(0);i<nbFemale;++i)
933  {
934  fs << generation << "\t" << femaleIDtable[i] << "\t" << female[currentG][i].getMother() << "\t" << female[currentG][i].getFather() << "\n";
935  }
936  for(int i(0);i<(nbHuman-nbFemale);++i)
937  {
938  fs << generation << "\t" << maleIDtable[i] << "\t" << male[currentG][i].getMother() << "\t" << male[currentG][i].getFather() << "\n";
939  }
940 }
941 
942 template <class T>
943 void Population<T>::initiate_pop(int N)
944 {
945  nbHuman = N;
946  generation = 0;
947  nbFemale = N/2;
948  popsizeDemo = N;
949  matingSystem = 0;
950  inbreeding = 0;
951  muA1 = 0;
952  muA2 = 0;
953  muX1 = 0;
954  muX2 = 0;
955  muY1 = 0;
956  muY2 = 0;
957  muMt1 = 0;
958  muMt2 = 0;
959  nbCrumbMt = 0;
960  nbCrumbA = 0;
961  nbCrumbY = 0;
962  nbCrumbX = 0;
963  nbCrumbNuc = 0;
964  nbChromosomesX = 0;
965  nbChromosomesA = 0;
966  nbCellPerA = 0;
967  nbCellPerX = 0;
968  sizeMt = 0;
969  sizePerX = 0;
970  sizeY = 0;
971  sizePerA = 0;
972  growthFactor.resize(3);
973  growthFactor[0]=0;
974  growthFactor[1]=1; // by default popsize (t+1) = popsize (t)
975  growthFactor[2]=0;
976  femaleIDtable.resize(std::ceil(popsizeDemo));
977  maleIDtable.resize(std::ceil(popsizeDemo));
978  int k = 0;
979  for (std::vector<int>::iterator it = femaleIDtable.begin(); it != femaleIDtable.end(); ++it)
980  {
981  *it=k;
982  k++;
983  }
984  k=nbFemale;
985  for (std::vector<int>::iterator it = maleIDtable.begin(); it != maleIDtable.end(); ++it)
986  {
987  *it=k;
988  k++;
989  }
990  T tmp(nbCrumbMt,nbCrumbNuc);
991  tmpfemale = tmp;
992  T tmp2(tmp);
993  tmpmale = tmp2;
994  for(int i(0);i<popsizeDemo;++i)
995  {
996  T people(tmpfemale);
997  female[0].push_back(people);
998  T people2(tmpfemale);
999  female[1].push_back(people2);
1000  }
1001  for(int i(0);i<popsizeDemo;++i)
1002  {
1003  T people(tmpmale);
1004  male[0].push_back(people);
1005  T people2(tmpmale);
1006  male[1].push_back(people2);
1007  }
1008 }
1009 
1010 template <class T>
1011 void Population<T>::reset(int N)
1012 {
1013  nbHuman = N;
1014  generation = 0;
1015  nbFemale = N/2;
1016  popsizeDemo = N;
1017  int k = 0;
1018  for (std::vector<int>::iterator it = femaleIDtable.begin(); it != femaleIDtable.end(); ++it)
1019  {
1020  *it=k;
1021  k++;
1022  }
1023  k=nbFemale;
1024  for (std::vector<int>::iterator it = maleIDtable.begin(); it != maleIDtable.end(); ++it)
1025  {
1026  *it=k;
1027  k++;
1028  }
1029  for(int i(0);i<std::ceil(N/2.0);++i)
1030  {
1031  male[0][i].reset();
1032  }
1033  for(int i(0);i<N/2;++i)
1034  {
1035  female[0][i].reset();
1036  }
1037 }
1038 
1039 template <class T>
1040 void Population<T>::initiate_pop(int N,int mt,int xL, int xS,int y,int aL,int aS)
1041 {
1042  nbHuman = N;
1043  generation = 0;
1044  nbFemale = N/2;
1045  popsizeDemo = N;
1046  matingSystem = 0;
1047  inbreeding = 0;
1048  muA1 = 0;
1049  muA2 = 0;
1050  muX1 = 0;
1051  muX2 = 0;
1052  muY1 = 0;
1053  muY2 = 0;
1054  muMt1 = 0;
1055  muMt2 = 0;
1056  nbCrumbMt = std::ceil(mt*1.0/CRUMB);
1057  sizeMt = std::ceil(mt*1.0/CRUMB)*CRUMB;
1058  sizePerA = std::ceil(aS*1.0/CRUMB)*CRUMB; // forced to be long as a 32 bits chunks
1059  nbChromosomesA = aL * 2;
1060  nbCellPerA = sizePerA/CRUMB;
1061  nbCrumbA = nbChromosomesA * sizePerA /CRUMB;
1062  sizeY = std::ceil(y*1.0/CRUMB)*CRUMB;
1063  nbCrumbY = sizeY/CRUMB;
1064  sizePerX = std::ceil(xS*1.0/CRUMB)*CRUMB;
1065  nbCellPerX = sizePerX /CRUMB;
1066  nbChromosomesX = xL;
1067  nbCrumbX = nbChromosomesX * sizePerX /CRUMB;
1068  int nbCrumbSex = std::max(nbCrumbX,nbCrumbY);
1069  nbCrumbNuc = nbCrumbA + nbCrumbX + nbCrumbSex;
1070  growthFactor.resize(3);
1071  growthFactor[0]=0;
1072  growthFactor[1]=1; // by default popsize = popsize
1073  growthFactor[2]=0;
1074  femaleIDtable.resize(std::ceil(popsizeDemo));
1075  maleIDtable.resize(std::ceil(popsizeDemo));
1076  int k = 0;
1077  for (std::vector<int>::iterator it = femaleIDtable.begin(); it != femaleIDtable.end(); ++it)
1078  {
1079  *it=k;
1080  k++;
1081  }
1082  k=nbFemale;
1083  for (std::vector<int>::iterator it = maleIDtable.begin(); it != maleIDtable.end(); ++it)
1084  {
1085  *it=k;
1086  k++;
1087  }
1088  T tmp(nbCrumbMt,nbCrumbNuc);
1089  tmpfemale = tmp;
1090  T tmp2(tmp);
1091  tmpmale = tmp2;
1092  for(int i(0);i<popsizeDemo;++i)
1093  {
1094  T people(tmpfemale);
1095  female[0].push_back(people);
1096  T people2(tmpfemale);
1097  female[1].push_back(people2);
1098  }
1099  for(int i(0);i<popsizeDemo;++i)
1100  {
1101  T people(tmpmale);
1102  male[0].push_back(people);
1103  T people2(tmpmale);
1104  male[1].push_back(people2);
1105  }
1106 }
1107 
1108 template <class T>
1110 {
1111  int oldsize = male[0].size();
1112  for(int i(0); i<(a-oldsize); i++)
1113  {
1114  T newH0(tmpmale);
1115  male[0].push_back(newH0);
1116  T newH1(tmpmale);
1117  male[1].push_back(newH1);
1118  T newF0(tmpfemale);
1119  female[0].push_back(newF0);
1120  T newF1(tmpfemale);
1121  female[1].push_back(newF1);
1122  }
1123  femaleIDtable.resize(a);
1124  maleIDtable.resize(a);
1125 }
1126 
1127 template <class T>
1128 void Population<T>::random_shuffle_pop() // knuth fisher yates algorithm stolen on http://www.codinghorror.com/blog/2007/12/the-danger-of-naivete.html
1129 {
1130  int currentG = (generation%2);
1131  int n;
1132  int tmpIndex = -1;
1133  for (int i = nbFemale - 1; i > 0; --i)
1134  {
1135  n = myrand(i-1);
1136  tmpfemale.reborn(female[currentG][i]);
1137  female[currentG][i].reborn(female[currentG][n]);
1138  female[currentG][n].reborn(tmpfemale);
1139  tmpIndex = femaleIDtable[i];
1140  femaleIDtable[i] = femaleIDtable[n];
1141  femaleIDtable[n] = tmpIndex;
1142  }
1143  for (int i = nbHuman - nbFemale - 1; i > 0; --i)
1144  {
1145  n = myrand(i-1);
1146  tmpmale.reborn(male[currentG][i]);
1147  male[currentG][i].reborn(male[currentG][n]);
1148  male[currentG][n].reborn(tmpmale);
1149  tmpIndex = maleIDtable[i];
1150  maleIDtable[i] = maleIDtable[n];
1151  maleIDtable[n] = tmpIndex;
1152  }
1153 }
1154 
1155 template <class T>
1157 {
1158  std::cout << generation << "\t" << generation << "\t" << diversity_mtdna() << "\t"<< pairwise_distance_mtdna() << " \t " << diversity_A() << "\t" << diversity_X() << "\t" << diversity_Y() << std::endl;
1159 }
1160 
1161 template <class T>
1163 {
1164  std::vector<int> nbChildren = get_nb_children();
1165  for(int i(nbFemale);i<nbHuman-nbFemale;++i)
1166  std::cout << "\n" << nbChildren[i];
1167  std::cout<<std::endl;
1168 }
1169 
1170 template <class T>
1172 {
1173  std::vector<int> nbMate = get_nb_mates();
1174  for(int i(0);i<nbFemale;++i)
1175  std::cout<<"\n"<<nbMate[i];
1176  std::cout<<std::endl;
1177 }
1178 
1179 
1180 #endif
void write_nexus(std::string const &file_name) const
Population(Population const &a)
Definition: population.h:83
void evolve(int gen)
Definition: population.h:528
void write_smartFormat(std::string const &filename) const
std::vector< T > male[2]
Definition: population.h:75
void test(int)
Definition: population.h:14
void analyse()
Population subsample_female()
Definition: population.h:495
std::vector< int > get_nb_mates()
Definition: population.h:433
double get_muX2() const
Definition: population.h:300
double diversity_X() const
typeDNA polySites(int nuclear) const
Population(int N, int mt, int xL, int xS, int y, int aL, int aS)
Definition: population.h:79
void output_nb_mates()
Definition: population.h:1171
double get_muA2() const
Definition: population.h:288
double get_popsizeDemo() const
Definition: population.h:355
typeDNA polySites_mtdna() const
double pairwise_distance_mtdna() const
int get_matingSystem() const
Definition: population.h:224
void output_nb_child()
Definition: population.h:1162
int get_nbFemale() const
Definition: population.h:343
Population & operator=(Population const &)
Definition: population.h:846
double diversity_mtdna() const
Population subsample(int sampleSize, int nbWomen)
Definition: population.h:463
void set_mu(double, double, double, double)
Definition: population.h:242
double diversity_Y() const
void set_inbreeding(int)
Definition: population.h:230
double get_muY2() const
Definition: population.h:312
void output_diversity()
Definition: population.h:1156
int get_nbHuman() const
Definition: population.h:337
Population subsample_male()
Definition: population.h:511
void evolve_gene(int gen, std::string filename)
Definition: population.h:539
void resize(int)
Definition: population.h:1109
int get_inbreeding() const
Definition: population.h:236
~Population()
Definition: population.h:108
double get_muX1() const
Definition: population.h:294
int get_nbMale() const
Definition: population.h:349
int get_generation() const
Definition: population.h:331
void output_pop_size() const
Definition: population.h:923
void set_growthFactor(double, double, double)
Definition: population.h:268
Population()
Definition: population.h:77
std::vector< int > get_nb_children()
Definition: population.h:445
double diversity_A() const
std::vector< T > get_pop(int current) const
double get_muMt2() const
Definition: population.h:324
double get_muMt1() const
Definition: population.h:318
double get_muY1() const
Definition: population.h:306
int get_sizeMt() const
Definition: population.h:409
void output_genealogy(std::ofstream &fs)
Definition: population.h:929
std::vector< T > female[2]
Definition: population.h:74
void write_fasta(std::string const &file_name) const
void write_txt_pop(std::string const &) const
Definition: population.h:903
double get_muA1() const
Definition: population.h:282

Home