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

deconvolution start for small instances ok

parent ff1c07d8
......@@ -2,8 +2,7 @@
import sys
import networkx as nx
import sys
import itertools
......@@ -13,7 +12,25 @@ def deconvolve(G,node):
# Extract neighbors from the graph
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):
......@@ -41,9 +58,18 @@ def get_communities(G):
d_graph = compute_d_graph(clq1, clq2, G)
if d_graph != None:
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.
# 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.
......@@ -63,6 +89,11 @@ def compute_d_graph(clq1, clq2, G):
arities2 = {name:0 for name in clq2}
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))
# Compute link arities
......@@ -80,14 +111,56 @@ def compute_d_graph(clq1, clq2, G):
if sum_edges < min_clq_size * (min_clq_size-1) / 2:
return None
print(clq1, clq2)
print(arities1, arities2, "\n")
# print(clq1, clq2)
# print(arities1, arities2, "\n")
# order lists
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])]
# print(min_clq_size)
# print(lst1, "\n", lst2, "\n")
# Return the 2 halves of the d-graph
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():
# Parsing the input file
......@@ -102,9 +175,11 @@ def main():
g_nodes = list(G.nodes())
for node in g_nodes:
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__":
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