next up previous
Next: About this document ... Up: polyploids Previous: polyploids

source code

It may not be as clean since I made it in a hurry, but here is an example.

#include <stdio.h>
#include <stdlib.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>

#define NUM_REPS   50000

const gsl_rng *gBaseRand;

double gMeanOvuleNum, gStddevOvuleNum, gSelfRate, gMeanPolVisit,
  gInitFreq4x;
int gPopSize;

double NonNegNormal(double mean, double stddev);
void SetupGlobalVars(void);
unsigned int MakeNextGenSeeds (unsigned int numTargetPloidy,
			       unsigned int numOtherPloidy);
int CheckStatus(int gen, unsigned int num2x, unsigned int num4x);

int main(void) {
  int i, rc, rep, gen, randSeed, maxGen = 10000;
  unsigned int num2x, num4x, totalN;
  unsigned int seeds2x, seeds4x;
  double freq2x, dummyPara;
  int results[4] = {0};

  
  /* specifying to use Mersenne twister MT-19937 as the uniform PRNG */
  gBaseRand = gsl_rng_alloc(gsl_rng_mt19937);
  
  srand(time(NULL));                    /* initialization for rand() */
  randSeed = rand();                    /* returns a non-negative integer */
  gsl_rng_set (gBaseRand, randSeed);    /* seed the PRNG */
  
  SetupGlobalVars();
  
  /* print header */
  printf("Changing MeanPolVisit\n");
  printf("paraVal\t4xWin\t2xWin\tPopExtinct\tCoexist\n");

  for (gMeanPolVisit = 1; gMeanPolVisit < 20; gMeanPolVisit +=2) {
  /* for (gMeanOvuleNum = 1; gMeanOvuleNum < 100; gMeanOvuleNum +=10) { */
  /* for (gSelfRate = 0; gSelfRate <= 1; gSelfRate +=0.2) { */
    /* initialize the results counter */
    dummyPara = gMeanPolVisit;
    
    for(i = 0; i < 4; i++) {
      results[i] = 0;
    }
    
    for (rep = 0; rep < NUM_REPS; rep++) {
      /* beginning of a single simulation */
      num2x =  (int) (gPopSize * (1-gInitFreq4x));      
      num4x = (int) (gPopSize * gInitFreq4x);
      for (gen = 0; gen < maxGen; gen++) {
	seeds2x = MakeNextGenSeeds(num2x, num4x);
	seeds4x = MakeNextGenSeeds(num4x, num2x);
	
	if (seeds2x + seeds4x > 0) {
	  freq2x = (double) seeds2x / (seeds2x + seeds4x);
	  
	  num2x = gsl_ran_binomial(gBaseRand,  freq2x, gPopSize);
	  num4x = gPopSize - num2x;
	} else {
	  num2x = num4x = 0;
	}
	
	rc = CheckStatus(gen, num2x, num4x);
	if (rc > 0) {  /* one ploidy went extinct */
	  results[rc - 1]++;
	  break;
	}
      }
      if (gen == maxGen) { /* coexistence */
	results[3]++;
      }
    }
    printf("%lf\t%d\t%d\t%d\t%d\n", dummyPara,
	   results[0], results[1], results[2], results[3]);
  }

  gsl_rng_free(gBaseRand);
  return 0;
}

/*
 * This function returns a random deviate sampled from truncated
 * normal distribution (i.e., the value returned is non negative).
 */
double NonNegNormal(double mean, double stddev) {
  double normalDeviate  = -1.0;

  while (normalDeviate < 0) {
    normalDeviate = gsl_ran_gaussian (gBaseRand, stddev) + mean;
  }
  
  return normalDeviate;
}


/* 
 * set up following variables: gMeanOvuleNum, gStddevOvuleNum,
 * gSelfRate, gMeanPolVisit;
 */
void SetupGlobalVars(void) {
  gMeanOvuleNum = 10;
  gStddevOvuleNum = gMeanOvuleNum/2;
  gSelfRate = 0.8;
  gMeanPolVisit = 3;
  gInitFreq4x = 0.2;
  gPopSize = 20;

  /* use the following for interactive setup
  fprintf(stderr, "Population Size: ");
  scanf("%d", &gPopSize);

  fprintf(stderr, "Init freq. of tetraploids: ");
  scanf("%lf", &gInitFreq4x);

  fprintf(stderr, "Mean number of ovules: ");
  scanf("%lf", &gMeanOvuleNum);
  
  fprintf(stderr, "Std. dev. of ovule numbers: ");
  scanf("%lf", &gStddevOvuleNum);
  
  fprintf(stderr, "Selfing rate [0 - 1]: ");
  scanf("%lf", &gSelfRate);
  
  fprintf(stderr, "Mean number of pollinator visit per flower: ");
  scanf("%lf", &gMeanPolVisit);
  */

  printf ("Parameters: meanOvNum = %lf, stddevOvNum = %lf, selfRate = %lf, "
	  "meanPolVisit = %lf, initNum2x = %d, initNum4x = %d\n",
	  gMeanOvuleNum, gStddevOvuleNum, gSelfRate,
	  gMeanPolVisit,
	  (int) (gPopSize * (1-gInitFreq4x)), (int) (gPopSize * gInitFreq4x));

  return;

}

/*
 * Take the state of current population as the argument.
 *
 * Return the number of seeds of the target ploidy for the next generation.
 *
 * For example, if the 1st argument is the number of diploid individuals and
 * the 2nd argument is the number of tetraploid individuals, it goes through
 * the mating process, and returns the number of diploid seeds in the
 * next generation.  If the 2 arguments are switched (i.e. numTargetPloidy
 * is the number of tetraploid individuals), it will return the
 * number of tetraploid seeds in the next generation.
 */
unsigned int MakeNextGenSeeds (unsigned int numTargetPloidy,
			       unsigned int numOtherPloidy) {
  int i;
  unsigned int numOv, numSelfedOv, numOCOv, numPollinatorVisit, numPollen;
  unsigned int goodOCSeeds, sum = 0;
  double freqThisPloidy, freqThisPloidyInPollen;

  /* frequency of this ploidy in the adults */
  freqThisPloidy = (double) numTargetPloidy/(numTargetPloidy + numOtherPloidy);

  /* go through each individual and let it produce seeds */
  for (i = 0; i < numTargetPloidy; i++) {
    /* number of ovules which this individual produces */
    numOv = (int) NonNegNormal(gMeanOvuleNum, gStddevOvuleNum);
    
    /* some of these ovules are used for selfing */
    numSelfedOv = gsl_ran_binomial(gBaseRand, gSelfRate, numOv);
    /* remainders are available for outcrossing */
    numOCOv = numOv - numSelfedOv;
    
    /* number of pollinators visitied this flower */
    numPollinatorVisit = gsl_ran_poisson(gBaseRand, gMeanPolVisit);
    
    
    /* number of outcrossed seeds which received the correct ploidy pollen */
    if (numPollinatorVisit > 0) {
      /* Freq. of pollen with the same ploidy as the mom */
      freqThisPloidyInPollen = 
	(double) gsl_ran_binomial(gBaseRand,freqThisPloidy,numPollinatorVisit)/
	numPollinatorVisit;

      goodOCSeeds = 
	gsl_ran_binomial(gBaseRand, freqThisPloidyInPollen, numOCOv);
    } else {  /* no pollinator visit, so no outcrossed seeds */
      goodOCSeeds = 0;
    }
    
    sum += numSelfedOv + goodOCSeeds; /* tracking the total viable seeds */
  }
  
  return sum;
}

#define PRINT_INTVL 10

/* This function returns 
 *   0: 2 ploidy exists
 *   1: diploid went extinct
 *   2: tetraploid went extinct
 *   3: population went extinct
 */

int CheckStatus(int gen, unsigned int num2x, unsigned int num4x) {
  /* if (gen % PRINT_INTVL == 0) {
    printf ("%d\t%u\t%u\n", gen, num2x, num4x);
  }
  */
  if (num2x == 0 && num4x == 0){
    return 3;
  }
  if (num2x == 0) {
    return 1;
  }
  if (num4x == 0) {
    return 2;
  }
  
  return 0;
}



Naoki Takebayashi 2006-04-03