def setUp(self):
        super(TestObjectiveFunctionsExtended, self).setUp()
        self.partitions = []

        #        alternate with selfloop
        self.graph = nx.Graph()
        self.number_of_nodes = 10
        for i in range(self.number_of_nodes):
            self.graph.add_edge(i, (i + 1) % self.number_of_nodes)
        # beside complete circle add one edge to connect all blocks
        self.graph.add_edge(0, 2)
        #   include one self loop
        self.graph.add_edge(0, 0)
        self.partition = sbm.NxPartition(graph=self.graph,
                                         number_of_blocks=3,
                                         calculate_degree_of_blocks=True,
                                         save_neighbor_edges=True,
                                         save_neighbor_of_blocks=True)
        self._fixed_starting_point()

        self.partitions.append(self.partition)
        # generate some random graphs with increasing chance
        for i in range(8):
            graph = nx.gnp_random_graph(10, i * .1 + .1)
            partition = sbm.NxPartition(graph=graph,
                                        number_of_blocks=3,
                                        calculate_degree_of_blocks=True,
                                        save_neighbor_edges=True,
                                        save_neighbor_of_blocks=True)
            self.partitions.append(partition)
Exemple #2
0
    def setUp(self):
        self.graphs = [
            nx.Graph(),
            nx.Graph(),
            nx.Graph(),
            nx.Graph(),
            nx.Graph()
        ]
        nx.add_path(self.graphs[0], [0, 0, 1, 2, 3])
        nx.add_path(self.graphs[1], [0, 1, 2, 3, 0])
        nx.add_path(self.graphs[2], [0, 1, 2, 3, 0, 0])
        nx.add_path(self.graphs[4], [0, 1, 2, 3, 0, 4])
        self.graphs[3] = self.graphs[2].copy()
        self.graphs[3].add_edge(2, 2)

        self.partitions = []
        for graph in self.graphs:
            partition = sbm.NxPartition(graph=graph, number_of_blocks=2)
            self.partitions.append(partition)
            partition.set_from_representation(
                {node: node % partition.B
                 for node in graph})

        # information about graphs below
        self.likelihood = ModelLikelihoodOfFlatMicrocanonicalDegreeCorrectedSbm(
        )
Exemple #3
0
    def create_parameters_for_model_selection_function(
            self, graph, partition_representation):
        """
        Creates from the given information the parameters for the model selection function
        :param graph: graph which nodes are clustered
        :param partition_representation: dictionary containing the clustering of the nodes, with the nodes as key and
        the communities labeled starting from 0
        :type graph: nx.Graph
        :type partition_representation dict
        :return:
        """
        parameters = {"is_degree_corrected": self.is_degree_corrected}

        if self.function_needs_partition:
            parameters["partition"] = sbm.NxPartition(
                graph, representation=partition_representation)

        if self.function_needs_partition_representation:
            parameters["partition_representation"] = partition_representation

        if self.function_needs_number_of_nodes:
            parameters["number_of_nodes"] = len(graph.nodes())

        if self.function_needs_number_of_edges:
            parameters["number_of_edges"] = len(graph.edges())

        if self.function_needs_is_directed:
            parameters["is_directed"] = graph.is_directed()

        if self.additional_fixed_key_arguments is not None:
            parameters.update(**self.additional_fixed_key_arguments)

        return parameters
