def create_true_graph(self): final_workflow = Graph() final_workflow.add_vertex(self.network_size) i = 0 while max([ shortest_distance(final_workflow, x, (self.network_size - 1)) for x in final_workflow.get_vertices() ]) > 100: i += 1 if i > 10000: raise RuntimeError('generating graph took too long') valid_source_nodes = [ index for index, in_degree in enumerate( final_workflow.get_in_degrees( final_workflow.get_vertices())) if ((in_degree > 0 or index < self.input_nodes) and index < (self.network_size - 1)) ] valid_to_nodes = [ index for index in final_workflow.get_vertices() if (index >= self.input_nodes) ] new_edge = final_workflow.add_edge( self.np_random.choice(valid_source_nodes), self.np_random.choice(valid_to_nodes)) if not is_DAG(final_workflow): final_workflow.remove_edge(new_edge) observation = adjacency(final_workflow).toarray().astype(int) if not self.observation_space.contains(observation): final_workflow.remove_edge(new_edge) return final_workflow
def insert_clique_subgraph(a: gt.Graph, n_nodes, att_dist, att_name, target_solutions): q_nodes = np.random.choice(a.get_vertices(), n_nodes, replace=False) a_to_q = {} q_to_a = {} nodes_list = [] edges_list = [] for i, n in enumerate(q_nodes): a_to_q[n] = i # Maps from archive node to T. q_to_a[i] = n # Maps from T to archive node nodes_list.append(n) for i in range(n_nodes): for j in range(i + 1, n_nodes): n1 = q_to_a[i] n2 = q_to_a[j] # e = a.edge(n1, n2) # if e: # edges_list.append(e) # continue e = a.add_edge(n1, n2) edges_list.append(e) add_single_edge_attribute(a, e, att_dist, att_name) new_target = {'nodes': nodes_list, 'edges': edges_list, 'isClutter': False} target_solutions.append(new_target) return create_q_graph(a, q_nodes)
def mdst_score(t: gt.Graph, n_idx, e_idx, used_stuff): n_att_name = next(n_idx.keys()) e_att_name = next(e_idx.keys()) percent_left = vp_map(t, 'PercentLeft', 'float') v_attribute_p = vp_map(t, n_att_name, 'int') e_attribute_p = ep_map(t, e_att_name, 'int') # Choose a vertex with input degree = 0 root = np.where(t.get_in_degrees(t.get_vertices()) == 0)[0] if root in used_stuff: percent_left[root] = 1 else: percent_left[root] = len( n_idx[n_att_name][v_attribute_p[root]]) / n_idx[n_att_name]['size'] total_score = percent_left[root] for e in gt_s.bfs_iterator(t, root): start_node, end_node = e if e in used_stuff: edge_score = 1 end_node_score = 1 else: edge_score = len(e_idx[e_att_name][ e_attribute_p[e]]) / e_idx[e_att_name]['size'] if end_node in used_stuff: end_node_score = 1 else: end_node_score = len(n_idx[n_att_name][ v_attribute_p[end_node]]) / n_idx[n_att_name]['size'] percent_left[ end_node] = end_node_score * percent_left[start_node] * edge_score total_score += percent_left[end_node] return total_score
def deg_attack(g: GT.Graph): return IdNodes(g.get_total_degrees(g.get_vertices()))
def plot_degree_distribution(graph: Graph, file_name): degrees = graph.get_total_degrees(graph.get_vertices()) plt.hist(degrees) plt.savefig(file_name) plt.clf()
def passing_volume(g: Graph): vs = g.get_vertices() return np.asarray(g.get_total_degrees(vs, g.edge_properties['weight']))
class graphRL(gym.Env): """ will have fixed action space, but not all actions are valid within each state step function should have a function that tests if the chosen action is valid the observation returned will be the graph_tool graph, but the state will just be the adjacency matrix (? maybe, currently have obs space as the matrix) maybe step function just alters the given graph """ metadata = {'render.modes': ['human', 'graph', 'interactive']} def __init__(self, network_size=10, input_nodes=3): self.network_size = network_size self.input_nodes = input_nodes self.graph = Graph() self.graph.set_fast_edge_removal(True) self.graph.add_vertex(self.network_size) self.action_space = spaces.Tuple((spaces.Discrete(self.network_size), spaces.Discrete(self.network_size))) self.observation_space = spaces.MultiDiscrete( np.full((self.network_size, self.network_size), 2)) self.time_step = 0 self.observation = adjacency(self.graph).toarray().astype(int) self.seed_value = self.seed() self.true_graph = self.create_true_graph() self.reset() def create_true_graph(self): final_workflow = Graph() final_workflow.add_vertex(self.network_size) i = 0 while max([ shortest_distance(final_workflow, x, (self.network_size - 1)) for x in final_workflow.get_vertices() ]) > 100: i += 1 if i > 10000: raise RuntimeError('generating graph took too long') valid_source_nodes = [ index for index, in_degree in enumerate( final_workflow.get_in_degrees( final_workflow.get_vertices())) if ((in_degree > 0 or index < self.input_nodes) and index < (self.network_size - 1)) ] valid_to_nodes = [ index for index in final_workflow.get_vertices() if (index >= self.input_nodes) ] new_edge = final_workflow.add_edge( self.np_random.choice(valid_source_nodes), self.np_random.choice(valid_to_nodes)) if not is_DAG(final_workflow): final_workflow.remove_edge(new_edge) observation = adjacency(final_workflow).toarray().astype(int) if not self.observation_space.contains(observation): final_workflow.remove_edge(new_edge) return final_workflow def render(self, mode='human'): if mode == 'graph': # return graphtools graph object return self.graph elif mode == 'interactive': interactive_window(self.graph) elif mode == 'human': filename = "./renders/render" + str(self.time_step) + ".png" graph_draw(self.graph, vertex_text=self.graph.vertex_index, vertex_font_size=18, output_size=(1000, 1000), output=filename) def render_truth(self, mode='human'): if mode == 'graph': # return graphtools graph object return self.true_graph elif mode == 'interactive': interactive_window(self.true_graph) elif mode == 'human': filename = "./renders/TrueGraphSeed" + str( self.seed_value) + ".png" graph_draw(self.true_graph, vertex_text=self.true_graph.vertex_index, vertex_font_size=18, output_size=(1000, 1000), output=filename) def seed(self, seed=None): self.np_random, seed = seeding.np_random(seed) return [seed] def step(self, action): done = 0 reward = 0 assert self.action_space.contains(action) valid_source_nodes = [ index for index, in_degree in enumerate( self.graph.get_in_degrees(self.graph.get_vertices())) if ((in_degree > 0 or index < self.input_nodes) and index < (self.network_size - 1)) ] if action[0] not in valid_source_nodes: raise ValueError('this action does not have a valid from node') new_edge = self.graph.add_edge(action[0], action[1]) if not is_DAG(self.graph): self.graph.remove_edge(new_edge) raise ValueError('this action violates the DAG property') self.observation = adjacency(self.graph).toarray().astype(int) if not self.observation_space.contains(self.observation): print(self.observation) self.graph.remove_edge(new_edge) self.observation = adjacency(self.graph).toarray().astype(int) raise ValueError('this action makes a duplicate edge') if isomorphism(self.graph, self.true_graph): reward = 1 done = 1 self.time_step += 1 return self.observation, reward, done, {"time_step": self.time_step} def reset(self): self.graph.clear_edges() self.time_step = 0 self.observation = adjacency(self.graph).toarray() return self.observation