Esempio n. 1
0
def test_insertable1():
    c = CliqueTree()
    edges = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (3, 5), (6, 4),
             (1, 3), (1, 5), (1, 4), (5, 7), (2, 5), (1, 6), (2, 4), (1, 7),
             (4, 7), (2, 7), (3, 7), (2, 6), (3, 6)]
    solutions = [
        frozenset([]),
        frozenset([(1, 3)]),
        frozenset([(1, 3), (2, 4)]),
        frozenset([(1, 3), (2, 4), (3, 5)]),
        frozenset([(4, 6), (1, 3), (2, 4), (3, 5)]),
        frozenset([(4, 6), (5, 7), (1, 3), (2, 4), (3, 5)]),
        frozenset([(1, 3), (4, 6), (5, 7), (3, 6), (2, 5), (2, 4)]),
        frozenset([(4, 7), (1, 3), (5, 7), (3, 6), (2, 5), (2, 4)]),
        frozenset([(4, 7), (5, 7), (1, 4), (1, 5), (3, 6), (2, 5), (2, 4)]),
        frozenset([(2, 5), (5, 7), (3, 6), (1, 4), (4, 7)]),
        frozenset([(4, 7), (5, 7), (1, 6), (3, 6), (2, 5), (2, 4)]),
        frozenset([(2, 5), (1, 6), (2, 4), (3, 6), (4, 7)]),
        frozenset([(4, 7), (1, 6), (2, 4), (3, 6)]),
        frozenset([(4, 7), (2, 4), (3, 6), (1, 7)]),
        frozenset([(4, 7), (2, 6), (3, 6), (1, 7)]),
        frozenset([(4, 7), (2, 6), (3, 6)]),
        frozenset([(2, 7), (3, 7), (2, 6), (3, 6)]),
        frozenset([(3, 7), (2, 6)]),
        frozenset([(2, 6), (3, 6)]),
        frozenset([(3, 6)]),
        frozenset([])
    ]

    for edge, insertable in zip(edges, solutions):
        c.add_edge(*edge)
        assert c.insertable == insertable
Esempio n. 2
0
def test_insertable1():
    c = CliqueTree()
    edges = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (3, 5), (6, 4),
             (1, 3), (1, 5), (1, 4), (5, 7), (2, 5), (1, 6), (2, 4), (1, 7),
             (4, 7), (2, 7), (3, 7), (2, 6), (3, 6)]
    solutions = [frozenset([]), frozenset([(1, 3)]), frozenset([(1, 3), (2, 4)]),
                 frozenset([(1, 3), (2, 4), (3, 5)]),
                 frozenset([(4, 6), (1, 3), (2, 4), (3, 5)]),
                 frozenset([(4, 6), (5, 7), (1, 3), (2, 4), (3, 5)]),
                 frozenset([(1, 3), (4, 6), (5, 7), (3, 6), (2, 5), (2, 4)]),
                 frozenset([(4, 7), (1, 3), (5, 7), (3, 6), (2, 5), (2, 4)]),
                 frozenset([(4, 7), (5, 7), (1, 4), (1, 5), (3, 6), (2, 5), (2, 4)]),
                 frozenset([(2, 5), (5, 7), (3, 6), (1, 4), (4, 7)]),
                 frozenset([(4, 7), (5, 7), (1, 6), (3, 6), (2, 5), (2, 4)]),
                 frozenset([(2, 5), (1, 6), (2, 4), (3, 6), (4, 7)]),
                 frozenset([(4, 7), (1, 6), (2, 4), (3, 6)]),
                 frozenset([(4, 7), (2, 4), (3, 6), (1, 7)]),
                 frozenset([(4, 7), (2, 6), (3, 6), (1, 7)]),
                 frozenset([(4, 7), (2, 6), (3, 6)]),
                 frozenset([(2, 7), (3, 7), (2, 6), (3, 6)]),
                 frozenset([(3, 7), (2, 6)]),
                 frozenset([(2, 6), (3, 6)]),
                 frozenset([(3, 6)]),
                 frozenset([])]

    for edge, insertable in zip(edges, solutions):
        c.add_edge(*edge)
        assert c.insertable == insertable
Esempio n. 3
0
def test_update():
    c = CliqueTree()
    edges = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (3, 5), (6, 4),
             (1, 3), (1, 5), (1, 4), (5, 7), (2, 5), (1, 6), (2, 4), (1, 7),
             (4, 7), (2, 7), (3, 7), (2, 6), (3, 6)]
    solutions = [frozenset([]), frozenset([(1, 3)]), frozenset([(1, 3), (2, 4)]),
                 frozenset([(1, 3), (2, 4), (3, 5)]),
                 frozenset([(4, 6), (1, 3), (2, 4), (3, 5)]),
                 frozenset([(4, 6), (5, 7), (1, 3), (2, 4), (3, 5)]),
                 frozenset([(1, 3), (4, 6), (5, 7), (3, 6), (2, 5), (2, 4)]),
                 frozenset([(4, 7), (1, 3), (5, 7), (3, 6), (2, 5), (2, 4)]),
                 frozenset([(4, 7), (5, 7), (1, 4), (1, 5), (3, 6), (2, 5), (2, 4)]),
                 frozenset([(2, 5), (5, 7), (3, 6), (1, 4), (4, 7)]),
                 frozenset([(4, 7), (5, 7), (1, 6), (3, 6), (2, 5), (2, 4)]),
                 frozenset([(2, 5), (1, 6), (2, 4), (3, 6), (4, 7)]),
                 frozenset([(4, 7), (1, 6), (2, 4), (3, 6)]),
                 frozenset([(4, 7), (2, 4), (3, 6), (1, 7)]),
                 frozenset([(4, 7), (2, 6), (3, 6), (1, 7)]),
                 frozenset([(4, 7), (2, 6), (3, 6)]),
                 frozenset([(2, 7), (3, 7), (2, 6), (3, 6)]),
                 frozenset([(3, 7), (2, 6)]),
                 frozenset([(2, 6), (3, 6)]),
                 frozenset([(3, 6)]),
                 frozenset([])]

    for edge, insertable in zip(edges[:10], solutions[:10]):
        c.add_edge(*edge)
    c.add_edge(*edges[10], update_insertable=False)
    assert len(c.insertable) == 0
    c.update_insertable(7, stop_at=1)
    assert len(c.insertable) == 1
    assert len(c.insertable.intersection(solutions[10])) == 1
