Commit e8a2652e authored by Yoann Dufresne's avatar Yoann Dufresne
Browse files

deconvolution start for small instances ok

parent ff1c07d8
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
import sys import sys
import networkx as nx import networkx as nx
import itertools
import sys
...@@ -13,7 +12,25 @@ def deconvolve(G,node): ...@@ -13,7 +12,25 @@ def deconvolve(G,node):
# Extract neighbors from the graph # Extract neighbors from the graph
G_neighbors = nx.Graph(G.subgraph(neighbors)) G_neighbors = nx.Graph(G.subgraph(neighbors))
get_communities(G_neighbors) communities = get_communities(G_neighbors)
# Continue only if something need to be splited.
if len(communities) == 1:
return
# Split communities
for idx, community in enumerate(communities):
# Add community center
node_name = f"{node}_{idx}"
G.add_node(node_name)
# Add links from the center to the community
for neighbor in community:
G.add_edge(node_name, neighbor)
# Remove old node
G.remove_node(node)
print("splitted into", len(communities), "parts\n")
def get_communities(G): def get_communities(G):
...@@ -41,9 +58,18 @@ def get_communities(G): ...@@ -41,9 +58,18 @@ def get_communities(G):
d_graph = compute_d_graph(clq1, clq2, G) d_graph = compute_d_graph(clq1, clq2, G)
if d_graph != None: if d_graph != None:
candidate_d_graphs.append(d_graph) candidate_d_graphs.append(d_graph)
# print(clq1, clq2, is_d_graph(clq1, clq2, G))
# Extract communites from all the possible d-graphes in the neighborood. # Extract communites from all the possible d-graphes in the neighborood.
# This is a minimal covering d_graph algorithm.
minimal_d_graphes = filter_d_graphs(candidate_d_graphs)
# If no community detected, return one big.
if len(minimal_d_graphes) == 0:
return [list(G.nodes())]
# TODO : !!! Concatenation not possible if the same node can be in both side
communites = [d_graph[0]+d_graph[1] for d_graph in minimal_d_graphes]
return communites
""" This function take two cliques in the graph G and try to find if they are 2 halfes of a d-graph. """ This function take two cliques in the graph G and try to find if they are 2 halfes of a d-graph.
...@@ -63,6 +89,11 @@ def compute_d_graph(clq1, clq2, G): ...@@ -63,6 +89,11 @@ def compute_d_graph(clq1, clq2, G):
arities2 = {name:0 for name in clq2} arities2 = {name:0 for name in clq2}
sum_edges = 0 sum_edges = 0
# TODO : Remove this part and improve the detection
if len(clq1) != len(clq2):
return None
# /TODO
min_clq_size = min(len(clq1), len(clq2)) min_clq_size = min(len(clq1), len(clq2))
# Compute link arities # Compute link arities
...@@ -80,14 +111,56 @@ def compute_d_graph(clq1, clq2, G): ...@@ -80,14 +111,56 @@ def compute_d_graph(clq1, clq2, G):
if sum_edges < min_clq_size * (min_clq_size-1) / 2: if sum_edges < min_clq_size * (min_clq_size-1) / 2:
return None return None
print(clq1, clq2) # print(clq1, clq2)
print(arities1, arities2, "\n") # print(arities1, arities2, "\n")
# order lists
lst1 = [key for key, value in sorted(arities1.items(), key=lambda tup: -tup[1])] lst1 = [key for key, value in sorted(arities1.items(), key=lambda tup: -tup[1])]
lst2 = [key for key, value in sorted(arities2.items(), key=lambda tup: -tup[1])] lst2 = [key for key, value in sorted(arities2.items(), key=lambda tup: -tup[1])]
# print(min_clq_size)
# print(lst1, "\n", lst2, "\n")
# Return the 2 halves of the d-graph
return lst1, lst2 return lst1, lst2
""" Filter the candiates regarding their compatibilities
"""
def filter_d_graphs(candidates):
# Count for each node the number of their apparition
counts = {}
for d_graph in candidates:
for node in itertools.chain(d_graph[0], d_graph[1]):
if not node in counts:
counts[node] = 0
counts[node] += 1
# take d_graphes with nodes that appears only once
filtered = []
selected = {node:False for node in counts.keys()}
for d_graph in candidates:
for node in itertools.chain(d_graph[0], d_graph[1]):
if counts[node] == 1:
# Add the d_graph to the selection
filtered.append(d_graph)
# register selection of the nodes
for node in itertools.chain(d_graph[0], d_graph[1]):
selected[node] = True
# Over for this d-graph
break
# TODO : improve performances when there are no uniq solution
for val in selected.values():
if not val:
# print(min(counts.values()), counts)
return []
# print(len(filtered))
return filtered
def main(): def main():
# Parsing the input file # Parsing the input file
...@@ -102,9 +175,11 @@ def main(): ...@@ -102,9 +175,11 @@ def main():
g_nodes = list(G.nodes()) g_nodes = list(G.nodes())
for node in g_nodes: for node in g_nodes:
deconvolve(G,node) deconvolve(G,node)
exit() # exit()
print(len(g_nodes), "->", len(list(G.nodes())))
# nx.write_graphml(G,sys.argv[1]+".deconvolved.graphml") nx.write_graphml(G,sys.argv[1]+".deconvolved.graphml")
if __name__ == "__main__": if __name__ == "__main__":
main() main()
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment