prime_factor_result* prime_factors(int n) { if(n == 1) { return simple_result(1, 1); } ivector* primes = get_prime_factor_vector(n); ivector_iter* iter = ivector_iter_init(primes); prime_factor_result* r = prime_factor_result_init(primes); int i = -1; int last = -1; while(ivector_iter_more(iter)) { int p = ivector_iter_next(iter); if(p == last) { r->pfs[i].exponent++; } else { i++; r->pfs[i].mantissa = p; r->pfs[i].exponent = 1; last = p; } } r->count = i+1; ivector_free(primes); ivector_iter_free(iter); return r; }
/////////////////////////////////////////// // The simulation // /////////////////////////////////////////// void *sim(void *parameters) { const Params P = *((Params*)parameters); const int k_gen = P.k_gen; const int kernel = P.kernel; const int communities = P.communities; const int j_per_c = P.j_per_c; const int init_species = P.init_species; const int init_pop_size = j_per_c / init_species; const double mu = P.mu; const double s = P.s; const double eta = P.eta; const double width = P.width; const double width2 = width * width; const double sigma = P.var; const double sigma2 = sigma * sigma; // GSL's Taus generator: gsl_rng *rng = gsl_rng_alloc(gsl_rng_taus2); // Initialize the GSL generator with /dev/urandom: const unsigned int seed = devurandom_get_uint(); gsl_rng_set(rng, seed); // Seed with time printf(" <seed>%u</seed>\n", seed); // Used to name the output file: char *buffer = (char*)malloc(100); // Nme of the file: sprintf(buffer, "%s%u.xml", P.ofilename, seed); // Open the output file: FILE *restrict out = fopen(buffer, "w"); // Store the total num. of species/1000 generations: int *restrict total_species = (int*)malloc(k_gen * sizeof(int)); // Number of speciation events/1000 generations: int *restrict speciation_events = (int*)malloc(k_gen * sizeof(int)); // Number of extinctions/1000 generations: int *restrict extinction_events = (int*)malloc(k_gen * sizeof(int)); // Number of speciation events/vertex: int *restrict speciation_per_c = (int*)malloc(communities * sizeof(int)); // Number of local extinction events/vertex: int *restrict extinction_per_c = (int*)malloc(communities * sizeof(int)); // Store the lifespan of the extinct species: ivector lifespan; ivector_init0(&lifespan); // Store the population size at speciation event: ivector pop_size; ivector_init0(&pop_size); // (x, y) coordinates for the spatial graph: double *restrict x = (double*)malloc(communities * sizeof(double)); double *restrict y = (double*)malloc(communities * sizeof(double)); for (int i = 0; i < communities; ++i) { speciation_per_c[i] = 0; extinction_per_c[i] = 0; } // Initialize an empty list of species: species_list *restrict list = species_list_init(); // Initialize the metacommunity and fill them with the initial species evenly: for (int i = 0; i < init_species; ++i) { // Intialize the species and add it to the list: species_list_add(list, species_init(communities, 0, 3)); } // To iterate the list; slnode *it = list->head; // Fill the communities: while (it != NULL) { for (int i = 0; i < communities; ++i) { it->sp->n[i] = init_pop_size; it->sp->genotypes[0][i] = init_pop_size; } it = it->next; } // To iterate the list; const int remainder = j_per_c - (init_species * init_pop_size); for (int i = 0; i < communities; ++i) { it = list->head; for (int j = 0; j < remainder; ++j, it = it->next) { ++(it->sp->n[i]); ++(it->sp->genotypes[0][i]); } } int sum = 0; it = list->head; while (it != NULL) { sum += species_total(it->sp); it = it->next; } assert(sum == j_per_c * communities); #ifdef NOTTOOCLOSE { int count_c = 0; while (count_c < communities) { bool within = false; const double xx = gsl_rng_uniform(rng); const double yy = gsl_rng_uniform(rng); for (int i = 0; i < count_c; ++i) { if (hypot(x[i] - xx, y[i] - yy) < MINDIST) { within = true; // oh nooo, an evil goto! break; } } if (within == false) { x[count_c] = xx; y[count_c] = yy; ++count_c; } } } #else for (int i = 0; i < communities; ++i) { x[i] = gsl_rng_uniform(rng); y[i] = gsl_rng_uniform(rng); } #endif double **m = (double**)malloc(communities * sizeof(double*)); for (int i = 0; i < communities; ++i) { m[i] = (double*)malloc(communities * sizeof(double)); } for (int i = 0; i < communities; ++i) { for (int j = 0; j < communities; ++j) { const double a = x[i] - x[j]; const double b = y[i] - y[j]; const double x = hypot(a, b); assert(distance >= 0.0); if (kernel == gaussian_k) { m[i][j] = (1.0 / sqrt(2 * M_PI * sigma2)) * exp((-x * x) / (2 * sigma2)); } else { m[i][j] = -(eta + 2)/(2 * M_PI * width2) * pow(1 + (x * x) / width2, eta / 2); } } } // Setup the array for migration: double **cmig = setup_cmig(m, communities); fprintf(out, "<?xml version=\"1.0\"?>\n"); fprintf(out, "<simulation>\n"); if (kernel == gaussian_k) { fprintf(out, " <model>Gaussian</model>\n"); } else { fprintf(out, " <model>Fat-tailed</model>\n"); } fprintf(out, " <seed>%u</seed>\n", seed); fprintf(out, " <metacom_size>%d</metacom_size>\n", j_per_c * communities); fprintf(out, " <k_gen>%d</k_gen>\n", k_gen); fprintf(out, " <num_comm>%d</num_comm>\n", communities); fprintf(out, " <individuals_per_comm>%d</individuals_per_comm>\n", j_per_c); fprintf(out, " <initial_num_species>%d</initial_num_species>\n", init_species); fprintf(out, " <mutation_rate>%.2e</mutation_rate>\n", mu); if (kernel == gaussian_k) { fprintf(out, " <variance>%.8e</variance>\n", sigma); } else { fprintf(out, " <width>%.8e</width>\n", width); fprintf(out, " <eta>%.8e</eta>\n", eta); } // To select the species and genotypes to pick and replace: slnode *s0 = list->head; // species0 slnode *s1 = list->head; // species1 int g0 = 0; int g1 = 0; int v1 = 0; // Vertex of the individual 1 ///////////////////////////////////////////// // Groups of 1 000 generations // ///////////////////////////////////////////// for (int k = 0; k < k_gen; ++k) { extinction_events[k] = 0; speciation_events[k] = 0; ///////////////////////////////////////////// // 1 000 generations // ///////////////////////////////////////////// for (int gen = 0; gen < 1000; ++gen) { const int current_date = (k * 1000) + gen; ///////////////////////////////////////////// // A single generation // ///////////////////////////////////////////// for (int t = 0; t < j_per_c; ++t) { ///////////////////////////////////////////// // A single time step (for each community) // ///////////////////////////////////////////// for (int c = 0; c < communities; ++c) { // Select the species and genotype of the individual to be replaced int position = (int)(gsl_rng_uniform(rng) * j_per_c); s0 = list->head; int index = s0->sp->n[c]; while (index <= position) { s0 = s0->next; index += s0->sp->n[c]; } position = (int)(gsl_rng_uniform(rng) * s0->sp->n[c]); if (position < s0->sp->genotypes[0][c]) { g0 = 0; } else if (position < (s0->sp->genotypes[0][c] + s0->sp->genotypes[1][c])) { g0 = 1; } else { g0 = 2; } // Choose the vertex for the individual const double r_v1 = gsl_rng_uniform(rng); v1 = 0; while (r_v1 > cmig[c][v1]) { ++v1; } // species of the new individual position = (int)(gsl_rng_uniform(rng) * j_per_c); s1 = list->head; index = s1->sp->n[v1]; while (index <= position) { s1 = s1->next; index += s1->sp->n[v1]; } if (v1 == c) // local remplacement { const double r = gsl_rng_uniform(rng); const int aa = s1->sp->genotypes[0][v1]; const int Ab = s1->sp->genotypes[1][v1]; const int AB = s1->sp->genotypes[2][v1]; // The total fitness of the population 'W': const double w = aa + Ab * (1.0 + s) + AB * (1.0 + s) * (1.0 + s); if (r < aa / w) { g1 = gsl_rng_uniform(rng) < mu ? 1 : 0; } else { if (AB == 0 || r < (aa + Ab * (1.0 + s)) / w) { g1 = gsl_rng_uniform(rng) < mu ? 2 : 1; } else { g1 = 2; } } } else { // Migration event g1 = 0; } // Apply the changes s0->sp->n[c]--; s0->sp->genotypes[g0][c]--; s1->sp->n[c]++; s1->sp->genotypes[g1][c]++; //////////////////////////////////////////// // Check for local extinction // //////////////////////////////////////////// if (s0->sp->n[c] == 0) { extinction_per_c[c]++; } //////////////////////////////////////////// // Check for speciation // //////////////////////////////////////////// else if (s0->sp->genotypes[2][c] > 0 && s0->sp->genotypes[0][c] == 0 && s0->sp->genotypes[1][c] == 0) { species_list_add(list, species_init(communities, current_date, 3)); // Add the new species const int pop = s0->sp->n[c]; list->tail->sp->n[c] = pop; list->tail->sp->genotypes[0][c] = pop; s0->sp->n[c] = 0; s0->sp->genotypes[2][c] = 0; // To keep info on patterns of speciation... ivector_add(&pop_size, pop); ++speciation_events[k]; ++speciation_per_c[c]; } } // End 'c' } // End 't' // Remove extinct species from the list and store the number of extinctions. extinction_events[k] += species_list_rmv_extinct2(list, &lifespan, current_date); } // End 'g' total_species[k] = list->size; } // End 'k' ////////////////////////////////////////////////// // PRINT THE FINAL RESULTS // ////////////////////////////////////////////////// fprintf(out, " <global>\n"); fprintf(out, " <avr_lifespan>%.4f</avr_lifespan>\n", imean(lifespan.array, lifespan.size)); fprintf(out, " <median_lifespan>%.4f</median_lifespan>\n", imedian(lifespan.array, lifespan.size)); fprintf(out, " <avr_pop_size_speciation>%.4f</avr_pop_size_speciation>\n", imean(pop_size.array, pop_size.size)); fprintf(out, " <median_pop_size_speciation>%.4f</median_pop_size_speciation>\n", imedian(pop_size.array, pop_size.size)); fprintf(out, " <speciation_per_k_gen>"); int i = 0; for (; i < k_gen - 1; ++i) { fprintf(out, "%d ", speciation_events[i]); } fprintf(out, "%d</speciation_per_k_gen>\n", speciation_events[i]); fprintf(out, " <extinctions_per_k_gen>"); for (i = 0; i < k_gen - 1; ++i) { fprintf(out, "%d ", extinction_events[i]); } fprintf(out, "%d</extinctions_per_k_gen>\n", extinction_events[i]); fprintf(out, " <extant_species_per_k_gen>"); for (i = 0; i < k_gen - 1; ++i) { fprintf(out, "%d ", total_species[i]); } fprintf(out, "%d</extant_species_per_k_gen>\n", total_species[i]); // Print global distribution fprintf(out, " <species_distribution>"); ivector species_distribution; ivector_init1(&species_distribution, 128); it = list->head; while (it != NULL) { ivector_add(&species_distribution, species_total(it->sp)); it = it->next; } ivector_sort_asc(&species_distribution); ivector_print(&species_distribution, out); fprintf(out, "</species_distribution>\n"); double *octaves; int oct_num = biodiversity_octaves(species_distribution.array, species_distribution.size, &octaves); fprintf(out, " <octaves>"); for (i = 0; i < oct_num; ++i) { fprintf(out, "%.2f ", octaves[i]); } fprintf(out, "%.2f</octaves>\n", octaves[i]); fprintf(out, " </global>\n"); // Print info on all vertices double *restrict ric_per_c = (double*)malloc(communities * sizeof(double)); for (int c = 0; c < communities; ++c) { fprintf(out, " <vertex>\n"); fprintf(out, " <id>%d</id>\n", c); fprintf(out, " <xcoor>%.4f</xcoor>\n", x[c]); fprintf(out, " <ycoor>%.4f</ycoor>\n", y[c]); fprintf(out, " <total_mig_rate>%.8f</total_mig_rate>\n", 1.0 - ((c==0)?cmig[0][0]:cmig[c][c]-cmig[c][c-1])); fprintf(out, " <speciation_events>%d</speciation_events>\n", speciation_per_c[c]); fprintf(out, " <extinction_events>%d</extinction_events>\n", extinction_per_c[c]); int vertex_richess = 0; ivector_rmvall(&species_distribution); it = list->head; while (it != NULL) { ivector_add(&species_distribution, it->sp->n[c]); it = it->next; } // Sort the species distribution and remove the 0s ivector_sort_asc(&species_distribution); ivector_trim_small(&species_distribution, 1); ric_per_c[c] = (double)species_distribution.size; fprintf(out, " <species_richess>%d</species_richess>\n", species_distribution.size); fprintf(out, " <species_distribution>"); ivector_print(&species_distribution, out); fprintf(out, "</species_distribution>\n"); // Print octaves free(octaves); oct_num = biodiversity_octaves(species_distribution.array, species_distribution.size, &octaves); fprintf(out, " <octaves>"); for (i = 0; i < oct_num - 1; ++i) { fprintf(out, "%.2f ", octaves[i]); } fprintf(out, "%.2f</octaves>\n", octaves[i]); fprintf(out, " </vertex>\n"); } fprintf(out, "</simulation>\n"); sprintf(buffer, "%s%u-bc.xml", P.ofilename, seed); FILE *restrict obc = fopen(buffer, "w"); fprintf(obc, "<dissimilarity>\n"); for (int i = 0; i < communities; ++i) { for (int j = 0; j < communities - i; ++j) { const double a = x[i] - x[j]; const double b = y[i] - y[j]; int sum = 0; s0 = list->head; while (s0 != NULL) { const int n_a = s0->sp->n[i]; const int n_b = s0->sp->n[j]; if (n_a > 0 && n_b > 0) { sum += MIN(n_a, n_b); } s0 = s0->next; } const double bray_curtis = ((double)sum) / j_per_c; fprintf(obc, " <pair><distance>%.8f</distance><bc>%.8f</bc></pair>\n", hypot(a, b), bray_curtis); } } fprintf(obc, "</dissimilarity>\n"); ////////////////////////////////////////////////// // EPILOGUE... // ////////////////////////////////////////////////// // Close files; fclose(out); fclose(obc); // Free arrays; free(x); free(y); free(ric_per_c); //free(spe_per_c); free(buffer); free(total_species); free(octaves); free(speciation_per_c); free(extinction_per_c); free(speciation_events); free(extinction_events); // Free structs; species_list_free(list); ivector_free(&species_distribution); ivector_free(&lifespan); ivector_free(&pop_size); gsl_rng_free(rng); return NULL; }
/////////////////////////////////////////// // The simulation // /////////////////////////////////////////// void *sim(void *parameters) { const Params P = *((Params*)parameters); char *shape = P.shape; const int k_gen = P.k_gen; const int communities = P.communities; const int j_per_c = P.j_per_c; const int init_species = P.init_species; const int init_pop_size = j_per_c / init_species; const double omega = P.omega; const double mu = P.mu; const double s = P.s; const double radius = P.r; const double width = P.w; // GSL's Taus generator: gsl_rng *rng = gsl_rng_alloc(gsl_rng_taus2); // Initialize the GSL generator with /dev/urandom: const unsigned int seed = devurandom_get_uint(); gsl_rng_set(rng, seed); // Seed with time printf(" <seed>%u</seed>\n", seed); // Used to name the output file: char *buffer = (char*)malloc(100); // Nme of the file: sprintf(buffer, "%s%u.xml", P.ofilename, seed); // Open the output file: FILE *restrict out = fopen(buffer, "w"); // Store the total num. of species/1000 generations: int *restrict total_species = (int*)malloc(k_gen * sizeof(int)); // Number of speciation events/1000 generations: int *restrict speciation_events = (int*)malloc(k_gen * sizeof(int)); // Number of extinctions/1000 generations: int *restrict extinction_events = (int*)malloc(k_gen * sizeof(int)); // Number of speciation events/vertex: int *restrict speciation_per_c = (int*)malloc(communities * sizeof(int)); // Number of local extinction events/vertex: int *restrict extinction_per_c = (int*)malloc(communities * sizeof(int)); // Store the lifespan of the extinct species: ivector lifespan; ivector_init0(&lifespan); // Store the population size at speciation event: ivector pop_size; ivector_init0(&pop_size); // (x, y) coordinates for the spatial graph: double *restrict x = (double*)malloc(communities * sizeof(double)); double *restrict y = (double*)malloc(communities * sizeof(double)); for (int i = 0; i < communities; ++i) { speciation_per_c[i] = 0; extinction_per_c[i] = 0; } // Initialize an empty list of species: species_list *restrict list = species_list_init(); // Initialize the metacommunity and fill them with the initial species evenly: for (int i = 0; i < init_species; ++i) { // Intialize the species and add it to the list: species_list_add(list, species_init(communities, 0, 3)); } // To iterate the list; slnode *it = list->head; // Fill the communities: while (it != NULL) { for (int i = 0; i < communities; ++i) { it->sp->n[i] = init_pop_size; it->sp->genotypes[0][i] = init_pop_size; } it = it->next; } // To iterate the list; const int remainder = j_per_c - (init_species * init_pop_size); for (int i = 0; i < communities; ++i) { it = list->head; for (int j = 0; j < remainder; ++j, it = it->next) { ++(it->sp->n[i]); ++(it->sp->genotypes[0][i]); } } // Test (will be removed for v2.0): int sum = 0; it = list->head; while (it != NULL) { sum += species_total(it->sp); it = it->next; } assert(sum == j_per_c * communities); // Create the metacommunity; graph g; switch(shape[0]) { case 's': shape = "star"; graph_get_star(&g, communities); break; case 'c': if (shape[1] == 'o') { shape = "complete"; graph_get_complete(&g, communities); break; } else { shape = "circle"; graph_get_circle(&g, communities); break; } case 'r': if (shape[1] == 'e') { shape = "rectangle"; graph_get_rec_crgg(&g, communities, width, radius, x, y, rng); break; } else { shape = "random"; graph_get_crgg(&g, communities, radius, x, y, rng); break; } default: shape = "random"; graph_get_crgg(&g, communities, radius, x, y, rng); } // Setup the cumulative jagged array for migration: double **cumul = setup_cumulative_list(&g, omega); fprintf(out, "<?xml version=\"1.0\"?>\n"); fprintf(out, "<simulation>\n"); fprintf(out, " <model>"); if (P.m == MODEL_BDM_NEUTRAL) { fprintf(out, "Neutral BDM speciation</model>\n"); } else if (P.m == MODEL_BDM_SELECTION) { fprintf(out, "BDM speciation with selection</model>\n"); } fprintf(out, " <seed>%u</seed>\n", seed); fprintf(out, " <shape_metacom>%s</shape_metacom>\n", shape); fprintf(out, " <metacom_size>%d</metacom_size>\n", j_per_c * communities); fprintf(out, " <k_gen>%d</k_gen>\n", k_gen); fprintf(out, " <num_comm>%d</num_comm>\n", communities); fprintf(out, " <individuals_per_comm>%d</individuals_per_comm>\n", j_per_c); fprintf(out, " <initial_num_species>%d</initial_num_species>\n", init_species); fprintf(out, " <mutation_rate>%.2e</mutation_rate>\n", mu); fprintf(out, " <omega>%.2e</omega>\n", omega); if (P.m == MODEL_BDM_SELECTION) { fprintf(out, " <selection>%.2e</selection>\n", s); } if (shape[0] == 'r') { fprintf(out, " <radius>%.4f</radius>\n", radius); } if (shape[0] == 'r' && shape[1] == 'e') { fprintf(out, " <width>%.4f</width>\n", width); } // To select the species and genotypes to pick and replace: slnode *s0 = list->head; // species0 slnode *s1 = list->head; // species1 int g0 = 0; int g1 = 0; int v1 = 0; // Vertex of the individual 1 ///////////////////////////////////////////// // Groups of 1 000 generations // ///////////////////////////////////////////// for (int k = 0; k < k_gen; ++k) { extinction_events[k] = 0; speciation_events[k] = 0; ///////////////////////////////////////////// // 1 000 generations // ///////////////////////////////////////////// for (int gen = 0; gen < 1000; ++gen) { const int current_date = (k * 1000) + gen; ///////////////////////////////////////////// // A single generation // ///////////////////////////////////////////// for (int t = 0; t < j_per_c; ++t) { ///////////////////////////////////////////// // A single time step (for each community) // ///////////////////////////////////////////// for (int c = 0; c < communities; ++c) { // Select the species and genotype of the individual to be replaced int position = (int)(gsl_rng_uniform(rng) * j_per_c); s0 = list->head; int index = s0->sp->n[c]; while (index <= position) { s0 = s0->next; index += s0->sp->n[c]; } position = (int)(gsl_rng_uniform(rng) * s0->sp->n[c]); if (position < s0->sp->genotypes[0][c]) { g0 = 0; } else if (position < (s0->sp->genotypes[0][c] + s0->sp->genotypes[1][c])) { g0 = 1; } else { g0 = 2; } // Choose the vertex for the individual const double r_v1 = gsl_rng_uniform(rng); v1 = 0; while (r_v1 > cumul[c][v1]) { ++v1; } v1 = g.adj_list[c][v1]; // species of the new individual position = (int)(gsl_rng_uniform(rng) * j_per_c); s1 = list->head; index = s1->sp->n[v1]; while (index <= position) { s1 = s1->next; index += s1->sp->n[v1]; } if (v1 == c) // local remplacement { const double r = gsl_rng_uniform(rng); const int aa = s1->sp->genotypes[0][v1]; const int Ab = s1->sp->genotypes[1][v1]; const int AB = s1->sp->genotypes[2][v1]; // The total fitness of the population 'W': const double w = aa + Ab * (1.0 + s) + AB * (1.0 + s) * (1.0 + s); if (r < aa / w) { g1 = gsl_rng_uniform(rng) < mu ? 1 : 0; } else { if (AB == 0 || r < (aa + Ab * (1.0 + s)) / w) { g1 = gsl_rng_uniform(rng) < mu ? 2 : 1; } else { g1 = 2; } } } else { // Migration event g1 = 0; } // Apply the changes s0->sp->n[c]--; s0->sp->genotypes[g0][c]--; s1->sp->n[c]++; s1->sp->genotypes[g1][c]++; //////////////////////////////////////////// // Check for local extinction // //////////////////////////////////////////// if (s0->sp->n[c] == 0) { extinction_per_c[c]++; } //////////////////////////////////////////// // Check for speciation // //////////////////////////////////////////// else if (s0->sp->genotypes[2][c] > 0 && s0->sp->genotypes[0][c] == 0 && s0->sp->genotypes[1][c] == 0) { species_list_add(list, species_init(communities, current_date, 3)); // Add the new species const int pop = s0->sp->n[c]; list->tail->sp->n[c] = pop; list->tail->sp->genotypes[0][c] = pop; s0->sp->n[c] = 0; s0->sp->genotypes[2][c] = 0; // To keep info on patterns of speciation... ivector_add(&pop_size, pop); ++speciation_events[k]; ++speciation_per_c[c]; } } // End 'c' } // End 't' // Remove extinct species from the list and store the number of extinctions. extinction_events[k] += species_list_rmv_extinct2(list, &lifespan, current_date); } // End 'g' total_species[k] = list->size; } // End 'k' ////////////////////////////////////////////////// // PRINT THE FINAL RESULTS // ////////////////////////////////////////////////// fprintf(out, " <global>\n"); fprintf(out, " <proper_edges>%d</proper_edges>\n", graph_edges(&g)); fprintf(out, " <links_per_c>%.4f</links_per_c>\n", (double)graph_edges(&g) / communities); fprintf(out, " <avr_lifespan>%.4f</avr_lifespan>\n", imean(lifespan.array, lifespan.size)); fprintf(out, " <median_lifespan>%.4f</median_lifespan>\n", imedian(lifespan.array, lifespan.size)); fprintf(out, " <avr_pop_size_speciation>%.4f</avr_pop_size_speciation>\n", imean(pop_size.array, pop_size.size)); fprintf(out, " <median_pop_size_speciation>%.4f</median_pop_size_speciation>\n", imedian(pop_size.array, pop_size.size)); fprintf(out, " <speciation_per_k_gen>"); int i = 0; for (; i < k_gen - 1; ++i) { fprintf(out, "%d ", speciation_events[i]); } fprintf(out, "%d</speciation_per_k_gen>\n", speciation_events[i]); fprintf(out, " <extinctions_per_k_gen>"); for (i = 0; i < k_gen - 1; ++i) { fprintf(out, "%d ", extinction_events[i]); } fprintf(out, "%d</extinctions_per_k_gen>\n", extinction_events[i]); fprintf(out, " <extant_species_per_k_gen>"); for (i = 0; i < k_gen - 1; ++i) { fprintf(out, "%d ", total_species[i]); } fprintf(out, "%d</extant_species_per_k_gen>\n", total_species[i]); // Print global distribution fprintf(out, " <species_distribution>"); ivector species_distribution; ivector_init1(&species_distribution, 128); it = list->head; while (it != NULL) { ivector_add(&species_distribution, species_total(it->sp)); it = it->next; } ivector_sort_asc(&species_distribution); ivector_print(&species_distribution, out); fprintf(out, "</species_distribution>\n"); double *octaves; int oct_num = biodiversity_octaves(species_distribution.array, species_distribution.size, &octaves); fprintf(out, " <octaves>"); for (i = 0; i < oct_num; ++i) { fprintf(out, "%.2f ", octaves[i]); } fprintf(out, "%.2f</octaves>\n", octaves[i]); fprintf(out, " </global>\n"); // Print info on all vertices double *restrict ric_per_c = (double*)malloc(communities * sizeof(double)); for (int c = 0; c < communities; ++c) { fprintf(out, " <vertex>\n"); fprintf(out, " <id>%d</id>\n", c); if (shape[0] == 'r') { fprintf(out, " <xcoor>%.4f</xcoor>\n", x[c]); fprintf(out, " <ycoor>%.4f</ycoor>\n", y[c]); } fprintf(out, " <degree>%d</degree>\n", g.num_e[c] + 1); fprintf(out, " <speciation_events>%d</speciation_events>\n", speciation_per_c[c]); fprintf(out, " <extinction_events>%d</extinction_events>\n", extinction_per_c[c]); int vertex_richess = 0; ivector_rmvall(&species_distribution); it = list->head; while (it != NULL) { ivector_add(&species_distribution, it->sp->n[c]); it = it->next; } // Sort the species distribution and remove the 0s ivector_sort_asc(&species_distribution); ivector_trim_small(&species_distribution, 1); ric_per_c[c] = (double)species_distribution.size; fprintf(out, " <species_richess>%d</species_richess>\n", species_distribution.size); fprintf(out, " <species_distribution>"); ivector_print(&species_distribution, out); fprintf(out, "</species_distribution>\n"); // Print octaves free(octaves); oct_num = biodiversity_octaves(species_distribution.array, species_distribution.size, &octaves); fprintf(out, " <octaves>"); for (i = 0; i < oct_num - 1; ++i) { fprintf(out, "%.2f ", octaves[i]); } fprintf(out, "%.2f</octaves>\n", octaves[i]); fprintf(out, " </vertex>\n"); } fprintf(out, "</simulation>\n"); // GraphML output: sprintf(buffer, "%s%u.graphml", P.ofilename, seed); FILE *outgml = fopen(buffer, "w"); graph_graphml(&g, outgml, seed); // Print to SVG files. sprintf(buffer, "%s%u.svg", P.ofilename, seed); FILE *outsvg = fopen(buffer, "w"); graph_svg(&g, x, y, 400.0, 20.0, outsvg); sprintf(buffer, "%s%u-speciation.svg", P.ofilename, seed); FILE *outsvgspe = fopen(buffer, "w"); double *spe_per_c = (double*)malloc(communities * sizeof(double)); for (int c = 0; c < communities; ++c) { spe_per_c[c] = (double)speciation_per_c[c]; } scale_0_1(spe_per_c, communities); graph_svg_abun(&g, x, y, 400.0, 20.0, spe_per_c, 2, outsvgspe); sprintf(buffer, "%s%u-richness.svg", P.ofilename, seed); FILE *outsvgric = fopen(buffer, "w"); scale_0_1(ric_per_c, communities); graph_svg_abun(&g, x, y, 400.0, 20.0, ric_per_c, 1, outsvgric); ////////////////////////////////////////////////// // EPILOGUE... // ////////////////////////////////////////////////// // Close files; fclose(out); fclose(outgml); fclose(outsvg); fclose(outsvgspe); fclose(outsvgric); // Free arrays; free(x); free(y); free(ric_per_c); free(spe_per_c); free(buffer); free(total_species); free(octaves); free(speciation_per_c); free(extinction_per_c); free(speciation_events); free(extinction_events); // Free structs; species_list_free(list); ivector_free(&species_distribution); ivector_free(&lifespan); ivector_free(&pop_size); graph_free(&g); gsl_rng_free(rng); return NULL; }