Skip to content

I’ve reviewed the Qermit-based mitigation module and identified several key issues and clean-ups #280

@AiPals

Description

@AiPals

Here are the proposed corrections—each illustrated with the minimal changed snippet—so you can integrate them directly.

Fixes by Jesus Carrasco

1. Fixing the “TK1” membership test in label_gates

Problem:

if labelled_command["op"]["type"] in ("TK1"):

This checks membership in the string "TK1" (i.e. {"T","K","1"}) rather than the OpType.

Correction:

from pytket.circuit import OpType

# …

if labelled_command["op"]["type"] == OpType.TK1:
    labelled_command["opgroup"] = f"Computing {comp_count}"
    comp_count += 1
elif labelled_command["op"]["type"] == OpType.CX:
    labelled_command["opgroup"] = f"Frame {frame_count}"
    frame_count += 1
else:
    raise RuntimeError(
        'Expected only TK1 or CX gates—please rebase first with PECRebase.'
    )

2. Consistent “noop” creation for identity Pauli

Problem:
In str_to_pauli_op and in wrapping frames, raw dicts and "noop" strings are used.

Correction:

def str_to_pauli_op(pauli_str: str) -> Op:
    assert pauli_str in ["I", "X", "Y", "Z"]
    mapping = {
        "I": OpType.Noop,
        "X": OpType.X,
        "Y": OpType.Y,
        "Z": OpType.Z,
    }
    return Op.create(mapping[pauli_str])

And in wrap_frame_gates, replace the manual dict with:

identity_op = Op.create(OpType.Noop)
# …
labelled_EM_command = {
    "op": identity_op.to_dict()["op"],
    "args": [arg],
    "opgroup": f"pre Pauli {frame_number} {qubit_i}"
}

3. Mapping qubits correctly (use Qubit, not Node)

Problem:

n_q_map[cc_qns[i]] = Node("q", i)

tket’s place_with_map expects Qubit-to-Qubit maps, not architecture Nodes.

Correction:

from pytket.unit_id import Qubit

# …

n_q_map = { old_q: Qubit(i) for i, old_q in enumerate(rand_cliff_circ.qubits) }
# Then use place_with_map(rand_cliff_circ, n_q_map)

4. Avoid reassigning circ.add_circuit (it returns None)

Problem:

circ = circ.add_circuit(cliff_circ, [...], [])

add_circuit mutates in place and returns None.

Correction:

circ.add_circuit(cliff_circ, list(range(n_qubits)), [])

5. Ensure full Pauli mapping in clifford_canonical_F

Problem: The doc said pauli_layer in {0,1,2,3}, but the code only handled 0,1,2.

Correction:

for i, gate in enumerate(pauli_layer):
    if gate == 1:        circ.X(i, opgroup="Clifford 1")
    elif gate == 2:      circ.Y(i, opgroup="Clifford 1")
    elif gate == 3:      circ.Z(i, opgroup="Clifford 1")
    # gate == 0: identity—no action

Next Steps

  1. Apply these patches into your module where indicated.
  2. Run your unit tests (especially around label_gates, wrapping logic, and your QubitPauliString expectations).
  3. Let me know if you encounter any lingering errors or need further refinements—happy to dive deeper.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions