def build_advice(net, configs): if (configs['advice_creation'] == 'once'): #assumes no growth advice_upon = configs['advice_upon'] biased = util.boool(configs['biased']) bias_on = str(configs['bias_on']) pressure = math.ceil((float(configs['PT_pairs_dict'][1][0]) / 100.0)) samples, sample_size = None, None if (advice_upon == 'nodes'): samples = net.nodes() sample_size = int(pressure * len(net.nodes())) elif (advice_upon == 'edges'): samples = [[str(node_i), str(node_j)] for node_i in net.nodes() for node_j in net.nodes()] # all possible edges #samples = net.edges() sample_size = int( pressure * len(net.edges())) #sample size based on all existing edges advice = util.advice(net, util.sample_p_elements(samples, sample_size), biased, advice_upon, bias_on) else: advice = None #will generate during reduction each time instead return advice
def distrib_workers(population, gen, worker_pop_size, num_survive, advice, BD_table, biases, configs): num_workers = int(configs['number_of_workers']) output_dir = configs['output_directory'] debug = util.boool(configs['debug']) if (debug == True): # sequential debug for w in range(1, num_workers + 1): dump_file = output_dir + "to_workers/" + str(gen) + "/" + str(w) seed = population[0].copy() randSeeds = os.urandom(sysRand().randint(0, 1000000)) worker_args = [w, seed, worker_pop_size, min(worker_pop_size, num_survive), randSeeds, advice, BD_table, biases, configs] with open(dump_file, 'wb') as file: pickle.dump(worker_args, file) # pool.map_async(minion.evolve_minion, (dump_file,)) minion.evolve_minion(dump_file, gen, w, output_dir) sleep(.0001) else: for w in range(1, num_workers + 1): dump_file = output_dir + "/to_workers/" + str(gen) + "/" + str(w) seed = population[w % num_survive].copy() randSeeds = os.urandom(sysRand().randint(0, 1000000)) assert (seed != population[w % num_survive]) worker_args = [w, seed, worker_pop_size, min(worker_pop_size, num_survive), randSeeds, advice, BD_table, biases, configs] with open(dump_file, 'wb') as file: pickle.dump(worker_args, file) del population if (debug == True): util.cluster_print(output_dir, "debug is ON")
def add_this_edge(net, configs, node1=None, node2=None, sign=None, random_direction=False, given_bias=None): reverse_allowed = util.boool(configs['reverse_edges_allowed']) bias_on = configs['bias_on'] node1_set, node2_set = node1, node2 #to save their states if not sign: sign = rd.randint(0, 1) if (sign == 0): sign = -1 pre_size = post_size = len(net.edges()) i = 0 while (pre_size == post_size): # ensure that net adds if not node1_set and node1_set != 0: node = rd.sample(net.nodes(), 1) node1 = node[0] if not node2_set and node2_set != 0: node2 = node1 while (node2 == node1): node2 = rd.sample(net.nodes(), 1) node2 = node2[0] if random_direction: #chance to swap nodes 1 & 2 if (rd.random() < .5): node3 = node2 node2 = node1 node1 = node3 if reverse_allowed: if not net.has_edge(node1, node2): net.add_edge(node1, node2, sign=sign) else: if not net.has_edge(node1, node2) and not net.has_edge( node2, node1): net.add_edge(node1, node2, sign=sign) post_size = len(net.edges()) i += 1 if (i == 10000000): util.cluster_print( configs['output_directory'], "\n\n\nWARNING mutate.add_this_edge() is looping a lot.\nNode1 = " + str(node1_set) + ", Node2 = " + str(node2_set) + "\n\n\n") if (bias and bias_on == 'edges'): bias.assign_an_edge_bias(net, [node1, node2], configs['bias_distribution'], given_bias=given_bias)
def add_edges(net, num_add, configs, biases=None): #if (num_add == 0): print("WARNING in mutate(): 0 nodes added in add_nodes\n") if (biases): assert (len(biases) == num_add) assert ( util.boool(configs['biased']) ) # note that the converse may not be true: net_generator will mutate first and add biases later for j in range(num_add): if (biases): add_this_edge(net, configs, given_bias=biases[j]) else: add_this_edge(net, configs) if util.boool(configs['single_cc']): net_undir = net.to_undirected() num_cc = nx.number_connected_components(net_undir) if (num_cc != 1): ensure_single_cc(net, configs)
def final_master_info(population, gen, configs): output_dir = configs['output_directory'] nx.write_edgelist(population[0].net, output_dir+"/nets/"+str(gen)) pickle_file = output_dir + "/pickle_nets/" + str(gen) + "_pickle" with open(pickle_file, 'wb') as file: pickle.dump(population[0].net, file) popn_data(population, output_dir, gen) #draw_nets.basic(population, output_dir, total_gens) if util.boool(configs['biased']): util.cluster_print(output_dir,"Pickling biases.") bias.pickle_bias(population[0].net, output_dir+"/bias", configs['bias_on'])
def rewire(net, num_rewire, bias, bias_on, dirr, configs): single_cc = util.boool(configs['single_cc']) edge_node_ratio = float(configs['edge_to_node_ratio']) for i in range(num_rewire): assert (edge_node_ratio != 1 or not single_cc) # this is an unlikely scenario, but bias tracking requires rm, then add # which triggers multiple connected components if edge_node_ratio = 1 orig_biases = rm_edges(net, 1, configs) add_this_edge(net, configs, given_bias=orig_biases[0])
def ensure_single_cc(net, configs, node1=None, node2=None, sign_orig=None, bias_orig=None): #rewires [node1, node2] at the expense of a random, non deg1 edge single_cc = util.boool(configs['single_cc']) if single_cc: if node1 or node1 == 0: assert (node2 or node2 == 0) elif not node1: assert not (node2) net_undir = net.to_undirected() num_cc = nx.number_connected_components(net_undir) if (num_cc != 1): #rm_edge() will recursively check #COULD CAUSE AN ERR if not node1 and node1 != 0: components = list(nx.connected_components(net_undir)) c1 = components[0] node1 = rd.sample(c1, 1) node1 = node1[0] if not node2 and node2 != 0: c2 = components[1] node2 = rd.sample(c2, 1) node2 = node2[0] if not sign_orig: sign_orig = rd.randint(0, 1) if (sign_orig == 0): sign_orig = -1 add_this_edge(net, configs, node1=node1, node2=node2, sign=sign_orig, given_bias=bias_orig) rm_edges(net, 1, configs) #calls ensure_single_cc() at end net_undir = net.to_undirected() num_cc = nx.number_connected_components(net_undir) assert (num_cc == 1)
def add_nodes(net, num_add, configs, biases=None): biased = util.boool(configs['biased']) bias_on = configs['bias_on'] if biases: assert (biased) # note that the converse may not be true: net_generator will mutate first and add biases later # ADD NODE for i in range(num_add): pre_size = post_size = len(net.nodes()) while (pre_size == post_size): new_node = rd.randint( 0, len(net.nodes()) * 1000) # hope to hit number that doesn't already exist if new_node not in net.nodes(): #could be slowing things down... net.add_node(new_node) post_size = len(net.nodes()) assert (pre_size < post_size) if biases and bias_on == 'nodes': bias.assign_a_node_bias(net, new_node, configs['bias_distribution'], given_bias=biases[i]) # ADD EDGE TO NEW NODE TO KEEP CONNECTED if biases and bias_on == 'edges': add_this_edge(net, configs, node1=new_node, random_direction=True, given_bias=biases[i]) else: add_this_edge(net, configs, node1=new_node, random_direction=True) # MAINTAIN NODE_EDGE RATIO num_edge_add = int( num_add * float(configs['edge_to_node_ratio'])) - num_add if biases and bias_on == 'edges': assert (len(biases) == num_edge_add + num_add) add_edges(net, num_edge_add, configs, biases=biases[num_add:]) else: add_edges(net, num_edge_add, configs)
def rm_edges(net, num_rm, configs): # constraints: doesn't leave 0 deg edges or mult connected components biased = util.boool(configs['biased']) bias_on = configs['bias_on'] orig_biases = [] for j in range(num_rm): pre_size = post_size = len(net.edges()) i = 0 while (pre_size == post_size): edge = rd.sample(net.edges(), 1) edge = edge[0] # don't allow 0 deg edges while ((net.in_degree(edge[0]) + net.out_degree(edge[0]) == 1) or (net.in_degree(edge[1]) + net.out_degree(edge[1]) == 1)): edge = rd.sample(net.edges(), 1) edge = edge[0] sign_orig = net[edge[0]][edge[1]]['sign'] if biased and bias_on == 'edges': bias_orig = net[edge[0]][edge[1]]['bias'] else: bias_orig = None orig_biases.append(bias_orig) net.remove_edge(edge[0], edge[1]) post_size = len(net.edges()) i += 1 if (i == 10000000): util.cluster_print( configs['output_directory'], "WARNING mutate.rm_edges() is looping a lot.\n") ensure_single_cc(net, configs, node1=edge[0], node2=edge[1], sign_orig=sign_orig, bias_orig=bias_orig) return orig_biases
def evolve_master(configs): # get configs num_workers = int(configs['number_of_workers']) output_dir = configs['output_directory'] worker_pop_size = int(configs['num_worker_nets']) fitness_direction = str(configs['fitness_direction']) biased = util.boool(configs['biased']) num_sims = int(configs['num_sims']) run_data = init_run(configs) if not run_data: return #for ex if run already finished population, gen, size, advice, BD_table, num_survive, keep_running = run_data while keep_running: t_start = time.time() pop_size, num_survive = curr_gen_params(size, num_survive, configs) output.master_info(population, gen, size, pop_size, num_survive, advice, BD_table, configs) write_mpi_info(output_dir, gen) if biased: biases = bias.gen_biases(configs) #all nets must have same bias to have comparable fitness else: biases = None distrib_workers(population, gen, worker_pop_size, num_survive, advice, BD_table, biases, configs) report_timing(t_start, gen, output_dir) population = watch(configs, gen, num_workers, output_dir, num_survive, fitness_direction) size = len(population[0].net.nodes()) gen += 1 keep_running = util.test_stop_condition(size, gen, configs) with open(output_dir + "/progress.txt", 'w') as out: out.write("Done") output.final_master_info(population, gen, configs) del_mpi_dirs(output_dir) util.cluster_print(output_dir,"Evolution finished, generating images.") if (num_sims == 1): plot_nets.single_run_plots(output_dir) util.cluster_print(output_dir,"Master finished config file.\n")
def init_population(init_type, start_size, pop_size, configs): sign_edges_needed = True edge_node_ratio = float(configs['edge_to_node_ratio']) num_edges = int(start_size*edge_node_ratio) #print("net_generator.init_population(): num edges = " + str(num_edges)) if (init_type == 'shell'): population = [Net(nx.DiGraph(), i) for i in range(pop_size)] #change to generate, based on start_size elif (init_type == 'erdos-renyi'): num_cc = 2 num_tries = 0 while(num_cc != 1): num_tries += 1 init_net = (nx.erdos_renyi_graph(start_size,.035, directed=True, seed=None)) num_added = 0 for node in init_net.nodes(): if (init_net.degree(node) == 0): pre_edges = len(init_net.edges()) num_added += 1 sign = sysRand().randint(0, 1) if (sign == 0): sign = -1 node2 = node while (node2 == node): node2 = sysRand().sample(init_net.nodes(), 1) node2 = node2[0] if (sysRand().random() < .5): init_net.add_edge(node, node2, sign=sign) else: init_net.add_edge(node2, node, sign=sign) assert (len(init_net.edges()) > pre_edges) else: if (init_net.in_edges(node) + init_net.out_edges(node) == 0): print("ERROR in net_generator(): hit a 0 deg node that is unrecognized.") net_undir = init_net.to_undirected() num_cc = nx.number_connected_components(net_undir) print("Number of added edges to avoid 0 degree = " + str(num_added) + ", num attempts to create suitable net = " + str(num_cc) + ".\n") population = [Net(init_net.copy(), i) for i in range(pop_size)] elif (init_type == 'empty'): population = [Net(nx.empty_graph(start_size, create_using=nx.DiGraph()), i) for i in range(pop_size)] elif (init_type == 'complete'): #crazy high run time due to about n^n edges population = [Net(nx.complete_graph(start_size, create_using=nx.DiGraph()), i) for i in range(pop_size)] elif (init_type == 'cycle'): population = [Net(nx.cycle_graph(start_size, create_using=nx.DiGraph()), i) for i in range(pop_size)] elif (init_type == 'star'): population = [Net(nx.star_graph(start_size-1), i) for i in range(pop_size)] custom_to_directed(population) elif (init_type == 'v sparse erdos-renyi'): num_cc = 2 num_tries = 0 while(num_cc != 1): num_tries += 1 init_net = (nx.erdos_renyi_graph(start_size,.002, directed=True, seed=None)) num_added = 0 for node in init_net.nodes(): if (init_net.degree(node) == 0): pre_edges = len(init_net.edges()) num_added += 1 sign = sysRand().randint(0, 1) if (sign == 0): sign = -1 node2 = node while (node2 == node): node2 = sysRand().sample(init_net.nodes(), 1) node2 = node2[0] if (sysRand().random() < .5): init_net.add_edge(node, node2, sign=sign) else: init_net.add_edge(node2, node, sign=sign) assert (len(init_net.edges()) > pre_edges) else: if (init_net.in_edges(node) + init_net.out_edges(node) == 0): print("ERROR in net_generator(): hit a 0 deg node that is unrecognized.") net_undir = init_net.to_undirected() num_cc = nx.number_connected_components(net_undir) print("Number of added edges to avoid 0 degree = " + str(num_added) + ", num attempts to create suitable net = " + str(num_cc) + ".\n") population = [Net(init_net.copy(), i) for i in range(pop_size)] elif (init_type == 'scale-free'): # curr does not work, since can't go to undirected for output population = [Net(nx.scale_free_graph(start_size, beta=.7, gamma=.15, alpha=.15),i) for i in range(pop_size)] elif (init_type == 'barabasi-albert 2'): population = [Net(nx.barabasi_albert_graph(start_size, 2),i) for i in range(pop_size)] custom_to_directed(population) elif (init_type == 'barabasi-albert 1'): population = [Net(nx.barabasi_albert_graph(start_size, 1),i) for i in range(pop_size)] custom_to_directed(population) elif (init_type == 'double cycle'): #double cycle population = [Net(nx.cycle_graph(start_size, create_using=nx.DiGraph()), i) for i in range(pop_size)] double_edges(population) elif (init_type == 'double star'): #double star population = [Net(nx.star_graph(start_size-1), i) for i in range(pop_size)] custom_to_directed(population) double_edges(population) elif (init_type == 'exponential'): #may be a bit slow init_net = Net(nx.cycle_graph(start_size, create_using=nx.DiGraph()),0) double_edges([init_net]) sign_edges([init_net]) sign_edges_needed = False num_rewire = start_size*10 mutate.rewire(init_net.net, num_rewire) population = [Net(init_net.net.copy(), i) for i in range(pop_size)] assert(population[0] != population[1] and population[0].net != population[1].net) elif (init_type == "vinayagam"): population = [Net(init.load_network(configs), i) for i in range(pop_size)] elif (init_type == "load"): population = [Net(nx.read_edgelist(configs['network_file'], nodetype=int,create_using=nx.DiGraph()), i) for i in range(pop_size)] elif (init_type == "pickle load"): pickled_net = pickle.load(configs['network_file']) population = [Net(pickled_net.copy(), i) for i in range(pop_size)] sign_edges_needed=False elif (init_type == 'All Leaves'): population = [Net(nx.configuration_model([1 for e in range(start_size)]),i) for i in range(pop_size)] elif (init_type == 'All 2s'): population = [Net(nx.configuration_model([2 for e in range(start_size)]),i) for i in range(pop_size)] elif (init_type == 'All 3s'): population = [Net(nx.configuration_model([3 for e in range(start_size)]),i) for i in range(pop_size)] elif (init_type == 'random'): if (start_size <= 20): init_net = nx.empty_graph(start_size, create_using=nx.DiGraph()) num_add = int(edge_node_ratio*start_size) mutate.add_edges(init_net, num_add, configs) else: #otherwise rewire till connected is intractable, grow without selection instead init_net = nx.empty_graph(8, create_using=nx.DiGraph()) num_add = int(edge_node_ratio*8) mutate.add_edges(init_net, num_add, configs) mutate.add_nodes(init_net, start_size-8, configs) if (len(init_net.edges()) == num_edges+1): mutate.rm_edges(init_net, 1, configs) mutate.ensure_single_cc(init_net, configs) assert(len(init_net.edges()) == num_edges) assert(len(init_net.nodes()) == start_size) population = [Net(init_net.copy(), i) for i in range(pop_size)] else: print("ERROR in master.gen_init_population(): unknown init_type.") return if (sign_edges_needed == True): sign_edges(population) if util.boool(configs['biased']): if (configs['bias_on'] == 'nodes'): bias.assign_node_bias(population, configs['bias_distribution']) elif (configs['bias_on'] == 'edges'): bias.assign_edge_bias(population, configs['bias_distribution']) else: print("ERROR in net_generator(): unknown bias_on: " + str (configs['bias_on'])) return population
def pressurize(configs, Net, instance_file_name, advice, BD_table): # configs: pressure = math.ceil((float(configs['pressure']) / 100.0)) sampling_rounds_multiplier = float(configs['sampling_rounds_multiplier'] ) #FRACTION of curr number of EDGES if (util.is_it_none(configs['sampling_rounds_max']) == None): max_sampling_rounds = None else: max_sampling_rounds = int(configs['sampling_rounds_max']) knapsack_solver = cdll.LoadLibrary(configs['KP_solver_binary']) advice_upon = configs['advice_upon'] use_kp = util.boool(configs['use_knapsack']) leaf_metric = str(configs['leaf_metric']) leaf_pow = float(configs['leaf_power']) hub_metric = str(configs['hub_metric']) fitness_operator = str(configs['fitness_operation']) edge_state = str(configs['edge_state']) biased = util.boool(configs['biased']) scale_node_fitness = util.boool(configs['scale_node_fitness']) net = Net.net #not great syntax, but Net is an individual in a population, whereas net is it's graph representation #num_samples_relative = min(max_sampling_rounds, len(net.nodes()) * sampling_rounds) num_samples_relative = max( 1, int(len(net.edges()) * sampling_rounds_multiplier)) if (max_sampling_rounds): num_samples_relative = min(num_samples_relative, max_sampling_rounds) if (advice_upon == 'nodes'): pressure_relative = int(pressure * len(net.nodes())) elif (advice_upon == 'edges'): pressure_relative = int(pressure * len(net.edges())) else: print("ERROR in pressurize(): unknown advice_upon: " + str(advice_upon)) return if (use_kp == 'True' or use_kp == True): leaf_fitness, hub_fitness, solo_fitness = 0, 0, 0 node_data.reset_fitness(net) #not actually used when kp = True node_data.reset_BDs(net) kp_instances = reducer.reverse_reduction(net, pressure_relative, num_samples_relative, advice, configs) if (instance_file_name != None): open(instance_file_name, 'w') for kp in kp_instances: a_result = solver.solve_knapsack(kp, knapsack_solver) inst_solo_fitness, inst_leaf_fitness, inst_hub_fitness = fitness.kp_instance_properties( a_result, leaf_metric, leaf_pow, hub_metric, fitness_operator, net, instance_file_name) leaf_fitness += inst_leaf_fitness hub_fitness += inst_hub_fitness solo_fitness += inst_solo_fitness leaf_fitness /= num_samples_relative hub_fitness /= num_samples_relative solo_fitness /= num_samples_relative Net.fitness, Net.leaf_fitness, Net.hub_fitness = solo_fitness, leaf_fitness, hub_fitness elif (use_kp == 'False' or use_kp == False): # assumes 100% pressure if (edge_state == 'probabilistic'): assert (not biased or not configs['bias_on'] == 'nodes') fitness_score = probabilistic_entropy.calc_fitness( net, BD_table, configs) elif (edge_state == 'experience'): node_data.reset_fitness(net) for i in range(num_samples_relative): node_data.reset_BDs(net) reducer.exp_BDs(net, configs) fitness.node_fitness(net, leaf_metric) fitness.node_normz(net, num_samples_relative) fitness_score = fitness.node_product(net, scale_node_fitness) else: print("ERROR in pressurize: Unknown edge state " + str(edge_state)) return Net.fitness = fitness_score else: print("ERROR in pressurize(): unknown use_knapsack config: " + str(use_kp))
def calc_fitness(net, BD_table, configs): # also uses log-likelihood normz biased = util.boool(configs['biased']) bias_on = configs['bias_on'] leaf_metric = configs['leaf_metric'] bias_distrib = configs['bias_distribution'] directed = util.boool(configs['directed']) pressure = float(float(configs['pressure']) / float(100)) pressure_on = configs['pressure_on'] auto_self_loops = util.boool(configs['auto_self_loops']) assert (not biased or not bias_distrib) #not ready to handle local bias on edges # fitness_score = 1 fitness_score = 0 if not directed: #not biased or not bias_distrib: #ie no local bias if False: #pressure is curr handled in BD_table building, before: not pressure==1 if pressure_on == 'edges': pressure_relative = int(len(net.edges()) * pressure) all_edges = net.edges() rd.shuffle(all_edges) pressured_edges = all_edges[:pressure_relative] for node in net.nodes(): effective_node_deg = 1 assert (len(net.edges(node)) == net.in_degree(node) + net.out_degree(node)) for edge in net.edges(node): if edge in pressured_edges: effective_node_deg += 1 deg_fitness = BD_table[effective_node_deg] if (deg_fitness != 0): fitness_score += deg_fitness else: assert (pressure_on == 'nodes') # either only pressurized nodes are evaluated in fitness function # or only edges between two pressurized nodes are evaluated # curr the later pressure_relative = int(len(net.nodes()) * pressure) all_nodes = net.nodes() rd.shuffle(all_nodes) pressured_nodes = all_nodes[:pressure_relative] for node in pressured_nodes: effective_node_deg = 1 assert (len(net.edges(node)) == net.in_degree(node) + net.out_degree(node)) for edge in net.edges(node): if (edge[0] == node and edge[1] in pressured_nodes ) or (edge[1] == node and edge[0] in pressured_nodes): effective_node_deg += 1 deg_fitness = BD_table[effective_node_deg] if (deg_fitness != 0): fitness_score += deg_fitness else: #degrees = list(net.degree().values()) if auto_self_loops: degrees = [ net.in_degree(node) + net.out_degree(node) + 1 for node in net.nodes() ] #making sure... else: degrees = [ net.in_degree(node) + net.out_degree(node) for node in net.nodes() ] # making sure... degs, freqs = np.unique(degrees, return_counts=True) tot = float(sum(freqs)) #freqs = [(f / tot) * 100 for f in freqs] for i in range(len(degs)): deg = degs[i] deg_fitness = BD_table[deg] #already log-scaled # fitness_score *= math.pow(deg_fitness,freqs[i]) #as per node product rule if (deg_fitness != 0): fitness_score += freqs[i] * deg_fitness else: assert (pressure == 1 and not auto_self_loops) #not ready yet node_degs = [[net.in_degree(node), net.out_degree(node)] for node in net.nodes()] for node_deg in node_degs: in_deg, out_deg = node_deg[0], node_deg[1] fitness_score += BD_table[in_deg][out_deg] ''' else: #TODO: fix dis later for n in net.nodes(): deg = net.in_degree(n) + net.out_degree(n) p = net.node[n]['bias'] node_fitness = 0 for B in range(deg+1): D = deg - B prBD = (math.factorial(B + D) / (math.factorial(B) * math.factorial(D))) * math.pow(p, B) * math.pow(1 - p, D) assert (prBD >= 0 and prBD <= 1) fitBD = l_fitness.node_score(leaf_metric, B, D) node_fitness += prBD * fitBD if (node_fitness != 0): node_fitness = math.log(node_fitness, 2) #log likelihood normz fitness_score += node_fitness ''' return fitness_score
def build_BD_table(configs, max_deg=100): # assumes no conservation score and bernouille pr distribution # incld log-normz directed = util.boool(configs['directed']) leaf_metric = configs['leaf_metric'] biased = util.boool(configs['biased']) global_edge_bias = float(configs['global_edge_bias']) pressure = float(float(configs['pressure']) / float(100)) pressure_on = configs['pressure_on'] if biased: global_edge_bias = float(global_edge_bias) p = .5 + global_edge_bias assert (p > 0 and p < 1) else: p = .5 if not directed: if pressure == 1: BD_table = [None for d in range(max_deg)] for d in range(max_deg): deg_fitness = 0 for B in range(d + 1): D = d - B prBD = bin_pr(B + D, B, p) assert (prBD >= 0 and prBD <= 1) fitBD = l_fitness.node_score(leaf_metric, B, D) deg_fitness += prBD * fitBD if (deg_fitness != 0): deg_fitness = math.log(deg_fitness, 2) #log likelihood normz BD_table[d] = deg_fitness else: #first build BD_table as if pressure==1 assert (pressure_on == 'edges' ) #otherwise not sure how to implement base_BD_table = [None for d in range(max_deg)] for d in range(max_deg): deg_fitness = 0 for B in range(d + 1): D = d - B prBD = bin_pr(B + D, B, p) assert (prBD >= 0 and prBD <= 1) fitBD = l_fitness.node_score(leaf_metric, B, D) deg_fitness += prBD * fitBD if (deg_fitness != 0): deg_fitness = math.log(deg_fitness, 2) # log likelihood normz base_BD_table[d] = deg_fitness BD_table = [0 for d in range(max_deg)] for d in range(max_deg): for d_pressured in range(d + 1): pr_d_pressured = bin_pr(d, d_pressured, pressure) BD_table[d] += pr_d_pressured * base_BD_table[d_pressured] else: #DIRECTED assert (pressure == 1) #not ready yet BD_table = [[0 for i in range(max_deg)] for j in range(max_deg)] for in_deg in range(max_deg): for out_deg in range(max_deg): for Bin in range(in_deg + 1): Din = in_deg - Bin prBDin = (math.factorial(Bin + Din) / (math.factorial(Bin) * math.factorial(Din)) ) * math.pow(p, Bin) * math.pow(1 - p, Din) assert (prBDin >= 0 and prBDin <= 1) for Bout in range(out_deg + 1): Dout = out_deg - Bout prBDout = (math.factorial(Bout + Dout) / (math.factorial(Bout) * math.factorial(Dout))) * math.pow( p, Bout) * math.pow(1 - p, Dout) assert (prBDout >= 0 and prBDout <= 1) fitBD = l_fitness.directed_node_score( leaf_metric, Bin, Bout, Din, Dout) BD_table[in_deg][ out_deg] += prBDin * prBDout * fitBD #i think... for i in range(max_deg): for o in range(max_deg): if (BD_table[i][o] > 0): BD_table[i][o] = math.log(BD_table[i][o], 2) # log likelihood normz else: assert (BD_table[i][o] > -.2) #allow rounding diff BD_table[i][o] = 0 return BD_table