Exemple #4
0
    def test_cleanup_block_merges(self):
        """Test cleaning merges"""
        # prepare a bigger graph (10 nodes)
        self.graph.add_edges_from([(5, 6), (7, 8), (8, 9)])
        self.partition = sbm.NxPartition(graph=self.graph,
                                         number_of_blocks=2,
                                         calculate_degree_of_blocks=True,
                                         save_neighbor_edges=True,
                                         save_neighbor_of_blocks=True)
        self.inference = sbm.PeixotoInference(self.graph,
                                              self.objective_function,
                                              self.partition)

        # minimum move on (delta, block_1, block_2)
        merges_with_delta = [(0, 8, 4), (0, 1, 2), (0, 1, 0), (0, 5, 6),
                             (0, 2, 4)]
        result, new_block_number = self.inference._cleanup_merges(
            merges_with_delta)

        # no loop therefore decrease by length
        self.assertEqual(new_block_number, 5)
        # test if all higher blocks are shifted
        for i in range(new_block_number, 10):
            self.assertTrue(i in result)
            self.assertLess(result[i], new_block_number)
        # Check merges
        for block in [1, 2, 4, 8]:
            self.assertEqual(result[block], 0)

        self.assertEqual(result[5], result[6])

        # next try with some loops
        merges_with_delta = [(0, 8, 4), (0, 1, 2), (0, 1, 8), (0, 4, 2),
                             (0, 3, 6), (0, 6, 3)]
        result, new_block_number = self.inference._cleanup_merges(
            merges_with_delta)

        self.assertEqual(new_block_number, 6)
        # test if all higher blocks are shifted
        for i in range(new_block_number, 10):
            self.assertTrue(i in result)
            self.assertLess(result[i], new_block_number)
        # Check merges
        for block in [2, 4, 8]:
            self.assertEqual(result[block], 1)
        self.assertEqual(result[6], 3)

        # test right updating of observed
        merges_with_delta = [(0, 2, 1), (0, 3, 0), (0, 2, 3), (0, 5, 4),
                             (0, 6, 7), (0, 5, 6)]
        result, new_block_number = self.inference._cleanup_merges(
            merges_with_delta)
        self.assertEqual(new_block_number, 4)
        # test if all higher blocks are shifted
        for i in range(new_block_number, 10):
            self.assertTrue(i in result)
            self.assertLess(result[i], new_block_number)
    def setUp(self):
        #        basically we only set up the test with different graphs and
        #         after that the same tests as before apply
        super(TestObjectiveFunctionsDirected, self).setUp()
        self.partitions = []
        self.graph = nx.DiGraph()
        self.number_of_nodes = 10
        for i in range(self.number_of_nodes):
            self.graph.add_edge(i, (i + 1) % self.number_of_nodes)
        # beside complete circle add one edge to connect all blocks
        self.graph.add_edge(0, 2)
        # here first without selfloops and undirected
        self.partition = sbm.NxPartition(graph=self.graph,
                                         number_of_blocks=4,
                                         calculate_degree_of_blocks=True,
                                         save_neighbor_edges=True,
                                         save_neighbor_of_blocks=True)
        self._fixed_starting_point()
        self.partitions.append(self.partition)

        #        with selfloop
        self.graph = self.graph.copy()
        self.graph.add_edge(0, 0)
        self.partition = sbm.NxPartition(graph=self.graph,
                                         number_of_blocks=3,
                                         calculate_degree_of_blocks=True,
                                         save_neighbor_edges=True,
                                         save_neighbor_of_blocks=True)
        self._fixed_starting_point()
        self.partitions.append(self.partition)

        for i in range(1, 10):
            #            attention creates MultiDigraph
            graph = nx.scale_free_graph(i * 10 + 1)
            # at the moment algorithms can only handle DiGraphs therefore cast
            partition = sbm.NxPartition(graph=nx.DiGraph(graph),
                                        number_of_blocks=rd.randint(2, 9),
                                        calculate_degree_of_blocks=True,
                                        save_neighbor_edges=True,
                                        save_neighbor_of_blocks=True)
            self.partitions.append(partition)

        for objective_function in self.objective_functions:
            objective_function.is_directed = True
    def test_base_class(self):
        """Test correct mapping of functions and switch on is_directed"""
        objective_function = sbm.ObjectiveFunction(
            self.partition.is_graph_directed(),
            lambda x: "complete undirected", lambda x: "complete directed",
            lambda *args: "delta undirected", lambda *args: "delta directed")
        if self.partition.is_graph_directed():
            self.assertEqual(objective_function.calculate(self.partition),
                             "complete directed")
            self.assertEqual(
                objective_function.calculate_delta(self.partition, 0, 1),
                "delta directed")
        else:
            self.assertEqual(objective_function.calculate(self.partition),
                             "complete undirected")
            self.assertEqual(
                objective_function.calculate_delta(self.partition, 0, 1),
                "delta undirected")

        objective_function.is_directed = True
        digraph = nx.DiGraph()
        digraph.add_edge(0, 1)
        directed_partition = sbm.NxPartition(digraph, number_of_blocks=1)
        self.assertEqual(objective_function.calculate(directed_partition),
                         "complete directed")
        self.assertEqual(
            objective_function.calculate_delta(directed_partition, 0, 1),
            "delta directed")

        objective_function.is_directed = False
        graph = nx.Graph()
        graph.add_edge(0, 1)
        undirected_partition = sbm.NxPartition(graph, number_of_blocks=1)
        self.assertEqual(objective_function.calculate(undirected_partition),
                         "complete undirected")
        self.assertEqual(
            objective_function.calculate_delta(undirected_partition, 0, 1),
            "delta undirected")
Exemple #7
0
    def test_infer_stochastic_block_model(self):
        # dummy objective function
        objective_function = sbm.DegreeCorrectedUnnormalizedLogLikelyhood(
            is_directed=False)

        graph = nx.DiGraph()
        graph.add_edges_from([(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3),
                              (4, 5), (4, 6), (4, 7), (5, 6), (5, 7), (6, 7),
                              (0, 4)])
        graph[0][1]['weight'] = 20
        representation = {0: 0, 1: 0, 2: 0, 3: 0, 4: 1, 5: 1, 6: 1, 7: 1}
        partition = sbm.NxPartition(graph, 2, True, True, False, False, False,
                                    representation)
        x = sbm.SpectralInference(graph, objective_function, partition)
        a = x.infer_stochastic_block_model()
Exemple #8
0
    def setUp(self):
        self.graph = nx.DiGraph(nx.karate_club_graph())

        self.partition = sbm.NxPartition(graph=self.graph,
                                         number_of_blocks=2,
                                         calculate_degree_of_blocks=True,
                                         save_neighbor_edges=True,
                                         save_neighbor_of_blocks=True)

        self.objective_function = sbm.TraditionalUnnormalizedLogLikelyhood(
            is_directed=True)

        # set up -> worse enough random partition
        #  optimum by around -240 start at least below -260
        while self.objective_function.calculate(self.partition) > -260:
            self.partition.random_partition(number_of_blocks=2)
    def setUp(self):
        self.graph = nx.Graph()
        self.number_of_nodes = 10
        for i in range(self.number_of_nodes):
            self.graph.add_edge(i, (i + 1) % self.number_of_nodes)
        # beside complete circle add one edge to connect all blocks
        self.graph.add_edge(0, 2)
        # here first without selfloops and undirected
        self.partition = sbm.NxPartition(graph=self.graph,
                                         number_of_blocks=3,
                                         calculate_degree_of_blocks=True,
                                         save_neighbor_edges=True,
                                         save_neighbor_of_blocks=True)
        self._fixed_starting_point()

        self.objective_functions = []

        self.objective_functions.append(
            sbm.TraditionalUnnormalizedLogLikelyhood(is_directed=False))
        self.objective_functions.append(
            sbm.DegreeCorrectedUnnormalizedLogLikelyhood(is_directed=False))
        self.objective_functions.append(
            sbm.TraditionalMicrocanonicalEntropy(is_directed=False))
        self.objective_functions.append(
            sbm.TraditionalMicrocanonicalEntropyDense(is_directed=False))
        self.objective_functions.append(
            sbm.DegreeCorrectedMicrocanonicalEntropy(is_directed=False))
        self.objective_functions.append(
            sbm.IntegratedCompleteLikelihoodExactJeffrey(is_directed=False))
        self.objective_functions.append(
            sbm.IntegratedCompleteLikelihoodExactUniform(is_directed=False))
        self.objective_functions.append(
            sbm.NewmanReinertDegreeCorrected(is_directed=False))
        self.objective_functions.append(
            sbm.NewmanReinertDegreeCorrected(is_directed=False))
        self.objective_functions.append(
            sbm.NewmanReinertNonDegreeCorrected(is_directed=False))
        self.objective_functions.append(
            sbm.LogLikelihoodOfFlatMicrocanonicalNonDegreeCorrected(
                is_directed=False))
        self.objective_functions.append(
            sbm.LogLikelihoodOfFlatMicrocanonicalDegreeCorrectedUniform(
                is_directed=False))
        self.objective_functions.append(
            sbm.
            LogLikelihoodOfFlatMicrocanonicalDegreeCorrectedUniformHyperprior(
                is_directed=False))