Esempio n. 4
0
def test_update():
    c = CliqueTree()
    edges = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (3, 5), (6, 4),
             (1, 3), (1, 5), (1, 4), (5, 7), (2, 5), (1, 6), (2, 4), (1, 7),
             (4, 7), (2, 7), (3, 7), (2, 6), (3, 6)]
    solutions = [
        frozenset([]),
        frozenset([(1, 3)]),
        frozenset([(1, 3), (2, 4)]),
        frozenset([(1, 3), (2, 4), (3, 5)]),
        frozenset([(4, 6), (1, 3), (2, 4), (3, 5)]),
        frozenset([(4, 6), (5, 7), (1, 3), (2, 4), (3, 5)]),
        frozenset([(1, 3), (4, 6), (5, 7), (3, 6), (2, 5), (2, 4)]),
        frozenset([(4, 7), (1, 3), (5, 7), (3, 6), (2, 5), (2, 4)]),
        frozenset([(4, 7), (5, 7), (1, 4), (1, 5), (3, 6), (2, 5), (2, 4)]),
        frozenset([(2, 5), (5, 7), (3, 6), (1, 4), (4, 7)]),
        frozenset([(4, 7), (5, 7), (1, 6), (3, 6), (2, 5), (2, 4)]),
        frozenset([(2, 5), (1, 6), (2, 4), (3, 6), (4, 7)]),
        frozenset([(4, 7), (1, 6), (2, 4), (3, 6)]),
        frozenset([(4, 7), (2, 4), (3, 6), (1, 7)]),
        frozenset([(4, 7), (2, 6), (3, 6), (1, 7)]),
        frozenset([(4, 7), (2, 6), (3, 6)]),
        frozenset([(2, 7), (3, 7), (2, 6), (3, 6)]),
        frozenset([(3, 7), (2, 6)]),
        frozenset([(2, 6), (3, 6)]),
        frozenset([(3, 6)]),
        frozenset([])
    ]

    for edge, insertable in zip(edges[:10], solutions[:10]):
        c.add_edge(*edge)
    c.add_edge(*edges[10], update_insertable=False)
    assert len(c.insertable) == 0
    c.update_insertable(7, stop_at=1)
    assert len(c.insertable) == 1
    assert len(c.insertable.intersection(solutions[10])) == 1
Esempio n. 5
0
    def greedy_learn(self, k_max=np.inf, time_limit=np.inf):
        """An algorithm for learning kDGs using a greedy hill-climbing approach. The code is influenced by the design
        of the hill climbing approach used in the pgmpy package
        (https://pgmpy.org/_modules/pgmpy/estimators/HillClimbSearch.html). However, we only consider edge additions
        which maintain chordality. The learned models are placed in the undirected and directed attributes.
        :param k_max (int): The maximal clique size of the graph to learn
        :param time_limit: The time limit of the search
        """
        # build the mst spanning tree
        initial_graph = CliqueTree()
        start = time.time()
        # Generate MST
        if nx.classes.function.is_empty(self.maxtree):
            self.mst()

        for edge in list(self.get_model_mst().edges()):
            initial_graph.add_edge(edge[0], edge[1])

        # the best bn learned so far is the MST
        self.to_bn(use_mst=True)
        best_bn = self.get_model_directed()
        # Flag which controls when the algorithm finishes
        add_edge = True
        if k_max > 2:
            while add_edge:
                running_time = time.time() - start
                best_score_delta = (0, None)
                if running_time > time_limit:
                    break
                current_bn = best_bn.copy()
                add_edge = False
                # make a list of all possible edges that could be added to the graph
                diff = initial_graph.insertable
                for edge in diff:
                    running_time = time.time() - start
                    if running_time > time_limit:
                        break
                    # add an edge to the graph
                    initial_graph.add_edge(edge[0], edge[1])
                    cliques = initial_graph.nodes_in_clique
                    # check if the graph is chordal and has the right clique number
                    if DecomposableModel.get_clique_num(cliques) <= k_max:
                        # get the score of the new graph
                        greedy_bn, greedy_score_delta = DecomposableModel.add_edge_to_bn(edge, current_bn.copy(),
                                                                                         self.bdeu)
                        # is the score better than previous graphs?
                        if greedy_score_delta > best_score_delta[0]:
                            # If we add can add an edge, the algorithm should continue looking for more edges
                            add_edge = True
                            best_score_delta = (greedy_score_delta, edge)
                            best_bn = greedy_bn

                    # after we check the candidate edge, remove it from the graph and keep looking
                    initial_graph.remove_edge(edge[0], edge[1])

                # make the new initial graph the best graph from the previous search
                if add_edge:
                    initial_graph.add_edge(best_score_delta[1][0], best_score_delta[1][1])

        self.undirected = initial_graph.G
        self.directed = best_bn