out_species.writerow(out_row_species) file_species.close() stop_sim = datetime.now() elapsed_sim = stop_sim - start_sim print 'time for simulation', elapsed_sim #ecosystem.draw_species_distribution() #layout = nx.graphviz_layout(net, prog='dot', args='-Gnodesep=.07, -Granksep=.1, -Grankdir=BT') layout = nx.circular_layout(net) #fig = figure() #network_plot = fig.add_subplot(111) #nx.draw_networkx(net, layout, ax=network_plot) print 'S original =', net.order(), 'L original =', net.size( ), 'C original =', net.connectance() # # net_final = ecosystem.realised_net.copy() # layout2 = nx.circular_layout(net_final) # # fig2 = figure() # network_plot2 = fig2.add_subplot(111) # nx.draw_networkx(net_final, layout2, ax=network_plot2) # # print 'S realised =', net_final.order(), 'L realised =', net_final.size(), 'C realised =', net_final.connectance() #show()
class NetworkCreator(): ''' classdocs ''' def __init__(self): ''' Constructor ''' self.rnd = Random() self.rnd_uniform = uniform() self.net = Network() # self.invaders = [] def reset_state(self): self.rnd = Random() self.rnd_uniform = uniform() self.net.clear() def create_niche_model_network(self, S, C, prob=False): ''' prob = False; whether to create the network following the probabilistic niche model Niche model This is an implementation of the niche model ''' ns = self.rnd_uniform.rvs(size=S+POSSIBLE_INVADERS) bet = (1/(2*C)) - 1 self.beta_dist = beta(1,bet) producers = int(math.floor(S*PRIMARY_PRODS)) current_producers = 0 herbivores = int(math.floor(S*HERBIVORY)) current_herbivores = 0 predators = int(math.floor(S*TOP_PREDATORS)) current_predators = 0 #basal_to_top_links = 1 ## New constraint that this must be zero! while self.net.size() == 0 or not nx.is_connected(self.net.to_undirected()) or current_producers < producers or current_herbivores < herbivores or current_predators < predators: #or max(self.net.get_shortest_chain_length().values()) < 3: self.net.clear() # self.invaders = [] basal = None smallest_n = None #here we obtain the fundamental niche values for each one of the species in the network # n, c, r for i in xrange(1,S+1): self.net.add_node(i) self.net.node[i]['n'] = float(ns[i-1]) #self.rnd_uniform.rvs() self.net.node[i]['r'] = self.beta_dist.rvs() * self.net.node[i]['n'] self.net.node[i]['c'] = self.rnd.uniform((self.net.node[i]['r']/2), min(self.net.node[i]['n'], (1-(self.net.node[i]['r']/2)))) #the original value of c (commented bit) as originally presented in the Nature 2000 paper #was changed after reading the niche model specification presented in the JAE 2008 paper #the new specification ensures that the r of all the species always lie within the niche interval [0,1] #self.net.node[i]['c'] = self.rnd.uniform(self.net.node[i]['r']/2, self.net.node[i]['n']) self.net.node[i]['invader'] = False if smallest_n == None or self.net.node[i]['n'] < smallest_n: smallest_n = self.net.node[i]['n'] basal = i #if INVASION: # for i in xrange(S+1, (S+1)+(POSSIBLE_INVADERS)): ## invader = dict() ## invader['n'] = self.rnd_uniform.rvs() ## invader['r'] = self.beta_dist.rvs() * self.net.node[i]['n'] ## invader['c'] = self.rnd.uniform(self.net.node[i]['r']/2, self.net.node[i]['n']) ## invader['invader'] = True # # self.net.add_node(i) # self.net.node[i]['n'] = float(ns[i-1]) #self.rnd_uniform.rvs() # self.net.node[i]['r'] = self.beta_dist.rvs() * self.net.node[i]['n'] # self.net.node[i]['c'] = self.rnd.uniform((self.net.node[i]['r']/2), min(self.net.node[i]['n'], (1-(self.net.node[i]['r']/2)))) # self.net.node[i]['invader'] = False # self.invaders.append(invader) self.net.node[basal]['r'] = 0.0 self._create_links_based_on_fundamental_niche() tls = self.net.get_trophic_levels() # replacement of links between trophic levels 0 and 3 (does not conform to niches): top, top_preds = self.net.top_predators() basal, basal_sps = self.net.basal() #basal_to_top_links = 0 to_replace = [] for u,v in self.net.edges(): if u in basal_sps and v in top_preds and tls[v] == 3: #basal_to_top_links += 1 self.net.remove_edge(u,v) to_replace.append((u,v)) for pair in to_replace: new_u = pair[1] while new_u in basal_sps or new_u==pair[1]: new_u = np.random.randint(1,61) # species indexing starts at 1 self.net.add_edge(new_u, pair[1]) # calculations to check trophic constraints: current_herbivores = 0 current_producers = 0 current_predators = 0 for k in tls.keys(): if tls[k] == 1: current_herbivores += 1 elif tls[k] == 0: current_producers += 1 elif tls[k] == 3: current_predators += 1 print("replaced %d links" %(len(to_replace))) return self.net def _create_links_based_on_fundamental_niche(self, nodes_to_link=None): #based on the fundamental niche values obtained above we construct the network by adding #the corresponding links according to the species' niche and feeding range if nodes_to_link == None: nodes_to_link = set(self.net.nodes()) for i in self.net.nodes(): if self.net.node[i]['r'] == 0.0: continue r_lower_bound = self.net.node[i]['c'] - (self.net.node[i]['r']/2) r_upper_bound = self.net.node[i]['c'] + (self.net.node[i]['r']/2) for j in self.net.nodes(): if i not in nodes_to_link and j not in nodes_to_link: continue if self.net.node[j]['n'] >= r_lower_bound and self.net.node[j]['n'] <= r_upper_bound: self.net.add_edge(j,i) #for disconnected or duplicated nodes disc_nodes = set() self_loops = set(self.net.selfloop_edges()) for i in nodes_to_link: disconnected = False if self.net.degree(i) == 0: disconnected = True elif self.net.in_degree(i) == 1 and (i,i) in self_loops: # print 'producer with selfloop' if self.net.out_degree(i) > 1: self.net.remove_edge(i,i) else: disconnected = True attrs = self.net.node[i] self.net.remove_node(i) self.net.add_node(i, attr_dict=attrs) else: i_succs = set(self.net.successors(i)) i_predecs = set(self.net.predecessors(i)) for j in self.net.nodes(): j_succs = self.net.successors(j) j_predecs = self.net.predecessors(j) if i_succs == j_succs and i_predecs == j_predecs: disconnected = True attrs = self.net.node[i] self.net.remove_node(i) self.net.add_node(i, attr_dict=attrs) print 'duplicated node' break #we reassign the fundamental niche values to nodes that are disconnected or duplicated if disconnected: self.net.node[i]['n'] = self.rnd_uniform.rvs() self.net.node[i]['r'] = self.beta_dist.rvs() * self.net.node[i]['n'] self.net.node[i]['c'] = self.rnd.uniform(self.net.node[i]['r']/2, self.net.node[i]['n']) disc_nodes.add(i) if len(disc_nodes) > 0: self._create_links_based_on_fundamental_niche(disc_nodes) return
class NetworkCreator(): ''' classdocs ''' def __init__(self): ''' Constructor ''' self.rnd = Random() self.rnd_uniform = uniform() self.net = Network() # self.invaders = [] def reset_state(self): self.rnd = Random() self.rnd_uniform = uniform() self.net.clear() def create_niche_model_network(self, S, C, prob=False): ''' prob = False; whether to create the network following the probabilistic niche model Niche model This is an implementation of the niche model ''' ns = self.rnd_uniform.rvs(size=S + POSSIBLE_INVADERS) bet = (1 / (2 * C)) - 1 self.beta_dist = beta(1, bet) producers = int(math.floor(S * PRIMARY_PRODS)) current_producers = 0 herbivores = int(math.floor(S * HERBIVORY)) current_herbivores = 0 predators = int(math.floor(S * TOP_PREDATORS)) current_predators = 0 while self.net.size() == 0 or not nx.is_connected( self.net.to_undirected() ) or current_herbivores < herbivores or current_producers < producers or current_predators < predators: #or max(self.net.get_shortest_chain_length().values()) < 3: self.net.clear() # self.invaders = [] basal = None smallest_n = None #here we obtain the fundamental niche values for each one of the species in the network # n, c, r for i in range(1, S + 1): self.net.add_node(i) self.net.nodes[i]['n'] = float(ns[i - 1]) #self.rnd_uniform.rvs() self.net.nodes[i]['r'] = self.beta_dist.rvs( ) * self.net.nodes[i]['n'] self.net.nodes[i]['c'] = self.rnd.uniform( (self.net.nodes[i]['r'] / 2), min(self.net.nodes[i]['n'], (1 - (self.net.nodes[i]['r'] / 2)))) #the original value of c (commented bit) as originally presented in the Nature 2000 paper #was changed after reading the niche model specification presented in the JAE 2008 paper #the new specification ensures that the r of all the species always lie within the niche interval [0,1] #self.net.node[i]['c'] = self.rnd.uniform(self.net.node[i]['r']/2, self.net.node[i]['n']) self.net.nodes[i]['invader'] = False if smallest_n == None or self.net.nodes[i]['n'] < smallest_n: smallest_n = self.net.nodes[i]['n'] basal = i #if INVASION: # for i in xrange(S+1, (S+1)+(POSSIBLE_INVADERS)): ## invader = dict() ## invader['n'] = self.rnd_uniform.rvs() ## invader['r'] = self.beta_dist.rvs() * self.net.node[i]['n'] ## invader['c'] = self.rnd.uniform(self.net.node[i]['r']/2, self.net.node[i]['n']) ## invader['invader'] = True # # self.net.add_node(i) # self.net.node[i]['n'] = float(ns[i-1]) #self.rnd_uniform.rvs() # self.net.node[i]['r'] = self.beta_dist.rvs() * self.net.node[i]['n'] # self.net.node[i]['c'] = self.rnd.uniform((self.net.node[i]['r']/2), min(self.net.node[i]['n'], (1-(self.net.node[i]['r']/2)))) # self.net.node[i]['invader'] = False # self.invaders.append(invader) self.net.nodes[basal]['r'] = 0.0 self._create_links_based_on_fundamental_niche() current_herbivores = 0 current_producers = 0 current_predators = 0 tls = self.net.get_trophic_levels() for k in tls.keys(): if tls[k] == 1: current_herbivores += 1 elif tls[k] == 0: current_producers += 1 elif tls[k] == 3: current_predators += 1 return self.net def _create_links_based_on_fundamental_niche(self, nodes_to_link=None): #based on the fundamental niche values obtained above we construct the network by adding #the corresponding links according to the species' niche and feeding range if nodes_to_link == None: nodes_to_link = set(self.net.nodes()) for i in self.net.nodes(): if self.net.nodes[i]['r'] == 0.0: continue r_lower_bound = self.net.nodes[i]['c'] - (self.net.nodes[i]['r'] / 2) r_upper_bound = self.net.nodes[i]['c'] + (self.net.nodes[i]['r'] / 2) for j in self.net.nodes(): if i not in nodes_to_link and j not in nodes_to_link: continue if self.net.nodes[j]['n'] >= r_lower_bound and self.net.nodes[ j]['n'] <= r_upper_bound: self.net.add_edge(j, i) #for disconnected or duplicated nodes disc_nodes = set() self_loops = set(nx.selfloop_edges(self.net)) for i in nodes_to_link: disconnected = False if self.net.degree(i) == 0: disconnected = True elif self.net.in_degree(i) == 1 and (i, i) in self_loops: # print 'producer with selfloop' if self.net.out_degree(i) > 1: self.net.remove_edge(i, i) else: disconnected = True attrs = self.net.nodes[i] self.net.remove_node(i) self.net.add_node(i, attr_dict=attrs) else: i_succs = set(self.net.successors(i)) i_predecs = set(self.net.predecessors(i)) for j in self.net.nodes(): j_succs = self.net.successors(j) j_predecs = self.net.predecessors(j) if i_succs == j_succs and i_predecs == j_predecs: disconnected = True attrs = self.net.nodes[i] self.net.remove_node(i) self.net.add_node(i, attr_dict=attrs) print('duplicated node') break #we reassign the fundamental niche values to nodes that are disconnected or duplicated if disconnected: self.net.nodes[i]['n'] = self.rnd_uniform.rvs() self.net.nodes[i]['r'] = self.beta_dist.rvs( ) * self.net.nodes[i]['n'] self.net.nodes[i]['c'] = self.rnd.uniform( self.net.nodes[i]['r'] / 2, self.net.nodes[i]['n']) disc_nodes.add(i) if len(disc_nodes) > 0: self._create_links_based_on_fundamental_niche(disc_nodes) return
tps = cumulative_sps_stats[sp]['tps'] if len(tps) == 0: mean_tps = 'N/A' sd_tps = 'N/A' else: mean_tps = sum(tps) / len(tps) sd_tps = 0.0 for n in tps: sd_tps += (n - mean_tps)**2 sd_tps = math.sqrt(sd_tps / len(tps)) out_row_species['mean_tp'] = mean_tps out_row_species['tp_sd'] = sd_tps out_row_species['individuals'] = series_counts[ITERATIONS][sp] out_row_species['immigrants'] = cumulative_sps_stats[sp]['immigrants'] out_row_species['born'] = cumulative_sps_stats[sp]['born'] out_row_species['dead'] = cumulative_sps_stats[sp]['dead'] out_species.writerow(out_row_species) file_species.close() stop_sim = datetime.now() elapsed_sim = stop_sim - start_sim print('time for simulation', elapsed_sim) print('S original =', net.order(), 'L original =', net.size(), 'C original =', net.connectance())