Exemple #10
0
    def setUp(self):
        # first check probabilities of new block
        self.graph = nx.Graph()
        # create graph
        #  0 - 1
        # |  \ | /\ 4
        # 3 -  2
        self.graph.add_edges_from([(0, 1), (1, 2), (2, 3), (0, 2), (1, 4),
                                   (2, 4)])
        self.partition = sbm.NxPartition(graph=self.graph,
                                         number_of_blocks=2,
                                         calculate_degree_of_blocks=True,
                                         save_neighbor_edges=True,
                                         save_neighbor_of_blocks=True)

        self.objective_function = sbm.TraditionalUnnormalizedLogLikelyhood(
            is_directed=False)
        self.inference = sbm.PeixotoInference(self.graph,
                                              self.objective_function,
                                              self.partition)
        self.inference.epsilon = 0.0
    def test_empty_to_group(self):
        objective_function = self.objective_functions[0]

        graph = nx.complete_graph(5)
        if objective_function.is_directed:
            graph = nx.DiGraph(graph)
        partition = sbm.NxPartition(graph,
                                    representation={
                                        0: 2,
                                        1: 1,
                                        2: 0,
                                        3: 0,
                                        4: 0
                                    })
        partition.move_node(1, 0)

        precalc_info = partition.precalc_move((0, 2, 1), objective_function)
        for objective_function in self.objective_functions:
            objective_function.calculate_delta(partition, 2, 1, *precalc_info)

        # first find
        generator = test_ground.PlantedPartitionGenerator(
            4, 32, 0.9696969696969697, 0.0)
        graph, _, _ = generator.generate(directed=False, seed=0)
        if objective_function.is_directed:
            graph = nx.DiGraph(graph)

        partition = sbm.NxPartition(graph,
                                    representation={
                                        0: 2,
                                        1: 2,
                                        2: 2,
                                        3: 2,
                                        4: 2,
                                        5: 2,
                                        6: 2,
                                        7: 2,
                                        8: 2,
                                        9: 2,
                                        10: 2,
                                        11: 2,
                                        12: 2,
                                        13: 2,
                                        14: 2,
                                        15: 2,
                                        16: 2,
                                        17: 2,
                                        18: 2,
                                        19: 2,
                                        20: 2,
                                        21: 2,
                                        22: 2,
                                        23: 2,
                                        24: 2,
                                        25: 2,
                                        26: 2,
                                        27: 2,
                                        28: 2,
                                        29: 2,
                                        30: 2,
                                        31: 2,
                                        32: 3,
                                        33: 3,
                                        34: 3,
                                        35: 3,
                                        36: 3,
                                        37: 3,
                                        38: 3,
                                        39: 3,
                                        40: 3,
                                        41: 3,
                                        42: 3,
                                        43: 3,
                                        44: 3,
                                        45: 3,
                                        46: 3,
                                        47: 3,
                                        48: 3,
                                        49: 3,
                                        50: 3,
                                        51: 3,
                                        52: 3,
                                        53: 3,
                                        54: 3,
                                        55: 3,
                                        56: 3,
                                        57: 3,
                                        58: 3,
                                        59: 3,
                                        60: 3,
                                        61: 3,
                                        62: 3,
                                        63: 3,
                                        64: 2,
                                        65: 2,
                                        66: 2,
                                        67: 2,
                                        68: 2,
                                        69: 2,
                                        70: 2,
                                        71: 2,
                                        72: 2,
                                        73: 2,
                                        74: 2,
                                        75: 2,
                                        76: 2,
                                        77: 2,
                                        78: 2,
                                        79: 2,
                                        80: 2,
                                        81: 2,
                                        82: 2,
                                        83: 2,
                                        84: 2,
                                        85: 2,
                                        86: 2,
                                        87: 2,
                                        88: 2,
                                        89: 2,
                                        90: 2,
                                        91: 2,
                                        92: 2,
                                        93: 2,
                                        94: 2,
                                        95: 2,
                                        96: 0,
                                        97: 0,
                                        98: 0,
                                        99: 0,
                                        100: 0,
                                        101: 0,
                                        102: 0,
                                        103: 0,
                                        104: 0,
                                        105: 0,
                                        106: 0,
                                        107: 0,
                                        108: 0,
                                        109: 0,
                                        110: 0,
                                        111: 0,
                                        112: 0,
                                        113: 0,
                                        114: 0,
                                        115: 0,
                                        116: 0,
                                        117: 0,
                                        118: 0,
                                        119: 0,
                                        120: 0,
                                        121: 0,
                                        122: 0,
                                        123: 0,
                                        124: 0,
                                        125: 0,
                                        126: 0,
                                        127: 0
                                    })

        precalc_info = partition.precalc_move((0, 2, 1), objective_function)
        for objective_function in self.objective_functions:
            objective_function.calculate_delta(partition, 2, 1, *precalc_info)
Exemple #12
0
    def test_inference(self):
        graph = nx.Graph()
        graph.add_edges_from([(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6),
                              (0, 7), (0, 8), (0, 10), (0, 11), (0, 12),
                              (0, 13), (0, 17), (0, 19), (0, 21), (0, 31),
                              (1, 2), (1, 3),
                              (1, 7), (1, 13), (1, 17), (1, 19), (1, 21),
                              (1, 30), (2, 3), (2, 7), (2, 8), (2, 9), (2, 13),
                              (2, 27), (2, 28), (2, 32), (3, 7), (3, 12),
                              (3, 13), (4, 6), (4, 10), (5, 6), (5, 10),
                              (5, 16), (6, 16), (8, 30), (8, 32), (8, 33),
                              (9, 33), (13, 33), (14, 32), (14, 33), (15, 32),
                              (15, 33), (18, 32), (18, 33), (19, 33), (20, 32),
                              (20, 33), (22, 32), (22, 33), (23, 25), (23, 27),
                              (23, 29), (23, 32), (23, 33), (24, 25), (24, 27),
                              (24, 31), (25, 31), (26, 29), (26, 33), (27, 33),
                              (28, 31), (28, 33), (29, 32), (29, 33), (30, 32),
                              (30, 33), (31, 32), (31, 33), (32, 33)])

        partition = sbm.NxPartition(graph,
                                    representation={
                                        0: 1,
                                        1: 1,
                                        2: 1,
                                        3: 1,
                                        4: 0,
                                        5: 0,
                                        6: 1,
                                        7: 0,
                                        8: 0,
                                        9: 0,
                                        10: 1,
                                        11: 0,
                                        12: 0,
                                        13: 0,
                                        14: 0,
                                        15: 0,
                                        16: 1,
                                        17: 0,
                                        18: 0,
                                        19: 0,
                                        20: 0,
                                        21: 0,
                                        22: 0,
                                        23: 1,
                                        24: 1,
                                        25: 0,
                                        26: 1,
                                        27: 0,
                                        28: 0,
                                        29: 0,
                                        30: 1,
                                        31: 1,
                                        32: 1,
                                        33: 1
                                    })

        objective_function = sbm.DegreeCorrectedUnnormalizedLogLikelyhood(
            is_directed=False)

        inference = sbm.KerninghanLinInference(graph, objective_function,
                                               partition)

        inference.infer_stochastic_block_model()
