Skip to content

Angle-handling defects at four ingress points: silent CRz drop, deg-as-rad, malformed PHIR angles, backend-dependent ZLUP angle #691

Open

Description

@ciaranra

Summary

An ingress audit of controlled-rotation lowering turned up four smaller defects alongside the sheet-loss ones (#688, #689, #690). Grouping them because each is small and they share a theme: an ingress that silently drops, mis-scales, or backend-varies an angle rather than failing loudly.

1. Legacy HUGR to SLR silently drops CRz

python/quantum-pecos/src/pecos/circuit_converters/hugr_to_ast.py omits CRz/CRx/CRy from its gate map, and the scanner then continues past unrecognized quantum nodes without reporting. A program containing a controlled rotation converts to an SLR AST that is missing it, with no error.

Fix: reject unrecognized quantum operations rather than skipping them, or map the controlled rotations.

2. Pure-Python PHIR treats degree angles as radians

python/quantum-pecos/src/pecos/reps/pyphir/pyphir.py multiplies only the "pi" unit; "deg" values pass through unchanged and are then consumed as radians. Only affects HybridEngine(cinterp="python").

Fix: convert "deg" by pi/180, and fail loudly on any unit the converter does not handle rather than passing it through.

3. QuantumCircuit.to_phir_dict/json emits the wrong angle shape

qc2phir.py emits a flat list of angle values where PHIR expects [[values], unit]. Independently of the sheet issue in #689, the emitted PHIR is malformed for consumers that read the unit.

4. ZLUP bare-number CRZ means different angles per backend

For a bare numeric argument, the PHIR backend treats it as turns and multiplies by tau, the HUGR backend treats it as radians, and the QASM backend prints it unchanged (exp/zlup/src/codegen/{phir,hugr,qasm}.rs). The same source program produces three different rotations.

Fix: settle one interpretation for a bare number at the language level and make all three backends agree, or require an explicit unit and reject bare numbers. Experimental crate, so lower urgency, but it should not be left ambiguous.

Also undetermined, recorded for follow-up

The HUGR-to-DAG and HUGR-to-PHIR scanners do not resolve ControlModifier nodes. Whether a modified function is merely omitted or an unmodified body can leak through depends on graph shape. A nested ControlModifier<2, Rz> full-matrix fixture through each converter would settle it. Note the QIS/LLVM compiler path is safe here: the locked resolver halves in raw f64 half-turns without Angle64, and recursively halves controlled global phase.

Background: ~/Repos/pecos-docs/design/angle-representation-and-controlled-rotations.md.

Activity

  1. added
    bugSomething isn't working
    rustPull requests that update rust code
    pythonPull requests that update python code
    severity:mediumDegraded or awkward behavior with a workaround
    on Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpythonPull requests that update python coderustPull requests that update rust codeseverity:mediumDegraded or awkward behavior with a workaround

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions