Skip to content

Add relabeling function for nodes in Pattern #519

@clebrin

Description

@clebrin

Is your feature request related to a problem? Please describe.

After optimization passes such as perform_pauli_pushing() with remove_pauli_measurements(), a pattern may contain sparse node labels because removed nodes are not relabeled.

For example, a pattern may end up with node labels such as:

{6, 7, 19, 21}

instead of a contiguous numbering:

{0, 1, 2, 3}

This is not a correctness issue, but it can be inconvenient when exporting to external runtimes.


Describe the feature you'd like

I would like a utility method to relabel pattern nodes into a contiguous range while preserving all command dependencies and input/output nodes.

For example:

pattern.perform_pauli_pushing()
pattern.remove_pauli_measurements()

print(sorted(pattern.extract_nodes()))
# [6, 7, 19, 21]

new_pattern = pattern.relabel_nodes()

print(sorted(new_pattern.extract_nodes()))
# [0, 1, 2, 3]

The method would update all node references appearing in commands (N, E, M, X, Z, S, etc.), dependency domains, and input/output node lists.


Additional context

I implemented a local helper function that performs this transformation (shown below). I would be happy to open a PR.

from copy import deepcopy

from graphix.command import C, E, M, N, S, X, Z
from graphix.pattern import Pattern


def relabel_nodes(pattern: Pattern) -> Pattern:
    pattern = deepcopy(pattern)

    relabel = {
        node: i
        for i, node in enumerate(sorted(pattern.extract_nodes()))
    }

    def remap_domain(domain):
        return {relabel[node] for node in domain}

    commands = []

    for cmd in pattern:
        if isinstance(cmd, (N, C)):
            cmd.node = relabel[cmd.node]

        elif isinstance(cmd, M):
            cmd.node = relabel[cmd.node]
            cmd.s_domain = remap_domain(cmd.s_domain)
            cmd.t_domain = remap_domain(cmd.t_domain)

        elif isinstance(cmd, E):
            u, v = cmd.nodes
            cmd.nodes = (relabel[u], relabel[v])

        elif isinstance(cmd, (X, Z, S)):
            cmd.node = relabel[cmd.node]
            cmd.domain = remap_domain(cmd.domain)

        commands.append(cmd)

    input_nodes = [relabel[node] for node in pattern.input_nodes]
    output_nodes = [relabel[node] for node in pattern.output_nodes]

    return Pattern(input_nodes, commands, output_nodes)

Metadata

Metadata

Assignees

No one assigned

    Labels

    new featureNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions