Skip to content

Add syntactic sugar for squin.two_qubit_pauli_channel#764

Open
jasonhan3 wants to merge 3 commits into
mainfrom
jasonh/341-sugar-twoqubitnoise
Open

Add syntactic sugar for squin.two_qubit_pauli_channel#764
jasonhan3 wants to merge 3 commits into
mainfrom
jasonh/341-sugar-twoqubitnoise

Conversation

@jasonhan3
Copy link
Copy Markdown
Contributor

Summary

Closes #341.

Adds syntax sugar for SQUIN two-qubit Pauli channels so users can pass Cirq-style
Pauli product probability dictionaries instead of manually constructing the full
15-entry probability list.

@squin.kernel
def main():
    q = squin.qalloc(2)
    squin.two_qubit_pauli_channel({"XX": 0.1, "YY": 0.2, "ZZ": 0.15}, q[0], q[1])

Omitted Pauli products default to 0.0.

The existing 15-entry probability list form and broadcast-style control/target lists continue to work.

Changes

  • Add custom Python-call lowering for squin.noise.stmts.TwoQubitPauliChannel
  • Support dict literals keyed by Pauli products such as "XX", "YY", and "ZZ"
  • Preserve the existing 15-entry list/IList probability form
  • Preserve broadcast controls/targets typed as IList[Qubit, N]
  • Allow single-qubit controls/targets in the simple public syntax by wrapping them into one-element ILists during lowering
  • Preserve Python list literals for controls/targets as ILists for broadcast use
  • Centralize PAULI_PRODUCT_ORDER and reuse it from Cirq lowering/emission and fidelity analysis
  • Correct the two-qubit Pauli probability operand type to IList[float, Literal[15]]

Verification

uv run --no-sync pytest test/squin/test_two_qubit_pauli_channel_sugar.py test/stim/passes/test_squin_noise_to_stim.py test/cirq_utils/test_squin_noise_to_cirq.py test/analysis/fidelity/test_fidelity.py
uv run --no-sync ruff check src/bloqade/squin/noise/stmts.py src/bloqade/squin/noise/_interface.py src/bloqade/squin/noise/__init__.py src/bloqade/squin/stdlib/simple/noise.py src/bloqade/cirq_utils/emit/noise.py src/bloqade/cirq_utils/lowering.py src/bloqade/squin/analysis/fidelity/impls.py test/squin/test_two_qubit_pauli_channel_sugar.py

@jasonhan3 jasonhan3 requested a review from david-pl April 29, 2026 19:56
@jasonhan3 jasonhan3 self-assigned this Apr 29, 2026
@jasonhan3 jasonhan3 added category: enhancement Category: this is an enhancement of an existing feature. area: SQUIN Area: SQUIN representation, transforms, and compilation. area: stdlib Area: standard library related issues. labels Apr 29, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 29, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 29, 2026

☂️ Python Coverage

current status: ✅

Overall Coverage

Lines Covered Coverage Threshold Status
12290 10980 89% 0% 🟢

New Files

No new covered files...

Modified Files

File Coverage Status
src/bloqade/cirq_utils/emit/noise.py 83% 🟢
src/bloqade/cirq_utils/lowering.py 92% 🟢
src/bloqade/squin/analysis/fidelity/impls.py 86% 🟢
src/bloqade/squin/noise/_init_.py 100% 🟢
src/bloqade/squin/noise/_interface.py 100% 🟢
src/bloqade/squin/noise/stmts.py 100% 🟢
src/bloqade/squin/stdlib/simple/noise.py 77% 🟢
TOTAL 91% 🟢

updated for commit: cd9e0f5 by action🐍

Copy link
Copy Markdown
Collaborator

@david-pl david-pl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not so sure about this change. It's a little weird because it lowers an ast.Dict, when kirin actually doesn't support it.

Something like this errors

@squin.kernel
def main():
    q = squin.qalloc(2)
    probs = {"XX": 0.1, "YY": 0.2, "ZZ": 0.15}
    squin.two_qubit_pauli_channel(probs, q[0], q[1])

with BuildError: Cannot lower Dict node: <ast.Dict object at 0x10ae5a4d0>

What's worse, however, is this silent footgun:

from bloqade import squin

probs = {"XX": 0.1, "YY": 0.2, "ZZ": 0.15}

@squin.kernel
def main():
    q = squin.qalloc(2)
    squin.two_qubit_pauli_channel(probs, q[0], q[1])

This seemingly works fine, but inspecting the IR, you see that it silently inserts the actual dict object and uses this as argument

func.func @main() -> !py.NoneType {
  ^0(%main_self):
  │ %0 = py.constant.constant 2 : !py.int%q = func.invoke qalloc(%0) : !py.IList[!py.Qubit, !Any] maybe_pure=False%1 = py.constant.constant {'XX': 0.1, 'YY': 0.2, 'ZZ': 0.15} : !Bottom%2 = py.constant.constant 0 : !py.int%3 = py.indexing.getitem(%q, %2) : !py.Qubit%4 = py.ilist.new(values=(%3)){elem_type=!py.Qubit} : !py.IList[!py.Qubit, Literal(1,int)]
  │ %5 = py.constant.constant 1 : !py.int%6 = py.indexing.getitem(%q, %5) : !py.Qubit%7 = py.ilist.new(values=(%6)){elem_type=!py.Qubit} : !py.IList[!py.Qubit, Literal(1,int)]
  │      squin.noise.two_qubit_pauli_channel(probabilities=%1, controls=%4, targets=%7)
  │ %8 = func.const.none() : !py.NoneTypefunc.return %8

This will only fail later with spurious rewrite failures or an unhelpful error message.

broadcast.two_qubit_pauli_channel(
probabilities, ilist.IList([control]), ilist.IList([target])
)
two_qubit_pauli_channel = noise.two_qubit_pauli_channel
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Er, what's this? This just aliases the wrapper right? That shouldn't be the case.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see, you can't support this signature in a kernel, right? Hm, well but this makes two_qubit_pauli_channel subtly different from all other channels and gates. Not sure if that's so great...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: SQUIN Area: SQUIN representation, transforms, and compilation. area: stdlib Area: standard library related issues. category: enhancement Category: this is an enhancement of an existing feature.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Syntax sugar for squin's two qubit pauli channel

2 participants