Beispiel #1
0
new_scc_new_edge.append(((4, 0)))
new_scc_correct_value.append(True)
new_scc_finishing_time.append(None)

# exists causal splitter
exists_causal_splitter_qblocks = []
exists_causal_splitter_result_map = []

# 0
g0 = nx.DiGraph()
g0.add_nodes_from(range(6))
g0.add_edges_from([(5, 0), (5, 5), (6, 5), (0, 3), (1, 3), (2, 4), (3, 3),
                   (4, 3)])
ip0 = [(0, 1, 2), (3, 4), (5, ), (6, )]

vertexes0, qblocks0 = decorate_nx_graph(g0, ip0)
decorate_bispy_graph(vertexes0, ip0)
exists_causal_splitter_qblocks.append(qblocks0)
# integer tuples are the indexes of the blocks in qblocks0
result0 = [((2, 3), True), ((0, 1), True), ((1, 2), False)]
exists_causal_splitter_result_map.append(result0)

# both blocks go to block
both_blocks_goto_result_map = []

# 0
both_blocks_goto_result_map.append([
    ((0, 1, 0), True),
    ((0, 1, 1), True),
    ((0, 1, 2), True),
    ((0, 1, 3), True),
Beispiel #2
0
def test_mark_wf_nodes_correct(graph, wf_nodes, nwf_nodes):
    vertexes, _ = decorate_nx_graph(graph)

    for i in range(len(graph.nodes)):
        assert (i in wf_nodes and vertexes[i].wf) or (i in nwf_nodes
                                                      and not vertexes[i].wf)
Beispiel #3
0
def test_clear_index():
    vertexes, _ = decorate_nx_graph(nx.balanced_tree(2, 3))
    partition = RankedPartition(vertexes)
    partition.clear_index(1)
    assert len(partition[1]) == 0
Beispiel #4
0
def test_get_item():
    vertexes, _ = decorate_nx_graph(nx.balanced_tree(2, 3))
    partition = RankedPartition(vertexes)
    assert partition[1] == partition._partition[1]
Beispiel #5
0
def test_len():
    vertexes, _ = decorate_nx_graph(nx.balanced_tree(2, 3))
    partition = RankedPartition(vertexes)
    assert len(partition) == 5
Beispiel #6
0
def test_scc_leaf_length():
    vertexes, _ = decorate_nx_graph(nx.balanced_tree(2, 3))
    partition = RankedPartition(vertexes)
    assert partition[0][0].size == 0
Beispiel #7
0
def test_append_at_index():
    vertexes, _ = decorate_nx_graph(nx.balanced_tree(2, 3))
    partition = RankedPartition(vertexes)
    block = _QBlock([], None)
    partition.append_at_index(block, 1)
    assert partition[1][-1] == block
Beispiel #8
0
def test_nvertexes(graph):
    vertexes, _ = decorate_nx_graph(graph)
    partition = RankedPartition(vertexes)
    assert partition.nvertexes == len(graph.nodes)
Beispiel #9
0
def test_compute_rank(graph, node_rank_dict: dict):
    vertexes, _ = decorate_nx_graph(graph)

    for idx in range(len(vertexes)):
        assert vertexes[idx].rank == node_rank_dict[idx]
Beispiel #10
0
def test_merge_condition_with_initial_partition(graph, initial_partition):
    vertexes, qblocks = decorate_nx_graph(graph, initial_partition)

    for tp in product(qblocks, qblocks):
        assert not merge_condition(tp[0], tp[1])
def dovier_piazza_policriti(
    graph: nx.Graph,
    initial_partition: List[Tuple[int]] = None,
    is_integer_graph: bool = False,
) -> List[Tuple]:
    """Compute the RSCP/maximum bisimulation of the given graph using
    *Dovier-Piazza-Policriti*'s algorithm.

    Example:
        >>> graph = networkx.balanced_tree(2,3)
        >>> dovier_piazza_policriti(graph)
        [(7, 8, 9, 10, 11, 12, 13, 14), (3, 4, 5, 6), (1, 2), (0,)]

    This function works with integer graph (nodes are integers starting from
    0 and form an interval without holes). If the given graph is non-integer
    it is converted to an isomorphic integer graph automatically (unless
    `is_integer_graph` is `True`) and then re-converted to its original form
    after the end of the computation. For this reason nodes of `graph` **must**
    be hashable objects.

    .. warning::
        Using a non integer graph and setting `is_integer_graph` to `True`
        will probably make the function fail with an exception, or, even worse,
        return a wrong output.

    :param graph: The input graph.
    :param initial_partition: The initial partition (or labeling set). Defaults
        to `None`, in which case the trivial labeling set (one block which
        contains all the nodes) is used.
    :param is_integer_graph: If `True`, we do not check if the given graph is
        integer (saves time). If `is_integer_graph` is `True` but the graph
        is not integer the output may be wrong. Defaults to False.
    :returns: The RSCP/maximum bisimulation of the given labeling set as a
        list of tuples, each of which contains bisimilar nodes.
    """

    if not isinstance(graph, nx.DiGraph):
        raise Exception("graph should be a directed graph (nx.DiGraph)")

    # if True, the input graph is already an integer graph
    original_graph_is_integer = is_integer_graph or check_normal_integer_graph(
        graph)

    if not original_graph_is_integer:
        # convert the graph to an "integer" graph
        integer_graph, node_to_idx = convert_to_integer_graph(graph)
    else:
        integer_graph = graph

    vertexes, _ = decorate_nx_graph(integer_graph, initial_partition)
    partition = RankedPartition(vertexes)

    tp = dovier_piazza_policriti_partition(partition)
    collapsed_partition, collapse_map = tp

    # from the collapsed partition obtained from FBA, build the RSCP (external
    # representation, List[Tuple[int]])
    rscp = []
    for rank in collapsed_partition:
        for block in rank:
            if block.vertexes.size > 0:
                block_survivor_node = block.vertexes.first.value
                block_vertexes = [block_survivor_node.label]

                if collapse_map[block_survivor_node.label] is not None:
                    block_vertexes.extend(
                        map(
                            lambda vertex: vertex.label,
                            collapse_map[block_survivor_node.label],
                        ))

                rscp.append(tuple(block_vertexes))

    if original_graph_is_integer:
        return rscp
    else:
        return back_to_original(rscp, node_to_idx)