Exemple #1
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
def dovier_piazza_policriti_partition(
    partition: RankedPartition,
) -> Tuple[RankedPartition, List[List[_Vertex]]]:
    """Apply *Dovier-Piazza-Policriti*'s algorithm to the given ranked
    partition.

    :param partition: A ranked partition (:math:`P` in the paper).
    :returns: A tuple such that the first item is the partition at the end of
        the algorithm (which at this point is made of blocks of size 1
        containing only the vertexes which survived the collapse), and the
        second is a list which maps a survivor nodes to the list of nodes
        collapsed to that survivor node.
    """

    # maps each survivor node to a list of nodes collapsed into it
    collapse_map = [None for _ in range(partition.nvertexes)]

    # loop over the ranks
    for partition_idx in range(len(partition)):
        if len(partition[partition_idx]) == 1:
            if len(partition[partition_idx][0].vertexes):
                block = partition[partition_idx][0]
                survivor_vertex, collapsed_vertexes = collapse(block)
                if survivor_vertex is not None:
                    # update the collapsed nodes map
                    collapse_map[survivor_vertex.label] = collapsed_vertexes
                    # update the partition
                    split_upper_ranks(partition, block)
        # OPTIMIZATION: if at the current rank we only have blocks of single
        # vertexes, skip this step.
        elif any(map(lambda block: block.size > 1, partition[partition_idx])):
            current_label = 0
            for block in partition[partition_idx]:
                for vertex in block.vertexes:
                    # scale vertex
                    vertex.scale_label(current_label)
                    current_label += 1

                    # exclude nodes having the wrong rank from the image and
                    # counterimage of the vertex. from now they're gone
                    # forever.
                    vertex.restrict_to_subgraph(
                        validation=lambda vx: vx.rank == vertex.rank)

            # apply PTA to the subgraph at the current examined rank
            # CAREFUL: if you debug here, you'll see that there are some
            # "duplicate" nodes (nodes with the same label in different blocks
            # of the partition). this happens becaus of the SCALING (which is
            # used to pass a normal graph to PTA)
            rscp = paige_tarjan_qblocks(partition[partition_idx])

            # clear the partition at the current rank
            partition.clear_index(partition_idx)

            # insert the new blocks in the partition at the current rank, and
            # collapse each block.
            for block in rscp:
                block_vertexes = []
                for scaled_vertex in block.vertexes:
                    scaled_vertex.back_to_original_label()
                    scaled_vertex.back_to_original_graph()
                    block_vertexes.append(scaled_vertex)

                # we can set XBlock to None because PTA won't be called again
                # on these blocks
                internal_block = _Block(block_vertexes, None)

                survivor_vertex, collapsed_vertexes = collapse(internal_block)

                if survivor_vertex is not None:
                    # update the collapsed nodes map
                    collapse_map[survivor_vertex.label] = collapsed_vertexes
                    # add the new block to the partition
                    partition.append_at_index(internal_block, partition_idx)
                    # update the upper ranks with respect to this block
                    split_upper_ranks(partition, internal_block)
        else:
            for block in partition[partition_idx]:
                # update the upper ranks with respect to this block
                split_upper_ranks(partition, block)

    return (partition, collapse_map)