void print_chains(const int *adjacency, const int *adjacency_length, const int *is_basal, const int *node_count, const int *max_queue, int *status) { /* WARNING: Nested returns */ /* Enumerates every unique trophic path in a directed graph. Output is written to chains. In params: adjacency: a matrix of node_count rows. First column is the number of consumers of that row. Subsequent columns are ids of consumers. adjacency_length: the number of ints in adjacency is_basal: an array of length node_count. 1 for nodes that have no resources, 0 otherwise. Chains start only with nodes which have a 1 in is_basal. node_count: the number of nodes in the network. ncols: the number of columns in chains. nrows: the number of rows in chains. max_queue: the maximum alowabe size of the queue used to compute chains. 0 indicates no limit. Out params: status: -1 - unexpected error. 0 - normal exit. 1 - problem with one of the parameters. */ /* Quick and dirty parameter checks */ if(0==adjacency || 0==adjacency_length || *adjacency_length<1 || 0==is_basal || 0==node_count || 0==max_queue || *max_queue<0 || 0==status) { if(0!=status) { *status = 1; } /* WARNING: Nested return */ return; } *status = -1; // Default to an error status code try { std::vector<IntVector> adj = Adjacency(adjacency, *node_count); IntVector basal(is_basal, is_basal + *node_count); TrophicChains<PrintChainsVisitor> worker(adj, basal, *max_queue); PrintChainsVisitor visitor; worker.visit(visitor); // Normal exit *status = 0; } catch(const std::exception &e) { REprintf("Unexpected error in print_chains[%s]\n", e.what()); } catch(...) { REprintf("Unexpected error in print_chains\n"); } }
void create_assembled_pool(Params *p, double **pool, int divpool, double fert) { restart:; // define and initialize the ecosystem list //----------------------------------------- sll ecosys; sll_init(&ecosys,(void*)free_species); // create the basal resources //--------------------------- basal(p,&ecosys,fert); // assemble until the targetted diversity is reached //-------------------------------------------------- int a = divpool + EAM_NBNUT + EAM_NBDET; int counter = EAM_STOP_UNSUCCESS_ASSEMBLY*divpool; while(ecosys.length != a) { ParamSP *sp = (void*)species(p,2); install_process(p,&ecosys,sp); sll_rm(&ecosys,extinct_condition); ++(p->num); --counter; if(counter == 0) { sll_rm_all(&ecosys); //create_assembled_pool(p, pool, divpool, fert); goto restart; } } // remove the resources //--------------------- sll_rm(&ecosys,is_resource); // create the subpool matrix and fill it with the selected species //---------------------------------------------------------------- sllnode *node = ecosys.head; for (int i = 0; node != NULL; i++, node = node->next) { ParamSP sp = *(ParamSP*)(node->data); sp.d = EAM_N0SP; tr_sp_array(&sp,pool[i]); } // free the memory //---------------- sll_rm_all(&ecosys); }
void assembly_run(Params *p, double nfert, double **regpool, int poolsize, char *folder, char *replicate_identity) { // Define and initialize the history and ecosystem lists //------------------------------------------------------ sll history; sll_init(&history,(void*)free_seq); sll ecosys; sll_init(&ecosys,(void*)free_species); // create the basal resources //--------------------------- basal(p,&ecosys,nfert); // create and initialize the presence matrix (ne pas oublier de mettre les espèces au minimum pour l'invasion) //------------------------------------------ unsigned int **presence = (unsigned int**)mat_alloc(2,poolsize,sizeof(unsigned int)); for(int i = 0 ; i < poolsize ; ++i) { presence[0][i] = regpool[i][1]; presence[1][i] = 0; } // get the initial values of the sequence //--------------------------------------- seqlevel *seq0 = fill_seq(&ecosys,0,0); seq0->success = 0; sll_add_head(&history,seq0); // assemble until any species can install (or all are already installed) //---------------------------------------------------------------------- int a = poolsize + EAM_NBNUT + EAM_NBDET; /* expected ecosystem size */ int stop_endcycles = poolsize * EAM_STOP_ENDCYCLE; /* variable to stop the sequence if infinite */ int endcycles = 0; /* 0 if endpoint / 1 if endcycle */ int unsucc = EAM_STOP; /* check the success of the invader */ int invasion = 1; /* invasion number */ while(ecosys.length != a) { int b = get_int(p->rng,0,poolsize); /* select randomly the number of the species in the regional pool */ if(presence[1][b] == 0) /* if the species is not already in the ecosystem */ { ParamSP *sp = (ParamSP*)malloc(sizeof(ParamSP)); tr_sp_struct(regpool[b],sp); install_process(p,&ecosys,sp); /* install the species */ seqlevel *seq = fill_seq(&ecosys,invasion,presence[0][b]); /* create and initialize a sequence node */ sll_rm(&ecosys,extinct_condition); /* remove the extincted species */ presence_absence(&ecosys,presence,poolsize); /* fill the presence-absence matrix */ unsucc = (presence[1][b] == 0) ? unsucc-1 : EAM_STOP; /* upgrade the counter of unsuccessfull installations */ seq->success = presence[1][b]; /* fill the success of invader installation in the sequence node */ sll_add_head(&history,seq); /* add the sequence node to the assembly history */ ++invasion; /* upgrade the invasion number */ --stop_endcycles; /* upgrade the endcycle detector */ } if(unsucc == 0) break; if(stop_endcycles == 0) /* break the loop if its an endcycle */ { endcycles = 1; break; } } // print the outputs : subpool / final community / sequence / abundances history / identity history //------------------ print_final_community(&ecosys,folder,replicate_identity); print_id_history(&history,poolsize,folder,replicate_identity); print_final_biomasses_history(&history,poolsize,folder,replicate_identity); print_sequence(&history,folder,replicate_identity); char *buffer = (char*)malloc(100); sprintf(buffer, "%s/%s_endcycle.txt",folder,replicate_identity); FILE *out = fopen(buffer,"w"); fprintf(out,"%d",endcycles); fclose(out); // free the memory //---------------- mat_free((void**)presence,2); sll_rm_all(&history); sll_rm_all(&ecosys); free(buffer); }
void trophic_chains_stats(const int *adjacency, const int *adjacency_length, const int *is_basal, const int *node_count, const int *n_chains, const int *longest, const int *max_queue, int *node_pos_counts, int *chain_lengths, int *status) { /* WARNING: Nested returns */ /* Enumerates every unique trophic path in a directed graph. Outputs are the mean, minimum and maximum position of each node in every chain. In params: adjacency: a matrix of node_count rows. First column is the number of consumers of that row. Subsequent columns are ids of consumers. adjacency_length: the number of ints in adjacency is_basal: an array of length node_count. 1 for nodes that have no resources, 0 otherwise. Chains start only with nodes which have a 1 in is_basal. node_count: the number of nodes in the network. n_chains: the number of chains. longest: the number of nodes in the longest chain. max_queue: the maximum alowabe size of the queue used to compute chains. 0 indicates no limit. Out params: node_pos_counts: an array of n_chains * longest integers. Will contain counts of the number of times each node appears at a given position in the chain. chain_lengths: an array of n_chains integers. Will contain the length of each chain. status: -1 - unexpected error. 0 - normal exit. 1 - problem with one of the parameters. */ /* Quick and dirty parameter checks */ if(0==adjacency || 0==adjacency_length || *adjacency_length<1 || 0==is_basal || 0==node_count || *node_count<1 || 0==n_chains || *n_chains<1 || 0==longest || *longest<1 || 0==max_queue || *max_queue<0 || 0==node_pos_counts || 0==chain_lengths || 0==status) { if(0!=status) { *status = 1; } /* WARNING: Nested return */ return; } *status = -1; // Default to an error status code try { std::vector<IntVector> adj = Adjacency(adjacency, *node_count); IntVector basal(is_basal, is_basal + *node_count); TrophicChains<ChainStatsVisitor> worker(adj, basal, *max_queue); ChainStatsVisitor visitor(*node_count, *longest); worker.visit(visitor); if(sizeof(IntVector::value_type)!=sizeof(*chain_lengths) || sizeof(IntVector::value_type)!=sizeof(*node_pos_counts)) { throw CheddarException("Unexpected type size"); } else if(visitor.chain_lengths_.size()!=IntVector::size_type(*n_chains)) { throw CheddarException("Unexpected number of chains"); } else if(visitor.counts_.size()!=IntVector::size_type(*node_count)) { throw CheddarException("Unexpected number of nodes"); } else { std::memcpy(chain_lengths, &visitor.chain_lengths_[0], sizeof(int) * *n_chains); for(ChainStatsVisitor::CountVector::size_type node=0; node<visitor.counts_.size(); ++node) { ChainStatsVisitor::CountVector::const_reference v = visitor.counts_[node]; if(v.size()!=ChainStatsVisitor::CountVector::value_type::size_type(*longest)) { throw CheddarException("Unexpected number of node position counts"); } else { std::memcpy(node_pos_counts + node * *longest, &v[0], sizeof(int) * *longest); } } } // Normal exit *status = 0; } catch(const std::exception &e) { REprintf("Unexpected error in trophic_chains_stats [%s]\n", e.what()); } catch(...) { REprintf("Unexpected error in trophic_chains_stats\n"); } }