Exemple #13
0
    def setUp(self):
        # unconnected example
        graph = nx.Graph()
        # create graph(s)
        #  0 - 1
        # 2 -  3 - 4
        # 6 - 5 -7
        # 8 - 9
        # |   |
        # 10 - 11
        # 12 - 13 (selfloop to 13)
        # 14 - 15 (selfloop) - 16 - 17 (selfloop) - 18
        # ensure that each node can be moved, i.e. in every block are at least 2 nodes
        graph.add_edges_from([(0, 1), (2, 3), (3, 4), (5, 6), (5, 7), (8, 9),
                              (9, 10), (10, 11), (11, 8), (12, 13), (13, 13),
                              (14, 15), (15, 15), (15, 16), (16, 17), (17, 17),
                              (17, 18)])
        self.partition = sbm.NxPartition(graph=graph,
                                         number_of_blocks=2,
                                         calculate_degree_of_blocks=True,
                                         save_neighbor_edges=True,
                                         save_neighbor_of_blocks=True,
                                         weighted_graph=False)

        # set defined block state
        for node in range(self.partition.get_number_of_nodes()):
            self.partition.move_node(node, node % 2)

        self.objective_function = ObjectiveFunctionDummy(is_directed=False)

        self.inference = sbm.MetropolisHastingInference(
            graph, self.objective_function, self.partition)

        # same with 3 blocks
        partition_3 = sbm.NxPartition(graph=graph,
                                      number_of_blocks=3,
                                      calculate_degree_of_blocks=True,
                                      save_neighbor_edges=True,
                                      save_neighbor_of_blocks=True,
                                      weighted_graph=False)
        # set defined block state
        for node in range(self.partition.get_number_of_nodes()):
            partition_3.move_node(node, node % 3)

        inference_3 = sbm.MetropolisHastingInference(graph,
                                                     self.objective_function,
                                                     partition_3)

        # create directed graph with the same examples like before,
        #  i.e. always insert both possible edges
        digraph = nx.DiGraph(graph)
        # add directed cycle
        # 19  -> 20 -> 21
        #  | <- - - - |
        digraph.add_edges_from([(19, 20), (20, 21), (21, 19)])

        self.dipartition = sbm.NxPartition(graph=digraph,
                                           number_of_blocks=2,
                                           calculate_degree_of_blocks=True,
                                           save_neighbor_edges=True,
                                           save_neighbor_of_blocks=True,
                                           weighted_graph=False)

        # set defined block state
        for node in range(self.dipartition.get_number_of_nodes()):
            self.dipartition.move_node(node, node % 2)

        self.di_inference = sbm.MetropolisHastingInference(
            digraph, self.objective_function, self.dipartition)

        dipartition_3 = sbm.NxPartition(graph=digraph,
                                        number_of_blocks=3,
                                        calculate_degree_of_blocks=True,
                                        save_neighbor_edges=True,
                                        save_neighbor_of_blocks=True,
                                        weighted_graph=False)
        # set defined block state
        for node in range(self.dipartition.get_number_of_nodes()):
            dipartition_3.move_node(node, node % 3)

        di_inference_3 = sbm.MetropolisHastingInference(
            digraph, self.objective_function, dipartition_3)

        self.test_cases = [
            (self.partition, self.inference),
            (partition_3, inference_3),
            (self.dipartition, self.di_inference),
            (dipartition_3, di_inference_3),
        ]