From 0fdad62fb844bea22929efbc8317ec14108b6fb2 Mon Sep 17 00:00:00 2001 From: ilya Date: Thu, 7 Nov 2024 13:40:33 -0800 Subject: [PATCH 1/4] sample probabilities first implementation --- src/esu.py | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/esu.py b/src/esu.py index 11e8563..1354b25 100644 --- a/src/esu.py +++ b/src/esu.py @@ -8,23 +8,27 @@ """ import networkx as nx +import random class ESU: def __init__(self, G: nx.Graph): self.G = G - def enumerate_subgraphs(self, size: int): + #currently does not allow for motif size over 10 because of default sample probability. should be fixed + def enumerate_subgraphs(self, size: int, sample_probability: list[float] = [1,1,1,1,1,1,1,1,1,1]): """ Enumerates all unique subgraphs of a given motif size from the input\ graph using the ESU algorithm. - Translated for networkx from https://github.com/IlyaVasUW/NEMO_SUITE/ + Translated and improved for networkx from https://github.com/IlyaVasUW/NEMO_SUITE/ """ subgraph_list = [] nodes = self.G.nodes() node_visited = set() - for node in nodes: + sample_neighbors = self.eliminate_percentage(nodes, sample_probability[0]) + + for node in sample_neighbors: neighbor_set = set(self.get_right_neighbors(node)) node_list = [node] node_visited.add(node) @@ -32,7 +36,7 @@ def enumerate_subgraphs(self, size: int): return subgraph_list - def esu_recursive_helper(self, size: int, neighbors: set, node_list: list, subgraph_list: list, nodes_visited: set): + def esu_recursive_helper(self, size: int, neighbors: set, node_list: list, subgraph_list: list, nodes_visited: set, sample_probability: list[float]): if size == 1: subgraph_list.append(self.G.subgraph(node_list.copy())) return @@ -40,12 +44,14 @@ def esu_recursive_helper(self, size: int, neighbors: set, node_list: list, subgr if len(neighbors) == 0: return - for node in neighbors: + sample_neighbors = self.eliminate_percentage(neighbors, sample_probability[len(node_list)]) + + for node in sample_neighbors: node_list.append(node) nodes_visited.add(node) next_neighbors = set() - for neighbor in neighbors: + for neighbor in sample_neighbors: if neighbor not in nodes_visited: next_neighbors.add(neighbor) for neighbor in self.G.neighbors(node): @@ -70,3 +76,15 @@ def get_right_neighbors(self, node): right_hand_neighbors.append(n) return iter(right_hand_neighbors) + + #Removes a given percentage of elements from a list randomly. + def eliminate_percentage(set: set, probability: float): + num_to_remove = int(len(set) * probability) + indices_to_remove = random.sample(range(len(set)), num_to_remove) + + # Remove elements in reverse order to avoid index issues + for i in sorted(indices_to_remove, reverse=True): + set.pop(i) + + return set + From b3a764efedada6eb6efb74cd6903e2adf7461952 Mon Sep 17 00:00:00 2001 From: ilya Date: Thu, 7 Nov 2024 14:07:52 -0800 Subject: [PATCH 2/4] sample probability now running --- src/esu.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/esu.py b/src/esu.py index 1354b25..dfc0864 100644 --- a/src/esu.py +++ b/src/esu.py @@ -26,17 +26,17 @@ def enumerate_subgraphs(self, size: int, sample_probability: list[float] = [1,1, nodes = self.G.nodes() node_visited = set() - sample_neighbors = self.eliminate_percentage(nodes, sample_probability[0]) + sample_neighbors = self.eliminate_percentage(list(nodes), sample_probability[0]) for node in sample_neighbors: neighbor_set = set(self.get_right_neighbors(node)) node_list = [node] node_visited.add(node) - self.esu_recursive_helper(size, neighbor_set, node_list, subgraph_list, node_visited) + self.esu_recursive_helper(size, neighbor_set, node_list, subgraph_list, node_visited, sample_probability) return subgraph_list - def esu_recursive_helper(self, size: int, neighbors: set, node_list: list, subgraph_list: list, nodes_visited: set, sample_probability: list[float]): + def esu_recursive_helper(self, size: int, neighbors: set, node_list: list, subgraph_list: list, nodes_visited: set, sample_probability: list[float]): if size == 1: subgraph_list.append(self.G.subgraph(node_list.copy())) return @@ -44,7 +44,7 @@ def esu_recursive_helper(self, size: int, neighbors: set, node_list: list, subgr if len(neighbors) == 0: return - sample_neighbors = self.eliminate_percentage(neighbors, sample_probability[len(node_list)]) + sample_neighbors = self.eliminate_percentage(list(neighbors), sample_probability[len(node_list)]) for node in sample_neighbors: node_list.append(node) @@ -58,7 +58,7 @@ def esu_recursive_helper(self, size: int, neighbors: set, node_list: list, subgr if neighbor not in nodes_visited: next_neighbors.add(neighbor) - self.esu_recursive_helper(size - 1, next_neighbors, node_list, subgraph_list, nodes_visited) + self.esu_recursive_helper(size - 1, next_neighbors, node_list, subgraph_list, nodes_visited, sample_probability) if len(node_list) > 0: node_list.pop() @@ -78,13 +78,14 @@ def get_right_neighbors(self, node): return iter(right_hand_neighbors) #Removes a given percentage of elements from a list randomly. - def eliminate_percentage(set: set, probability: float): - num_to_remove = int(len(set) * probability) - indices_to_remove = random.sample(range(len(set)), num_to_remove) + #KEEPS PRECENTAGE INPUT. REMOVES 1 - PRECENTAGE + def eliminate_percentage(self, collection, probability: float): + num_to_remove = int(len(collection) * (1-probability)) + indices_to_remove = random.sample(range(len(collection)), num_to_remove) # Remove elements in reverse order to avoid index issues for i in sorted(indices_to_remove, reverse=True): - set.pop(i) + collection.pop(i) - return set + return collection From feb2de1cc440af7f8976d65a221f77180705540a Mon Sep 17 00:00:00 2001 From: ilya Date: Thu, 7 Nov 2024 14:16:05 -0800 Subject: [PATCH 3/4] need website implementation to use sample probabilities --- src/graph_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/graph_utils.py b/src/graph_utils.py index 1ec6a9e..89c093a 100644 --- a/src/graph_utils.py +++ b/src/graph_utils.py @@ -83,7 +83,7 @@ def draw_graph(self): def draw_subgraph(self, motif_size: int): output_dir = "drawings/subgraphs" esu = ESU(self.G) - esu_list = esu.enumerate_subgraphs(motif_size) # FIXME: 3 is default motif size + esu_list = esu.enumerate_subgraphs(motif_size) for i, subgraph in enumerate(esu_list): if self.graph_type == "Directed": @@ -102,6 +102,6 @@ def draw_subgraph(self, motif_size: int): with open(file_name, "r") as f: html = f.read() - st.markdown(f"### Subgraph {labelGraph(subgraph, self.graph_type)}") + st.markdown(f"### Subgraph {i}: {labelGraph(subgraph, self.graph_type)}") components.html(html, height=600, scrolling=True) return From 43862532c941016682635d69d7d8ff77bafcbd42 Mon Sep 17 00:00:00 2001 From: ilya Date: Wed, 13 Nov 2024 15:02:45 -0800 Subject: [PATCH 4/4] quick fix to neighbors visited --- src/esu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/esu.py b/src/esu.py index dfc0864..3ee88f9 100644 --- a/src/esu.py +++ b/src/esu.py @@ -51,7 +51,7 @@ def esu_recursive_helper(self, size: int, neighbors: set, node_list: list, subgr nodes_visited.add(node) next_neighbors = set() - for neighbor in sample_neighbors: + for neighbor in neighbors: if neighbor not in nodes_visited: next_neighbors.add(neighbor) for neighbor in self.G.neighbors(node):