Esempio n. 1
0
/*
 * Merge the exists and forall variables of constraint i
 * - store the variables in solver->all_vars
 * - store their values in solver->all_values
 */
static void ef_build_full_map(ef_solver_t *solver, uint32_t i) {
  ef_cnstr_t *cnstr;
  ivector_t *v;
  uint32_t n;

  assert(i < ef_prob_num_constraints(solver->prob));
  cnstr = solver->prob->cnstr + i;

  // collect all variables of cnstr in solver->all_vars
  v = &solver->all_vars;
  ivector_reset(v);
  n = ef_constraint_num_evars(cnstr);
  ivector_add(v, cnstr->evars, n);
  n = ef_constraint_num_uvars(cnstr);
  ivector_add(v, cnstr->uvars, n);

  // project the evalues onto the exists variable of constraint i
  // store the results in all_values
  v = &solver->all_values;
  n = ef_constraint_num_evars(cnstr);
  resize_ivector(v, n);
  v->size = n;
  ef_project_exists_model(solver->prob, solver->evalue, cnstr->evars, v->data, n);

  // copy the uvalues for constraint i (from uvalue_aux to v)
  n = ef_constraint_num_uvars(cnstr);
  assert(n == solver->uvalue_aux.size);
  ivector_add(v, solver->uvalue_aux.data, n);

#if EF_VERBOSE
  printf("Full map\n");
  print_full_map(stdout, solver);
  fflush(stdout);
#endif
}
Esempio n. 2
0
File: main.c Progetto: PhDP/jsm
///////////////////////////////////////////
// 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;
}
Esempio n. 3
0
File: main.c Progetto: PhDP/origin
///////////////////////////////////////////
// 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;
}