Skip to content

Commit

Permalink
Merge pull request #131 from GiulioRossetti/antichain
Browse files Browse the repository at this point in the history
🆕 Siblinarity Antichain algorithm
  • Loading branch information
GiulioRossetti authored Sep 17, 2020
2 parents 9116f59 + 7b7c8dc commit b29c767
Show file tree
Hide file tree
Showing 8 changed files with 842 additions and 117 deletions.
1 change: 0 additions & 1 deletion cdlib/algorithms/attribute_clustering.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ def ilouvain(g_original, labels, id):
1. Combe D., Largeron C., Géry M., Egyed-Zsigmond E. "I-Louvain: An Attributed Graph Clustering Method". <https://link.springer.com/chapter/10.1007/978-3-319-24465-5_16> In: Fromont E., De Bie T., van Leeuwen M. (eds) Advances in Intelligent Data Analysis XIV. IDA (2015). Lecture Notes in Computer Science, vol 9385. Springer, Cham
"""


g = convert_graph_formats(g_original, nx.Graph)
nx.set_node_attributes(g, labels)
id = dict()
Expand Down
135 changes: 102 additions & 33 deletions cdlib/algorithms/crisp_partition.py

Large diffs are not rendered by default.

77 changes: 6 additions & 71 deletions cdlib/algorithms/internal/ILouvain.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
#!/usr/bin/python

from __future__ import division

#from pprint import pprint

#import argparse
import numpy as np
#from scipy.spatial.distance import pdist, squareform
import os.path

# -*- coding: utf-8 -*-
"""
This module implements community detection.
"""
__all__ = ["partition_at_level", "modularity", "best_partition", "generate_dendogram", "induced_graph"]
__author__ = """Thomas Aynaud (thomas.aynaud@lip6.fr)"""

__author__ = ["Thomas Aynaud (thomas.aynaud@lip6.fr)"]
# Copyright (C) 2009 by
# Thomas Aynaud <thomas.aynaud@lip6.fr>
# All rights reserved.
Expand All @@ -23,7 +14,7 @@
import networkx as nx


class ML2:
class ML2(object):
__MIN = 0.000001
__PASS_MAX = -1
LOGOPERATIONS = False
Expand All @@ -49,9 +40,6 @@ def __init__(self, graph, attributes, authorIndex):
self.status_list = list()

def critereCombinaison(self):
# if(args.verbose):
# print("Mod1: " + str(self.__modularity(self.statusTab[0])))
# print("Mod2: " + str(self.__modularity(self.statusTab[1])))
return (self.__modularity(self.statusTab[0]) + self.__modularity(self.statusTab[1])) / 2.

def findPartition(self):
Expand All @@ -75,11 +63,6 @@ def findPartition(self):
self.__one_level(giniMatrix=giniMatrix)
new_mod = self.critereCombinaison()
if new_mod - mod < self.__MIN:
# if(args.verbose):
# print("modularities")
# print(self.__modularity(self.statusTab[0]))
# print(self.__modularity(self.statusTab[1]))
# print("Modularity Final: " + str(self.__modularity(self.statusTab[1]) + self.__modularity(self.statusTab[0])))
break
partition, bijection = self.__renumber()

Expand All @@ -103,17 +86,6 @@ def findPartition(self):
partition[node] = dendogram[index][community]

return partition
# for elem, part in sorted(partition.iteritems()) :
# if(args.verbose):
# print(str(self.authorIndex[elem]) + " " + str(part) + " " + str(self.attributes[self.authorIndex[elem]]))
# else:
# out = str(self.authorIndex[elem]) + " " + str(part)
# if(args.multipleDataset != None):
# f = open(args.dataset + "_" + str(curDatasetIdx) + ".2ModLouvain",'a')
# else:
# f = open(args.dataset + ".2ModLouvain",'a')
# f.write(out + "\n")
# f.close()

def dist(self, v1, v2):
attrV1 = self.attributes[v1]
Expand Down Expand Up @@ -317,7 +289,7 @@ def __modularity(self, status):
return result


class Status:
class Status(object):
"""
To handle several data in one struct.
Could be replaced by named tuple, but don't want to depend on python 2.6
Expand Down Expand Up @@ -351,16 +323,13 @@ def initAttribStatus(self, graph, authorIndex, attributes):

variance = {}
for node in sorted(graph.nodes()):
distanceToCenterOfGravity = 0.
for attrId, attrValue in meanVector.items():
variance[attrId] = variance.get(attrId, 0.) + (
(attrValue - attributes[authorIndex[node]].get(attrId, 0.)) ** 2)
inertieTot = 0.
for v in variance.values():
inertieTot += (v / N)

# if(args.verbose):
# print("# Total inertia:", inertieTot)
self.total_weight = (0.0 - inertieTot)

for node in sorted(graph.nodes()):
Expand Down Expand Up @@ -426,7 +395,7 @@ def loadDataset(path):
graph = nx.Graph()

# Read the graph
if (not os.path.isfile(path + ".edgeList")):
if not os.path.isfile(path + ".edgeList"):
print("Error: file '" + path + ".edgeList' not found")
exit(-1)
with open(path + ".edgeList") as f:
Expand All @@ -442,7 +411,7 @@ def loadDataset(path):
for n in graph:
attributes[n] = {}

if (not os.path.isfile(path + ".attributes")):
if not os.path.isfile(path + ".attributes"):
print("Error: file '" + path + ".attributes' not found")
exit(-1)

Expand All @@ -468,37 +437,3 @@ def loadDataset(path):
os.remove(path + ".2ModLouvain")

return graph, attributes, authorIndex


def readToyGraph():
graph = nx.Graph()
graph.add_node("a")
graph.add_node("b")
graph.add_node("c")
graph.add_node("d")
graph.add_node("e")
graph.add_edge("a", "b")
graph.add_edge("b", "c")
graph.add_edge("c", "d")
graph.add_edge("d", "e")
graph.add_edge("a", "e")
graph.add_edge("b", "e")
graph.add_edge("c", "e")
graph.add_edge("b", "d")
graph.add_edge("a", "c")
graph.add_edge("a", "d")

authorIndex = {}
authorIndex["a"] = 0
authorIndex["b"] = 1
authorIndex["c"] = 2
authorIndex["d"] = 3
authorIndex["e"] = 4

attributes = {
0: {0: 2., 1: 4},
1: {0: 8., 1: 1},
2: {0: 7., 1: 5},
3: {0: 12., 1: 6},
4: {0: 1., 1: 4}}
return graph, attributes, authorIndex
Loading

0 comments on commit b29c767

Please sign in to comment.