Skip to content

reverse_qubit_order() KeyError on aliased operand nodes (same root cause as #331) #333

Description

@ryanhill1

Summary

QasmModule.reverse_qubit_order() raises KeyError on any program whose unrolled AST contains aliased operand nodes — the same root cause as #331, surfacing one method below the fix in #332.

Found during adversarial review of #332: the visited-set guard added there fixes _remap_qubits, but reverse_qubit_order (src/pyqasm/modules/base.py:533-555) walks the same statements and mutates bit.indices[0][0].value in place with a negative-marker trick. On a node shared by k statements, the second visit reads the already-negated value and looks up new_qubit_mappings[reg][-2]KeyError: -1.

Reproduction

from pyqasm import loads

m = loads('''OPENQASM 3;
include "stdgates.inc";
qubit[3] q;
crz(0.5) q[1], q[2];
''')
m.unroll()
m.reverse_qubit_order()   # KeyError: -1

Reproduces on main (pre-dates #332; that PR did not touch this method).

Fix options

Same two options as #331, not mutually exclusive:

  1. Root cause: have unroll() / the decomposer emit fresh (deep-copied) operand nodes so no AST node is shared across statements. This retires the whole class of bug — every in-place index mutation in modules/base.py is currently exposed to aliasing.
  2. Point fix: apply the same visited-node-id guard from fix: remove_idle_qubits KeyError on shared operand nodes #332 to both passes in reverse_qubit_order. Note the marker pass and the unmark pass each need their own guard (or the method should be rewritten to build the mapping without the negative-marker trick, which only exists to survive double visits it doesn't actually survive).

Option 1 is the better long-term fix; if we take it, the guard added in #332 becomes harmless belt-and-braces.

🤖 Filed with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions