Phase-Gradient Rotations

The phase_gradient gallery entry composes signed single-qubit rotations from T-resource injection stages. It shows how a small family of reusable modules can form a longer adaptive computation. Start with modules and T Block.

Note

The gallery’s k=4 label names a fixed single-qubit rotation construction. It does not describe a four-qubit phase-gradient register or expose a general rotation-synthesis API. Its source contains 22 signed \(\pi/4\) rotations, followed by a Hadamard.

What the source implements

Let \(R_P(\theta)=\exp(-i\theta P/2)\). In time order, each row below applies \(R_X(a\pi/4)\) followed by \(R_Z(b\pi/4)\):

Pair

\(a\)

\(b\)

0

+1

+1

1

+1

+1

2

−1

−1

3

−1

−1

4

−1

+1

5

−1

−1

6

+1

−1

7

−1

+1

8

−1

+1

9

+1

−1

10

+1

+1

A final \(H\) completes the map. This is the exact gate sequence checked by Bloq’s independent logical-map test, up to global phase. The example does not attach an approximation-error bound to a different target rotation.

Four reusable definitions cover the two axes and rotation signs:

Definition

Logical role

Transverse resource arm

RxPlusAtYPlus

\(R_X(+\pi/4)\)

Local +Y

RxMinusAtYPlus

\(R_X(-\pi/4)\)

Local +Y

RzPlusAtXPlus

\(R_Z(+\pi/4)\)

Local +X

RzMinusAtXPlus

\(R_Z(-\pi/4)\)

Local +X

Each definition has temporal q_in / q_out data ports and one T source. Here is the positive X rotation:

module RxPlusAtYPlus {
in q_in: data = 0
out q_out: data = 2
0: Port [0, 0, 0] role=input <q_in>
1: XZX [0, 0, 1]
2: Port [0, 0, 2] role=output <q_out>
3: T [0, 1, 0]
4: XZZ [0, 1, 1]
5: ZY [0, 1, 2]
0 -> +Z
1 -> +Z
1 -> +Y
3 -H> +Z
4 -> +Z
m = measure 1 -> +Y
resolve 5 if !m
feedback X 1 if m
}

m is a named merge readout. resolve chooses the ordered measurement basis, and feedback applies the declared correction. The positive and negative definitions differ in their selective cap and, for X rotations, their feedback condition. Substituting one for the other changes the signed operation.

Place the instances

The root alternates resource arms around the data wire: +Y, +X, −Y, −X. A Z half-turn moves a definition’s arm to the opposite side while keeping its time direction. This allows nearby instances without overlapping their arms.

s00: RxPlusAtYPlus @ [0, 0, 0]
s01: RzPlusAtXPlus @ [0, 0, 1]
s02: RxPlusAtYPlus @ [0, 0, 2] rotate Z 180
s03: RzPlusAtXPlus @ [0, 0, 3] rotate Z 180
s04: RxMinusAtYPlus @ [0, 0, 4]
s05: RzMinusAtXPlus @ [0, 0, 5]
s06: RxMinusAtYPlus @ [0, 0, 6] rotate Z 180
s07: RzMinusAtXPlus @ [0, 0, 7] rotate Z 180
flowchart LR
  q["q_in"] --> rx0["s00: +Rx"] --> rz0["s01: +Rz"]
  rz0 --> rx1["s02: +Rx, rotate Z 180"] --> rz1["s03: +Rz, rotate Z 180"]
  rz1 --> rest["s04 … s21"] --> h["Hadamard seam"] --> output["q_out"]

All 22 stages connect explicitly. The last stage uses a Hadamard pipe into a parent-owned cube, followed by the output Port:

s20.q_out -> s21.q_in
s21.q_out -H> 1
1 -> 2

The full hierarchy has five definitions, including main. It contains 21 direct child-to-child seams. The final Hadamard is a connection; there is no extra FinalHadamard module.

Load and compile

Compile at distance three with ordinary T cultivation, then save text Bloq IR:

from pathlib import Path
import bloq

example = bloq.GalleryItem.PHASE_GRADIENT
Path("phase-gradient.blog").write_text(example.source(), encoding="utf-8")
graph = example.load()
flat = graph.flatten()
assert flat.t_count == 22
assert flat.selective_count == 22
program = bloq.compile(graph, distance=3)
program.validate()
program.save("phase-gradient.bloqir")
use bloq::prelude::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let source = GalleryItem::PhaseGradientK4.build();
    assert_eq!(source.modules().count(), 5);
    assert_eq!(source.instances.len(), 22);
    std::fs::write("phase-gradient.blog", source.to_blog_text())?;
    let program = compile(&source, 3)?;
    program.validate()?;
    std::fs::write("phase-gradient.bloqir", program.to_text())?;
    Ok(())
}

The named readouts remain output-safe after composition; the compiler derives terminal corrections from the same signed relation.

CLI:

bloq compile --gallery phase_gradient -d 3 --backend ir-text -o phase-gradient.bloqir
bloq validate phase-gradient.bloqir

Download the full BLOG source to modify placements or open it in the editor.

Verification and proxies

The result retains T-source retries, selected measurements, and feed-forward. Use the verification VM to simulate those dependencies. The T states here come from the compiled cultivation regions. They are not assumed to arrive through external prepared-state ports.

For a Clifford distance-analysis circuit, the CLI supports a reproducible proxy:

bloq compile --gallery phase_gradient -d 3 --clifford-proxy --proxy-seed 7 -o phase-gradient-proxy.stim

Important

A Clifford proxy replaces T resources with ideal ports and jointly selects a reachable measurement path. It is a distance-analysis stand-in, not an execution of the rotation channel or a measurement of its logical error rate.