So, my code can’t get beyond this line:
double correction = ((double) (1/(1 + pow(2, ((double) ((popsize - maxpop)/maxpop)))))) + 0.5;
popsize is an int, and maxpop is a long int, defined by the user and limited to values between 1 and 10,000 and 1 and 500,000 respectively (though I may in the future set a higher limit on maxpop, which is why it’s a long int in advance). I realize that most of those double‘s are redundant, but I wanted to remain sure. The code compiles without any warnings, but once it actually gets to running this, it hangs. I tried printing out correction directly after it was declared, but not even that ran because it was stuck on that line. Also, don’t worry, I didn’t forget to include math.h (though I did at first, and had the same problem with an additional implicit declaration error). What’s going wrong?
EDIT: Here is all my code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
long double randomDouble() {
long double r = (long double)rand()/(long double)RAND_MAX;
return r;
}
int tryBernoulli(long double p) {
if ((long double)rand()/(long double)RAND_MAX < p) {
return 1;
} else
return 0;
}
int tryRademacher() {
if (rand() % 2) {
return 1;
}
return -1;
}
int calculateSeries(int arg) {
int sum = 0;
for (int i = 0; i <= arg; i++) {
sum = sum + i;
}
return sum;
}
int main() {
long double allp [1001] [33];
long double p [33] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int allalsum [33] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int alsum [33] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int nalsum [33] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long double selection [33] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int allgenotypes [467];
for (int i = 0; i <= 465; i++) {
allgenotypes[i] = 0;
}
int genotypes [467];
for (int i = 0; i <= 465; i++) {
genotypes[i] = 0;
}
int a,b; // The two alleles generated during generation for a single organism.
int temp; // A temporary variable to store numbers in.
long double randdbl = 0; // The number that randomDouble generates.
int randint = 0; // A random integer (for safekeeping).
int alnum = 2;
int popsize = 1;
int npopsize = 0;
long int maxpop = 0;
int gens = 1;
long double fsum = 0; // For keeping track of what part of the probability distro you're in.
int isum = 0; // For keeping track of what part of the gene pool you're in.
int input = 0;
long double finput = 0;
long int linput = 0;
printf("Hello! Welcome to Mike's Glorious Evolutionary Modeler. This models the genetic drift of a single gene in a population of arbitrary size. For a sufficiently large population, you should get no drift at all! To start, specify the starting population size (from 1 to 10,000, no commas please):\n");
scanf("%d",&input);
if (input < 1 || input > 10000) {
while (input < 1 || input > 10000) {
printf("That was outside of the limits (1 to 10,000)! Try again:\n");
scanf("%d",&input);
}
}
popsize = input;
printf("\nAnd give the environmental population cap (between 1 and 500,000):\n");
scanf("%ld",&linput);
if (input < 1 || linput > 500000) {
while (input < 1 || linput > 500000) {
printf("That was outside of the limits (1 to 500,000)! Try again:\n");
scanf("%ld",&linput);
}
}
maxpop = linput;
printf("\nNext, tell me how many alleles you would like (between 2 and 32):\n");
scanf("%d", &input);
if (input < 2 || input > 32) {
while (input < 2 || input > 32) {
printf("That was outside of the limits (2 to 32)! Try again:\n");
scanf("%d",&input);
}
}
alnum = input;
printf("\nTime to specify the probabilities of all of the alleles (except the last one)! Specify each, up to four decimal places. They have to add up to 1. ");
for (int i = 1; i <= (alnum-1); i++) {
printf("Please enter the probability of Allele %d, denoted A%d (between 0 and %Lf, inclusive):\n", i, i, (1-fsum));
scanf("%Lf",&finput);
if (fsum + finput > 1) {
while (fsum + finput > 1) {
printf("That put the sum over 1! Try again:\n");
scanf("%Lf",&finput);
}
}
p[i-1] = finput;
fsum = fsum + finput;
printf("Now please enter the selection coefficient for Allele %d. If you want the population growth to remain at 0, set it to 1. In order to maintain a reasonable growth rate, this coefficient may be no more than 1.1.\n", i);
scanf("%Lf",&finput);
if (finput < 0 || finput > 1.1) {
while (finput < 0 || finput > 1.1) {
printf("Nice try. It should be between 0 and 1.1.\n");
scanf("%Lf",&finput);
}
}
selection[i-1] = finput;
}
fsum = 0;
for (int i = 1; i <= (alnum-1); i++) {
fsum = fsum + p[i-1];
}
p[alnum-1] = 1 - fsum;
printf("Okay, the probability for A%d will be %Lf. What should its selection coefficient be?\n",alnum,p[alnum-1]);
scanf("%Lf",&finput);
if (finput <= 0 || finput > 1.1) {
while (finput <= 0 || finput > 1.1) {
printf("Nice try. It should be between 0 and 1.1.\n");
scanf("%Lf",&finput);
}
}
selection[alnum-1] = finput;
printf("\nOkay! Enter the amount of generations that the calculations should be done for (between 1 and 1,000):\n");
scanf("%d",&input);
if (input < 1 || input > 1000) {
while (input < 1 || input > 1000) {
printf("That was outside of the limits (1 to 1,000)! Try again:\n");
scanf("%d",&input);
}
}
gens = input;
printf("Okay! Ready to go. Give me a moment...\n\n");
srand((unsigned int) time(NULL)); // Seed the generator. Only do this once!
for (int j = 0; j <= popsize-1; j++) { // This part generates and files the alleles and genotypes of the first generation.
randdbl = randomDouble();
fsum = 0;
for (int k = 0; k <= alnum-1; k++) {
if (randdbl > fsum && randdbl < fsum + p[k]) {
a = k+1;
break;
}
fsum = fsum + p[k];
}
randdbl = randomDouble();
fsum = 0;
for (int k = 0; k <= alnum-1; k++) {
if (randdbl > fsum && randdbl < fsum + p[k]) {
b = k+1;
break;
}
fsum = fsum + p[k];
}
if (a > b) {
temp = a;
a = b;
b = temp;
}
allalsum[a-1]++;
allalsum[b-1]++;
alsum[a-1]++;
alsum[b-1]++;
if (b == a) {
if (b == 1) {
genotypes[0]++;
} else {
genotypes[calculateSeries(b)-b]++;
allgenotypes[calculateSeries(b)-b]++;
}
} else {
genotypes[calculateSeries(b-1)+a]++;
allgenotypes[calculateSeries(b-1)+a]++;
}
}
printf("\nStatistics for Generation 1:\n Population: %d\n Number of Genotype:\n", popsize);
int index = 0;
for (int i = 0; i <= alnum-1; i++) {
printf(" A%dA%d: %d\n",(i+1),(i+1),genotypes[index]);
index++;
for (int j = 1; j <= i; j++) {
printf(" A%dA%d: %d\n",j,(i+1),genotypes[index]);
index++;
}
}
printf("\n Number of Allele:\n");
for (int i = 0; i <= alnum-1; i++) {
printf(" A%d: %d\n",(i+1),alsum[i]);
}
printf("\n Percent Allele Composition:\n");
for (int i = 0; i <= alnum-1; i++) {
allp [gens] [i] = p[i]; // Store old probability values in array
p[i] = ((long double) alsum[i])/((long double) (2*popsize)); // Generate new ones from current generation
printf(" A%d: %Lf%%\n",(i+1),(p[i]*100));
}
// Clean up:
for (int j = 0; j <= 465; j++) {
genotypes[j] = 0;
}
/********************************************************************************************************
************************************************IMPORTANT***********************************************
********************************************************************************************************/
for (int i = 2; i <= gens; i++) { // This part calculates the values for all the rest of the generations.
double correction = ((double) (1/(1 + pow(2, ((double) ((popsize - maxpop)/maxpop)))))) + 0.5; // The logistic function that curves the population growth with respect to the population cap.
for (int j = 0; j <= (alnum-1); j++) {
for (int k = 0; k <= alsum[j]; k++) {
while (tryBernoulli(((0.5+correction)*selection[j]))) {
nalsum[j]++;
}
}
}
popsize = 0;
for (int j = 0; j <= (alnum-1); j++) {
popsize = popsize+nalsum[j];
}
if ((popsize % 2) == 1) {
popsize--;
nalsum[rand()%alnum]--;
}
for (int j = 0; j <= (alnum-1); j++) {
alsum[j] = nalsum[j];
allalsum[j] = allalsum[j] + nalsum[j];
}
if (popsize == 0) {
printf("\nOops! Your population has died out!");
break;
}
npopsize = popsize/2;
while (npopsize != 0) {
isum = alsum[0];
randint = rand()%popsize;
for (int j = 0; j <= (alnum-1); j++) {
if (nalsum[j] > 0) {
if (randint <= isum) {
a = j + 1;
nalsum[j]--;
break;
}
}
isum = isum + alsum [j+1];
}
isum = alsum[0];
randint = rand()%popsize;
for (int j = 0; j <= (alnum-1); j++) {
if (nalsum[j] > 0) {
if (randint <= isum) {
b = j + 1;
nalsum[j]--;
break;
}
}
isum = isum + alsum [j+1];
}
if (b == a) {
if (b == 1) {
genotypes[0]++;
} else {
genotypes[calculateSeries(b)-b]++;
allgenotypes[calculateSeries(b)-b]++;
}
} else {
genotypes[calculateSeries(b-1)+a]++;
allgenotypes[calculateSeries(b-1)+a]++;
}
npopsize--;
}
popsize = popsize/2;
printf("\nStatistics for Generation %d:\n Population: %d\n Number of Genotype:\n",i,popsize);
int index = 0;
for (int j = 0; j <= alnum-1; j++) {
printf(" A%dA%d: %d\n",(j+1),(j+1),genotypes[index]);
index++;
for (int k = 1; k <= j; k++) {
printf(" A%dA%d: %d\n",k,(j+1),genotypes[index]);
index++;
}
}
printf("\n Number of Allele:\n");
for (int j = 0; j <= alnum-1; j++) {
printf(" A%d: %d\n",(j+1),alsum[j]);
}
printf("\n Percent Allele Composition:\n");
for (int j = 0; j <= alnum-1; j++) {
/*allp [gens] [j] = p[j]; // Store old probability values in array */
p[j] = ((long double) alsum[j])/((long double) (2*popsize)); // Generate new ones from current generation
printf(" A%d: %Lf%%\n",(j+1),(p[j]*100));
}
// Clean up:
for (int j = 0; j <= 465; j++) {
genotypes[j] = 0;
}
for (int j = 0; j <= 31; j++) {
nalsum[j] = 0;
}
}
/*printf("\nGraph of Total Amounts of Each Genotype (one # represents 10):\n");
int index = 0;
for (int i = 0; i <= alnum-1; i++) {
printf(" A%dA%d: ",(i+1),(i+1));
for (int j = 0; j < (allgenotypes[index]/10); j++) {
printf("#");
}
printf("\n");
index++;
for (int j = 1; j <= i; j++) {
printf(" A%dA%d: ",j,(i+1));
for (int k = 0; k <= (allgenotypes[index]/10); k++) {
printf("#");
}
printf("\n");
index++;
}
}*/
return 0;
}
The expression:
is going to be zero whenever
maxpopis greater thanpopsize. If you’re interested in fractional powers, you’re going to need to convert to double sooner.A value of zero shouldn’t cause a freeze, though. Did you include
<math.h>? (Yes: you say as much in the question.)If not, then you’ve got more problems; the first argument should be an explicit double.You could sensibly write:
That’s far more readable because there are fewer parentheses and fewer casts.
Have you tried printing the various values at the point of the freeze? If you’re not sure why something is going wrong, one of the first things to do is to make sure you know what values you’re working with.