bloqade-circuit 0.1.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of bloqade-circuit might be problematic. Click here for more details.
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/.github/workflows/ci.yml +1 -1
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/.github/workflows/release.yml +1 -1
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/PKG-INFO +8 -2
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/pyproject.toml +12 -4
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/analysis/address/impls.py +5 -9
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/analysis/address/lattice.py +1 -1
- bloqade_circuit-0.2.1/src/bloqade/analysis/fidelity/__init__.py +1 -0
- bloqade_circuit-0.2.1/src/bloqade/analysis/fidelity/analysis.py +69 -0
- bloqade_circuit-0.2.1/src/bloqade/device.py +130 -0
- bloqade_circuit-0.2.1/src/bloqade/noise/__init__.py +2 -0
- bloqade_circuit-0.2.1/src/bloqade/noise/fidelity.py +51 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/noise/native/model.py +1 -2
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/noise/native/rewrite.py +5 -5
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/noise/native/stmts.py +40 -11
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/pyqrack/__init__.py +8 -2
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/pyqrack/base.py +24 -3
- bloqade_circuit-0.2.1/src/bloqade/pyqrack/device.py +166 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/pyqrack/noise/native.py +1 -2
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/pyqrack/qasm2/core.py +31 -15
- bloqade_circuit-0.2.1/src/bloqade/pyqrack/qasm2/glob.py +28 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/pyqrack/qasm2/uop.py +9 -1
- bloqade_circuit-0.2.1/src/bloqade/pyqrack/reg.py +77 -0
- bloqade_circuit-0.2.1/src/bloqade/pyqrack/squin/op.py +154 -0
- bloqade_circuit-0.2.1/src/bloqade/pyqrack/squin/qubit.py +85 -0
- bloqade_circuit-0.2.1/src/bloqade/pyqrack/squin/runtime.py +515 -0
- bloqade_circuit-0.2.1/src/bloqade/pyqrack/squin/wire.py +69 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/pyqrack/target.py +9 -2
- bloqade_circuit-0.2.1/src/bloqade/pyqrack/task.py +30 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/_wrappers.py +11 -1
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/core/stmts.py +15 -4
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/expr/_emit.py +9 -8
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/emit/base.py +4 -2
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/emit/gate.py +0 -14
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/emit/main.py +19 -15
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/emit/target.py +2 -6
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/glob.py +1 -1
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/parse/lowering.py +124 -1
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/passes/glob.py +3 -3
- bloqade_circuit-0.2.1/src/bloqade/qasm2/passes/lift_qubits.py +26 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/passes/noise.py +6 -14
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/passes/parallel.py +3 -3
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/passes/py2qasm.py +1 -2
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/passes/qasm2py.py +1 -2
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/rewrite/desugar.py +6 -6
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/rewrite/glob.py +9 -9
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/rewrite/heuristic_noise.py +30 -38
- bloqade_circuit-0.2.1/src/bloqade/qasm2/rewrite/insert_qubits.py +34 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/rewrite/native_gates.py +54 -55
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/rewrite/parallel_to_uop.py +9 -9
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/rewrite/uop_to_parallel.py +20 -22
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/types.py +3 -6
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qbraid/schema.py +10 -12
- bloqade_circuit-0.2.1/src/bloqade/squin/__init__.py +2 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/squin/analysis/nsites/analysis.py +4 -6
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/squin/analysis/nsites/impls.py +2 -6
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/squin/analysis/schedule.py +1 -1
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/squin/groups.py +15 -7
- bloqade_circuit-0.2.1/src/bloqade/squin/noise/__init__.py +27 -0
- bloqade_circuit-0.2.1/src/bloqade/squin/noise/_dialect.py +3 -0
- bloqade_circuit-0.2.1/src/bloqade/squin/noise/stmts.py +59 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/squin/op/__init__.py +35 -5
- bloqade_circuit-0.2.1/src/bloqade/squin/op/number.py +5 -0
- bloqade_circuit-0.2.1/src/bloqade/squin/op/rewrite.py +46 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/squin/op/stmts.py +23 -2
- bloqade_circuit-0.2.1/src/bloqade/squin/op/types.py +24 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/squin/qubit.py +79 -11
- bloqade_circuit-0.2.1/src/bloqade/squin/rewrite/measure_desugar.py +33 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/squin/wire.py +31 -2
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/emit/stim.py +1 -1
- bloqade_circuit-0.2.1/src/bloqade/task.py +94 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/visual/animation/base.py +25 -15
- bloqade_circuit-0.2.1/test/analysis/address/test_lattice.py +17 -0
- bloqade_circuit-0.2.1/test/analysis/fidelity/test_fidelity.py +246 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/pyqrack/runtime/noise/native/test_loss.py +9 -9
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/pyqrack/runtime/noise/native/test_pauli.py +20 -8
- bloqade_circuit-0.2.1/test/pyqrack/runtime/test_dyn_memory.py +36 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/pyqrack/runtime/test_qrack.py +6 -5
- bloqade_circuit-0.2.1/test/pyqrack/test_squin.py +514 -0
- bloqade_circuit-0.2.1/test/pyqrack/test_target.py +173 -0
- bloqade_circuit-0.2.1/test/qasm2/emit/test_qasm2.py +26 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/passes/test_heuristic_noise.py +5 -7
- bloqade_circuit-0.2.1/test/qasm2/test_lowering.py +82 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/test_native.py +37 -1
- bloqade_circuit-0.2.1/test/squin/test_constprop.py +110 -0
- bloqade_circuit-0.2.1/test/squin/test_measure_sugar.py +36 -0
- bloqade_circuit-0.2.1/test/squin/test_mult_rewrite.py +166 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/stim/dialects/stim/emit/base.py +1 -1
- bloqade_circuit-0.2.1/test/stim/wrapper/__init__.py +0 -0
- bloqade_circuit-0.2.1/test/visual/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/uv.lock +25 -7
- bloqade_circuit-0.1.0/src/bloqade/noise/__init__.py +0 -1
- bloqade_circuit-0.1.0/src/bloqade/pyqrack/reg.py +0 -109
- bloqade_circuit-0.1.0/src/bloqade/squin/__init__.py +0 -2
- bloqade_circuit-0.1.0/src/bloqade/squin/op/complex.py +0 -6
- bloqade_circuit-0.1.0/src/bloqade/squin/op/types.py +0 -10
- bloqade_circuit-0.1.0/test/pyqrack/runtime/test_dyn_memory.py +0 -32
- bloqade_circuit-0.1.0/test/pyqrack/test_target.py +0 -40
- bloqade_circuit-0.1.0/test/qasm2/emit/test_qasm2.py +0 -27
- bloqade_circuit-0.1.0/test/qasm2/test_lowering.py +0 -22
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/.github/dependabot.yml +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/.github/workflows/isort.yml +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/.github/workflows/lint.yml +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/.gitignore +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/.pre-commit-config.yaml +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/LICENSE +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/README.md +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/_typos.toml +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/justfile +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/analysis/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/analysis/address/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/analysis/address/analysis.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/noise/native/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/noise/native/_dialect.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/noise/native/_wrappers.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/pyqrack/noise/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/pyqrack/qasm2/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/pyqrack/qasm2/parallel.py +0 -0
- {bloqade_circuit-0.1.0/src/bloqade/squin/analysis → bloqade_circuit-0.2.1/src/bloqade/pyqrack/squin}/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/core/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/core/_dialect.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/core/_emit.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/core/_typeinfer.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/core/address.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/expr/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/expr/_dialect.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/expr/_from_python.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/expr/_interp.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/expr/stmts.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/glob.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/indexing.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/inline.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/noise.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/parallel.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/uop/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/uop/_dialect.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/uop/_emit.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/uop/schedule.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/dialects/uop/stmts.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/emit/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/groups.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/parallel.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/parse/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/parse/ast.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/parse/build.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/parse/parser.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/parse/print.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/parse/qasm2.lark +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/parse/visitor.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/parse/visitor.pyi +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/passes/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/passes/fold.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/rewrite/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qasm2/rewrite/register.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qbraid/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qbraid/lowering.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qbraid/simulation_result.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/qbraid/target.py +0 -0
- {bloqade_circuit-0.1.0/src/bloqade/visual/animation → bloqade_circuit-0.2.1/src/bloqade/squin/analysis}/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/squin/analysis/nsites/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/squin/analysis/nsites/lattice.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/squin/op/_dialect.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/squin/op/traits.py +0 -0
- {bloqade_circuit-0.1.0/src/bloqade/visual/animation/runtime → bloqade_circuit-0.2.1/src/bloqade/squin/rewrite}/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/_wrappers.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/aux/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/aux/_dialect.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/aux/emit.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/aux/interp.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/aux/lowering.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/aux/stmts/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/aux/stmts/annotate.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/aux/stmts/const.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/aux/types.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/collapse/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/collapse/_dialect.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/collapse/emit.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/collapse/stmts/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/collapse/stmts/measure.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/collapse/stmts/pp_measure.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/collapse/stmts/reset.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/gate/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/gate/_dialect.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/gate/emit.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/gate/stmts/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/gate/stmts/base.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/gate/stmts/clifford_1q.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/gate/stmts/clifford_2q.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/gate/stmts/control_2q.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/gate/stmts/pp.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/noise/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/noise/_dialect.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/noise/emit.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/dialects/noise/stmts.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/emit/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/stim/groups.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/test_utils.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/types.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/visual/__init__.py +0 -0
- {bloqade_circuit-0.1.0/test → bloqade_circuit-0.2.1/src/bloqade/visual/animation}/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/visual/animation/animate.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/visual/animation/gate_event.py +0 -0
- {bloqade_circuit-0.1.0/test/pyqrack → bloqade_circuit-0.2.1/src/bloqade/visual/animation/runtime}/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/visual/animation/runtime/aod.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/visual/animation/runtime/atoms.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/visual/animation/runtime/ppoly.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/visual/animation/runtime/qpustate.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/src/bloqade/visual/animation/runtime/utils.py +0 -0
- {bloqade_circuit-0.1.0/test/pyqrack/runtime → bloqade_circuit-0.2.1/test}/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/analysis/address/test_analysis.py +0 -0
- {bloqade_circuit-0.1.0/test/pyqrack/runtime/noise → bloqade_circuit-0.2.1/test/pyqrack}/__init__.py +0 -0
- {bloqade_circuit-0.1.0/test/qasm2 → bloqade_circuit-0.2.1/test/pyqrack/runtime}/__init__.py +0 -0
- {bloqade_circuit-0.1.0/test/qasm2/parse → bloqade_circuit-0.2.1/test/pyqrack/runtime/noise}/__init__.py +0 -0
- {bloqade_circuit-0.1.0/test/qasm2/passes → bloqade_circuit-0.2.1/test/qasm2}/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/analysis/test_dag.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/emit/test_extended.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/emit/test_qasm2_emit.py +0 -0
- {bloqade_circuit-0.1.0/test/qbraid → bloqade_circuit-0.2.1/test/qasm2/parse}/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/programs/README.md +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/programs/global.qasm +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/programs/iqft1.qasm +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/programs/main.qasm +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/programs/noise.qasm +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/programs/para.qasm +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/programs/process_tomo.qasm +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/programs/qelib1.inc +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/programs/qft.qasm +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/programs/qft2.qasm +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/programs/rb.qasm +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/programs/rep_code.qasm +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/programs/ripple_carry_adder.qasm +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/programs/tele.qasm +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/test_ast.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/parse/test_roundtrip.py +0 -0
- {bloqade_circuit-0.1.0/test/sample → bloqade_circuit-0.2.1/test/qasm2/passes}/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/passes/test_global_to_parallel.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/passes/test_global_to_uop.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/passes/test_parallel_to_uop.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/passes/test_qasm2py.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/passes/test_uop_to_parallel.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/test_count.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/test_inline.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qasm2/test_two2one.py +0 -0
- {bloqade_circuit-0.1.0/test/stim → bloqade_circuit-0.2.1/test/qbraid}/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qbraid/test_clean_circuit.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qbraid/test_lowering.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/qbraid/test_target.py +0 -0
- {bloqade_circuit-0.1.0/test/stim/dialects → bloqade_circuit-0.2.1/test/sample}/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/sample/test_noise_model.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/squin/analysis/test_nsites_analysis.py +0 -0
- {bloqade_circuit-0.1.0/test/stim/dialects → bloqade_circuit-0.2.1/test}/stim/__init__.py +0 -0
- {bloqade_circuit-0.1.0/test/stim/dialects/stim/emit → bloqade_circuit-0.2.1/test/stim/dialects}/__init__.py +0 -0
- {bloqade_circuit-0.1.0/test/stim/wrapper → bloqade_circuit-0.2.1/test/stim/dialects/stim}/__init__.py +0 -0
- {bloqade_circuit-0.1.0/test/visual → bloqade_circuit-0.2.1/test/stim/dialects/stim/emit}/__init__.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/stim/dialects/stim/emit/test_stim_1q.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/stim/dialects/stim/emit/test_stim_ctrl.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/stim/dialects/stim/emit/test_stim_detector.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/stim/dialects/stim/emit/test_stim_meas.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/stim/dialects/stim/emit/test_stim_noise.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/stim/dialects/stim/emit/test_stim_obs_inc.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/stim/dialects/stim/emit/test_stim_ppmeas.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/stim/dialects/stim/emit/test_stim_spp.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/stim/dialects/stim/test_stim_circuits.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/stim/dialects/stim/test_stim_const.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/stim/wrapper/test_wrapper.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/test_serialization.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/test_zone_model.py +0 -0
- {bloqade_circuit-0.1.0 → bloqade_circuit-0.2.1}/test/visual/test_utils.py +0 -0
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bloqade-circuit
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: The software development toolkit for neutral atom arrays.
|
|
5
5
|
Author-email: Roger-luo <rluo@quera.com>, kaihsin <khwu@quera.com>, weinbe58 <pweinberg@quera.com>, johnzl-777 <jlong@quera.com>
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Requires-Python: >=3.10
|
|
8
|
-
Requires-Dist: kirin-toolchain~=0.
|
|
8
|
+
Requires-Dist: kirin-toolchain~=0.17.0
|
|
9
9
|
Requires-Dist: numpy>=1.22.0
|
|
10
10
|
Requires-Dist: pandas>=2.2.3
|
|
11
11
|
Requires-Dist: pydantic<2.11.0,>=1.3.0
|
|
12
|
+
Requires-Dist: pyqrack-cpu>=1.38.2; sys_platform != 'darwin'
|
|
13
|
+
Requires-Dist: pyqrack>=1.38.2; sys_platform == 'darwin'
|
|
12
14
|
Requires-Dist: rich>=13.9.4
|
|
13
15
|
Requires-Dist: scipy>=1.13.1
|
|
14
16
|
Provides-Extra: cirq
|
|
15
17
|
Requires-Dist: cirq-core>=1.4.1; extra == 'cirq'
|
|
16
18
|
Requires-Dist: cirq-core[contrib]>=1.4.1; extra == 'cirq'
|
|
19
|
+
Provides-Extra: pyqrack-cuda
|
|
20
|
+
Requires-Dist: pyqrack-cuda>=1.38.2; extra == 'pyqrack-cuda'
|
|
21
|
+
Provides-Extra: pyqrack-opencl
|
|
22
|
+
Requires-Dist: pyqrack>=1.38.2; (sys_platform != 'darwin') and extra == 'pyqrack-opencl'
|
|
17
23
|
Provides-Extra: qasm2
|
|
18
24
|
Requires-Dist: lark>=1.2.2; extra == 'qasm2'
|
|
19
25
|
Provides-Extra: qbraid
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "bloqade-circuit"
|
|
3
|
-
version = "0.1
|
|
3
|
+
version = "0.2.1"
|
|
4
4
|
description = "The software development toolkit for neutral atom arrays."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -13,10 +13,12 @@ requires-python = ">=3.10"
|
|
|
13
13
|
dependencies = [
|
|
14
14
|
"numpy>=1.22.0",
|
|
15
15
|
"scipy>=1.13.1",
|
|
16
|
-
"kirin-toolchain~=0.
|
|
16
|
+
"kirin-toolchain~=0.17.0",
|
|
17
17
|
"rich>=13.9.4",
|
|
18
18
|
"pydantic>=1.3.0,<2.11.0",
|
|
19
19
|
"pandas>=2.2.3",
|
|
20
|
+
"pyqrack>=1.38.2 ; sys_platform == 'darwin'",
|
|
21
|
+
"pyqrack-cpu>=1.38.2 ; sys_platform != 'darwin'",
|
|
20
22
|
]
|
|
21
23
|
|
|
22
24
|
[project.optional-dependencies]
|
|
@@ -36,6 +38,12 @@ cirq = [
|
|
|
36
38
|
"cirq-core>=1.4.1",
|
|
37
39
|
"cirq-core[contrib]>=1.4.1",
|
|
38
40
|
]
|
|
41
|
+
pyqrack-opencl = [
|
|
42
|
+
"pyqrack>=1.38.2 ; sys_platform != 'darwin'",
|
|
43
|
+
]
|
|
44
|
+
pyqrack-cuda = [
|
|
45
|
+
"pyqrack-cuda>=1.38.2",
|
|
46
|
+
]
|
|
39
47
|
|
|
40
48
|
[build-system]
|
|
41
49
|
requires = ["hatchling"]
|
|
@@ -68,7 +76,7 @@ dev-linux = [
|
|
|
68
76
|
"pyqrack-cpu>=1.38.2",
|
|
69
77
|
"qbraid>=0.9.5",
|
|
70
78
|
"ffmpeg>=1.4",
|
|
71
|
-
"matplotlib>=3.
|
|
79
|
+
"matplotlib>=3.9.2",
|
|
72
80
|
"pyqt5>=5.15.11",
|
|
73
81
|
"tqdm>=4.67.1",
|
|
74
82
|
]
|
|
@@ -76,7 +84,7 @@ dev-mac-arm = [
|
|
|
76
84
|
"cirq-core[contrib]>=1.4.1",
|
|
77
85
|
"ffmpeg>=1.4",
|
|
78
86
|
"lark>=1.2.2",
|
|
79
|
-
"matplotlib>=3.
|
|
87
|
+
"matplotlib>=3.9.2",
|
|
80
88
|
"pyqrack>=1.38.2",
|
|
81
89
|
"pyqt5>=5.15.11",
|
|
82
90
|
"qbraid>=0.9.5",
|
|
@@ -192,7 +192,10 @@ class SquinWireMethodTable(interp.MethodTable):
|
|
|
192
192
|
|
|
193
193
|
origin_qubit = frame.get(stmt.qubit)
|
|
194
194
|
|
|
195
|
-
|
|
195
|
+
if isinstance(origin_qubit, AddressQubit):
|
|
196
|
+
return (AddressWire(origin_qubit=origin_qubit),)
|
|
197
|
+
else:
|
|
198
|
+
return (Address.top(),)
|
|
196
199
|
|
|
197
200
|
@interp.impl(squin.wire.Apply)
|
|
198
201
|
def apply(
|
|
@@ -201,14 +204,7 @@ class SquinWireMethodTable(interp.MethodTable):
|
|
|
201
204
|
frame: ForwardFrame[Address],
|
|
202
205
|
stmt: squin.wire.Apply,
|
|
203
206
|
):
|
|
204
|
-
|
|
205
|
-
origin_qubits = tuple(
|
|
206
|
-
[frame.get(input_elem).origin_qubit for input_elem in stmt.inputs]
|
|
207
|
-
)
|
|
208
|
-
new_address_wires = tuple(
|
|
209
|
-
[AddressWire(origin_qubit=origin_qubit) for origin_qubit in origin_qubits]
|
|
210
|
-
)
|
|
211
|
-
return new_address_wires
|
|
207
|
+
return frame.get_values(stmt.inputs)
|
|
212
208
|
|
|
213
209
|
|
|
214
210
|
@squin.qubit.dialect.register(key="qubit.address")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .analysis import FidelityAnalysis as FidelityAnalysis
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
from dataclasses import field
|
|
3
|
+
|
|
4
|
+
from kirin import ir
|
|
5
|
+
from kirin.lattice import EmptyLattice
|
|
6
|
+
from kirin.analysis import Forward
|
|
7
|
+
from kirin.interp.value import Successor
|
|
8
|
+
from kirin.analysis.forward import ForwardFrame
|
|
9
|
+
|
|
10
|
+
from ..address import AddressAnalysis
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class FidelityAnalysis(Forward):
|
|
14
|
+
"""
|
|
15
|
+
This analysis pass can be used to track the global addresses of qubits and wires.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
keys = ["circuit.fidelity"]
|
|
19
|
+
lattice = EmptyLattice
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
The fidelity of the gate set described by the analysed program. It reduces whenever a noise channel is encountered.
|
|
23
|
+
"""
|
|
24
|
+
gate_fidelity: float = 1.0
|
|
25
|
+
|
|
26
|
+
_current_gate_fidelity: float = field(init=False)
|
|
27
|
+
|
|
28
|
+
"""
|
|
29
|
+
The probabilities that each of the atoms in the register survive the duration of the analysed program. The order of the list follows the order they are in the register.
|
|
30
|
+
"""
|
|
31
|
+
atom_survival_probability: list[float] = field(init=False)
|
|
32
|
+
|
|
33
|
+
_current_atom_survival_probability: list[float] = field(init=False)
|
|
34
|
+
|
|
35
|
+
addr_frame: ForwardFrame = field(init=False)
|
|
36
|
+
|
|
37
|
+
def initialize(self):
|
|
38
|
+
super().initialize()
|
|
39
|
+
self._current_gate_fidelity = 1.0
|
|
40
|
+
self._current_atom_survival_probability = [
|
|
41
|
+
1.0 for _ in range(len(self.atom_survival_probability))
|
|
42
|
+
]
|
|
43
|
+
return self
|
|
44
|
+
|
|
45
|
+
def posthook_succ(self, frame: ForwardFrame, succ: Successor):
|
|
46
|
+
self.gate_fidelity *= self._current_gate_fidelity
|
|
47
|
+
for i, _current_survival in enumerate(self._current_atom_survival_probability):
|
|
48
|
+
self.atom_survival_probability[i] *= _current_survival
|
|
49
|
+
|
|
50
|
+
def eval_stmt_fallback(self, frame: ForwardFrame, stmt: ir.Statement):
|
|
51
|
+
# NOTE: default is to conserve fidelity, so do nothing here
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
def run_method(self, method: ir.Method, args: tuple[EmptyLattice, ...]):
|
|
55
|
+
return self.run_callable(method.code, (self.lattice.bottom(),) + args)
|
|
56
|
+
|
|
57
|
+
def run_analysis(
|
|
58
|
+
self, method: ir.Method, args: tuple | None = None, *, no_raise: bool = True
|
|
59
|
+
) -> tuple[ForwardFrame, Any]:
|
|
60
|
+
self._run_address_analysis(method, no_raise=no_raise)
|
|
61
|
+
return super().run_analysis(method, args, no_raise=no_raise)
|
|
62
|
+
|
|
63
|
+
def _run_address_analysis(self, method: ir.Method, no_raise: bool):
|
|
64
|
+
addr_analysis = AddressAnalysis(self.dialects)
|
|
65
|
+
addr_frame, _ = addr_analysis.run_analysis(method=method, no_raise=no_raise)
|
|
66
|
+
self.addr_frame = addr_frame
|
|
67
|
+
|
|
68
|
+
# NOTE: make sure we have as many probabilities as we have addresses
|
|
69
|
+
self.atom_survival_probability = [1.0] * addr_analysis.qubit_count
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
from typing import Any, Generic, TypeVar, ParamSpec
|
|
3
|
+
|
|
4
|
+
from kirin import ir
|
|
5
|
+
|
|
6
|
+
from bloqade.task import (
|
|
7
|
+
BatchFuture,
|
|
8
|
+
AbstractTask,
|
|
9
|
+
AbstractRemoteTask,
|
|
10
|
+
AbstractSimulatorTask,
|
|
11
|
+
DeviceTaskExpectMixin,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
Params = ParamSpec("Params")
|
|
15
|
+
RetType = TypeVar("RetType")
|
|
16
|
+
ObsType = TypeVar("ObsType")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
TaskType = TypeVar("TaskType", bound=AbstractTask)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class AbstractDevice(abc.ABC, Generic[TaskType]):
|
|
23
|
+
"""Abstract base class for devices. Defines the minimum interface for devices."""
|
|
24
|
+
|
|
25
|
+
@abc.abstractmethod
|
|
26
|
+
def task(
|
|
27
|
+
self,
|
|
28
|
+
kernel: ir.Method[Params, RetType],
|
|
29
|
+
args: tuple[Any, ...] = (),
|
|
30
|
+
kwargs: dict[str, Any] | None = None,
|
|
31
|
+
) -> TaskType:
|
|
32
|
+
"""Creates a remote task for the device."""
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
ExpectTaskType = TypeVar("ExpectTaskType", bound=DeviceTaskExpectMixin)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ExpectationDeviceMixin(AbstractDevice[ExpectTaskType]):
|
|
39
|
+
def expect(
|
|
40
|
+
self,
|
|
41
|
+
kernel: ir.Method[Params, RetType],
|
|
42
|
+
observable: ir.Method[[RetType], ObsType],
|
|
43
|
+
args: tuple[Any, ...] = (),
|
|
44
|
+
kwargs: dict[str, Any] | None = None,
|
|
45
|
+
*,
|
|
46
|
+
shots: int = 1,
|
|
47
|
+
) -> ObsType:
|
|
48
|
+
"""Returns the expectation value of the given observable after running the task."""
|
|
49
|
+
return self.task(kernel, args, kwargs).expect(observable, shots)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
RemoteTaskType = TypeVar("RemoteTaskType", bound=AbstractRemoteTask)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class AbstractRemoteDevice(AbstractDevice[RemoteTaskType]):
|
|
56
|
+
"""Abstract base class for remote devices."""
|
|
57
|
+
|
|
58
|
+
def run(
|
|
59
|
+
self,
|
|
60
|
+
kernel: ir.Method[Params, RetType],
|
|
61
|
+
args: tuple[Any, ...] = (),
|
|
62
|
+
kwargs: dict[str, Any] | None = None,
|
|
63
|
+
*,
|
|
64
|
+
shots: int = 1,
|
|
65
|
+
timeout: float | None = None,
|
|
66
|
+
) -> list[RetType]:
|
|
67
|
+
"""Runs the kernel and returns the result.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
kernel (ir.Method):
|
|
71
|
+
The kernel method to run.
|
|
72
|
+
args (tuple[Any, ...]):
|
|
73
|
+
Positional arguments to pass to the kernel method.
|
|
74
|
+
kwargs (dict[str, Any] | None):
|
|
75
|
+
Keyword arguments to pass to the kernel method.
|
|
76
|
+
shots (int):
|
|
77
|
+
The number of times to run the kernel method.
|
|
78
|
+
timeout (float | None):
|
|
79
|
+
Timeout in seconds for the asynchronous execution. If None, wait indefinitely.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
list[RetType]:
|
|
83
|
+
The result of the kernel method, if any.
|
|
84
|
+
|
|
85
|
+
"""
|
|
86
|
+
return self.task(kernel, args, kwargs).run(shots=shots, timeout=timeout)
|
|
87
|
+
|
|
88
|
+
def run_async(
|
|
89
|
+
self,
|
|
90
|
+
kernel: ir.Method[Params, RetType],
|
|
91
|
+
args: tuple[Any, ...] = (),
|
|
92
|
+
kwargs: dict[str, Any] | None = None,
|
|
93
|
+
*,
|
|
94
|
+
shots: int = 1,
|
|
95
|
+
) -> BatchFuture[RetType]:
|
|
96
|
+
"""Runs the kernel asynchronously and returns a Future object.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
kernel (ir.Method):
|
|
100
|
+
The kernel method to run.
|
|
101
|
+
args (tuple[Any, ...]):
|
|
102
|
+
Positional arguments to pass to the kernel method.
|
|
103
|
+
kwargs (dict[str, Any] | None):
|
|
104
|
+
Keyword arguments to pass to the kernel method.
|
|
105
|
+
shots (int):
|
|
106
|
+
The number of times to run the kernel method.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Future[list[RetType]]:
|
|
110
|
+
The Future for all executions of the kernel method.
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
"""
|
|
114
|
+
return self.task(kernel, args, kwargs).run_async(shots=shots)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
SimulatorTaskType = TypeVar("SimulatorTaskType", bound=AbstractSimulatorTask)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class AbstractSimulatorDevice(AbstractDevice[SimulatorTaskType]):
|
|
121
|
+
"""Abstract base class for simulator devices."""
|
|
122
|
+
|
|
123
|
+
def run(
|
|
124
|
+
self,
|
|
125
|
+
kernel: ir.Method[Params, RetType],
|
|
126
|
+
args: tuple[Any, ...] = (),
|
|
127
|
+
kwargs: dict[str, Any] | None = None,
|
|
128
|
+
) -> RetType:
|
|
129
|
+
"""Runs the kernel and returns the result."""
|
|
130
|
+
return self.task(kernel, args, kwargs).run()
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from kirin import interp
|
|
2
|
+
from kirin.lattice import EmptyLattice
|
|
3
|
+
|
|
4
|
+
from bloqade.analysis.fidelity import FidelityAnalysis
|
|
5
|
+
|
|
6
|
+
from .native import dialect as native
|
|
7
|
+
from .native.stmts import PauliChannel, CZPauliChannel, AtomLossChannel
|
|
8
|
+
from ..analysis.address import AddressQubit, AddressTuple
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@native.register(key="circuit.fidelity")
|
|
12
|
+
class FidelityMethodTable(interp.MethodTable):
|
|
13
|
+
|
|
14
|
+
@interp.impl(PauliChannel)
|
|
15
|
+
@interp.impl(CZPauliChannel)
|
|
16
|
+
def pauli_channel(
|
|
17
|
+
self,
|
|
18
|
+
interp: FidelityAnalysis,
|
|
19
|
+
frame: interp.Frame[EmptyLattice],
|
|
20
|
+
stmt: PauliChannel | CZPauliChannel,
|
|
21
|
+
):
|
|
22
|
+
probs = stmt.probabilities
|
|
23
|
+
try:
|
|
24
|
+
ps, ps_ctrl = probs
|
|
25
|
+
except ValueError:
|
|
26
|
+
(ps,) = probs
|
|
27
|
+
ps_ctrl = ()
|
|
28
|
+
|
|
29
|
+
p = sum(ps)
|
|
30
|
+
p_ctrl = sum(ps_ctrl)
|
|
31
|
+
|
|
32
|
+
# NOTE: fidelity is just the inverse probability of any noise to occur
|
|
33
|
+
fid = (1 - p) * (1 - p_ctrl)
|
|
34
|
+
|
|
35
|
+
interp._current_gate_fidelity *= fid
|
|
36
|
+
|
|
37
|
+
@interp.impl(AtomLossChannel)
|
|
38
|
+
def atom_loss(
|
|
39
|
+
self,
|
|
40
|
+
interp: FidelityAnalysis,
|
|
41
|
+
frame: interp.Frame[EmptyLattice],
|
|
42
|
+
stmt: AtomLossChannel,
|
|
43
|
+
):
|
|
44
|
+
# NOTE: since AtomLossChannel acts on IList[Qubit], we know the assigned address is a tuple
|
|
45
|
+
addresses: AddressTuple = interp.addr_frame.get(stmt.qargs)
|
|
46
|
+
|
|
47
|
+
# NOTE: get the corresponding index and reduce survival probability accordingly
|
|
48
|
+
for qbit_address in addresses.data:
|
|
49
|
+
assert isinstance(qbit_address, AddressQubit)
|
|
50
|
+
index = qbit_address.data
|
|
51
|
+
interp._current_atom_survival_probability[index] *= 1 - stmt.prob
|
|
@@ -102,10 +102,9 @@ class MoveNoiseModelABC(abc.ABC):
|
|
|
102
102
|
params: MoveNoiseParams = field(default_factory=MoveNoiseParams)
|
|
103
103
|
"""Parameters for calculating move noise."""
|
|
104
104
|
|
|
105
|
-
@classmethod
|
|
106
105
|
@abc.abstractmethod
|
|
107
106
|
def parallel_cz_errors(
|
|
108
|
-
|
|
107
|
+
self, ctrls: List[int], qargs: List[int], rest: List[int]
|
|
109
108
|
) -> Dict[Tuple[float, float, float, float], List[int]]:
|
|
110
109
|
"""Takes a set of ctrls and qargs and returns a noise model for all qubits."""
|
|
111
110
|
pass
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
|
|
3
3
|
from kirin import ir
|
|
4
|
-
from kirin.rewrite import abc, dce, walk,
|
|
4
|
+
from kirin.rewrite import abc, dce, walk, fixpoint
|
|
5
5
|
from kirin.passes.abc import Pass
|
|
6
6
|
|
|
7
7
|
from .stmts import PauliChannel, CZPauliChannel, AtomLossChannel
|
|
@@ -9,19 +9,19 @@ from ._dialect import dialect
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class RemoveNoiseRewrite(abc.RewriteRule):
|
|
12
|
-
def rewrite_Statement(self, node: ir.Statement) ->
|
|
12
|
+
def rewrite_Statement(self, node: ir.Statement) -> abc.RewriteResult:
|
|
13
13
|
if isinstance(node, (AtomLossChannel, PauliChannel, CZPauliChannel)):
|
|
14
14
|
node.delete()
|
|
15
|
-
return
|
|
15
|
+
return abc.RewriteResult(has_done_something=True)
|
|
16
16
|
|
|
17
|
-
return
|
|
17
|
+
return abc.RewriteResult()
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
@dataclass
|
|
21
21
|
class RemoveNoisePass(Pass):
|
|
22
22
|
name = "remove-noise"
|
|
23
23
|
|
|
24
|
-
def unsafe_run(self, mt: ir.Method) ->
|
|
24
|
+
def unsafe_run(self, mt: ir.Method) -> abc.RewriteResult:
|
|
25
25
|
delete_walk = walk.Walk(RemoveNoiseRewrite())
|
|
26
26
|
dce_walk = fixpoint.Fixpoint(walk.Walk(dce.DeadCodeElimination()))
|
|
27
27
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from typing import Tuple
|
|
2
|
+
|
|
1
3
|
from kirin import ir, types, lowering
|
|
2
4
|
from kirin.decl import info, statement
|
|
3
5
|
from kirin.dialects import ilist
|
|
@@ -7,25 +9,44 @@ from bloqade.qasm2.types import QubitType
|
|
|
7
9
|
from ._dialect import dialect
|
|
8
10
|
|
|
9
11
|
|
|
10
|
-
@statement
|
|
11
|
-
class
|
|
12
|
-
|
|
12
|
+
@statement
|
|
13
|
+
class NativeNoiseStmt(ir.Statement):
|
|
13
14
|
traits = frozenset({lowering.FromPythonCall()})
|
|
14
15
|
|
|
16
|
+
@property
|
|
17
|
+
def probabilities(self) -> Tuple[Tuple[float, ...], ...]:
|
|
18
|
+
raise NotImplementedError(f"Override the method in {type(self).__name__}")
|
|
19
|
+
|
|
20
|
+
def check(self):
|
|
21
|
+
for probs in self.probabilities:
|
|
22
|
+
self.check_probability(sum(probs))
|
|
23
|
+
for p in probs:
|
|
24
|
+
self.check_probability(p)
|
|
25
|
+
|
|
26
|
+
def check_probability(self, p: float):
|
|
27
|
+
if not 0 <= p <= 1:
|
|
28
|
+
raise ValueError(
|
|
29
|
+
f"Invalid noise probability encountered in {type(self).__name__}: {p}"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@statement(dialect=dialect)
|
|
34
|
+
class PauliChannel(NativeNoiseStmt):
|
|
15
35
|
px: float = info.attribute(types.Float)
|
|
16
36
|
py: float = info.attribute(types.Float)
|
|
17
37
|
pz: float = info.attribute(types.Float)
|
|
18
38
|
qargs: ir.SSAValue = info.argument(ilist.IListType[QubitType])
|
|
19
39
|
|
|
40
|
+
@property
|
|
41
|
+
def probabilities(self) -> Tuple[Tuple[float, ...], ...]:
|
|
42
|
+
return ((self.px, self.py, self.pz),)
|
|
43
|
+
|
|
20
44
|
|
|
21
45
|
NumQubits = types.TypeVar("NumQubits")
|
|
22
46
|
|
|
23
47
|
|
|
24
48
|
@statement(dialect=dialect)
|
|
25
|
-
class CZPauliChannel(
|
|
26
|
-
|
|
27
|
-
traits = frozenset({lowering.FromPythonCall()})
|
|
28
|
-
|
|
49
|
+
class CZPauliChannel(NativeNoiseStmt):
|
|
29
50
|
paired: bool = info.attribute(types.Bool)
|
|
30
51
|
px_ctrl: float = info.attribute(types.Float)
|
|
31
52
|
py_ctrl: float = info.attribute(types.Float)
|
|
@@ -36,11 +57,19 @@ class CZPauliChannel(ir.Statement):
|
|
|
36
57
|
ctrls: ir.SSAValue = info.argument(ilist.IListType[QubitType, NumQubits])
|
|
37
58
|
qargs: ir.SSAValue = info.argument(ilist.IListType[QubitType, NumQubits])
|
|
38
59
|
|
|
60
|
+
@property
|
|
61
|
+
def probabilities(self) -> Tuple[Tuple[float, ...], ...]:
|
|
62
|
+
return (
|
|
63
|
+
(self.px_ctrl, self.py_ctrl, self.pz_ctrl),
|
|
64
|
+
(self.px_qarg, self.py_qarg, self.pz_qarg),
|
|
65
|
+
)
|
|
39
66
|
|
|
40
|
-
@statement(dialect=dialect)
|
|
41
|
-
class AtomLossChannel(ir.Statement):
|
|
42
|
-
|
|
43
|
-
traits = frozenset({lowering.FromPythonCall()})
|
|
44
67
|
|
|
68
|
+
@statement(dialect=dialect)
|
|
69
|
+
class AtomLossChannel(NativeNoiseStmt):
|
|
45
70
|
prob: float = info.attribute(types.Float)
|
|
46
71
|
qargs: ir.SSAValue = info.argument(ilist.IListType[QubitType])
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def probabilities(self) -> Tuple[Tuple[float, ...], ...]:
|
|
75
|
+
return ((self.prob,),)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from .reg import (
|
|
2
2
|
CBitRef as CBitRef,
|
|
3
3
|
CRegister as CRegister,
|
|
4
|
-
PyQrackReg as PyQrackReg,
|
|
5
4
|
QubitState as QubitState,
|
|
6
5
|
Measurement as Measurement,
|
|
6
|
+
PyQrackWire as PyQrackWire,
|
|
7
7
|
PyQrackQubit as PyQrackQubit,
|
|
8
8
|
)
|
|
9
9
|
from .base import (
|
|
@@ -11,8 +11,14 @@ from .base import (
|
|
|
11
11
|
DynamicMemory as DynamicMemory,
|
|
12
12
|
PyQrackInterpreter as PyQrackInterpreter,
|
|
13
13
|
)
|
|
14
|
+
from .task import PyQrackSimulatorTask as PyQrackSimulatorTask
|
|
14
15
|
|
|
15
16
|
# NOTE: The following import is for registering the method tables
|
|
16
17
|
from .noise import native as native
|
|
17
|
-
from .qasm2 import uop as uop, core as core, parallel as parallel
|
|
18
|
+
from .qasm2 import uop as uop, core as core, glob as glob, parallel as parallel
|
|
19
|
+
from .squin import op as op, qubit as qubit
|
|
20
|
+
from .device import (
|
|
21
|
+
StackMemorySimulator as StackMemorySimulator,
|
|
22
|
+
DynamicMemorySimulator as DynamicMemorySimulator,
|
|
23
|
+
)
|
|
18
24
|
from .target import PyQrack as PyQrack
|
|
@@ -26,13 +26,28 @@ class PyQrackOptions(typing.TypedDict):
|
|
|
26
26
|
isOpenCL: bool
|
|
27
27
|
|
|
28
28
|
|
|
29
|
+
def _validate_pyqrack_options(options: PyQrackOptions) -> None:
|
|
30
|
+
if options["isBinaryDecisionTree"] and options["isStabilizerHybrid"]:
|
|
31
|
+
raise ValueError(
|
|
32
|
+
"Cannot use both isBinaryDecisionTree and isStabilizerHybrid at the same time."
|
|
33
|
+
)
|
|
34
|
+
elif options["isTensorNetwork"] and options["isBinaryDecisionTree"]:
|
|
35
|
+
raise ValueError(
|
|
36
|
+
"Cannot use both isTensorNetwork and isBinaryDecisionTree at the same time."
|
|
37
|
+
)
|
|
38
|
+
elif options["isTensorNetwork"] and options["isStabilizerHybrid"]:
|
|
39
|
+
raise ValueError(
|
|
40
|
+
"Cannot use both isTensorNetwork and isStabilizerHybrid at the same time."
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
29
44
|
def _default_pyqrack_args() -> PyQrackOptions:
|
|
30
45
|
return PyQrackOptions(
|
|
31
46
|
qubitCount=-1,
|
|
32
47
|
isTensorNetwork=False,
|
|
33
48
|
isSchmidtDecomposeMulti=True,
|
|
34
49
|
isSchmidtDecompose=True,
|
|
35
|
-
isStabilizerHybrid=
|
|
50
|
+
isStabilizerHybrid=False,
|
|
36
51
|
isBinaryDecisionTree=True,
|
|
37
52
|
isPaged=True,
|
|
38
53
|
isCpuGpuHybrid=True,
|
|
@@ -45,6 +60,9 @@ class MemoryABC(abc.ABC):
|
|
|
45
60
|
pyqrack_options: PyQrackOptions = field(default_factory=_default_pyqrack_args)
|
|
46
61
|
sim_reg: "QrackSimulator" = field(init=False)
|
|
47
62
|
|
|
63
|
+
def __post_init__(self):
|
|
64
|
+
_validate_pyqrack_options(self.pyqrack_options)
|
|
65
|
+
|
|
48
66
|
@abc.abstractmethod
|
|
49
67
|
def allocate(self, n_qubits: int) -> tuple[int, ...]:
|
|
50
68
|
"""Allocate `n_qubits` qubits and return their ids."""
|
|
@@ -115,10 +133,13 @@ class DynamicMemory(MemoryABC):
|
|
|
115
133
|
return tuple(range(start, start + n_qubits))
|
|
116
134
|
|
|
117
135
|
|
|
136
|
+
MemoryType = typing.TypeVar("MemoryType", bound=MemoryABC)
|
|
137
|
+
|
|
138
|
+
|
|
118
139
|
@dataclass
|
|
119
|
-
class PyQrackInterpreter(Interpreter):
|
|
140
|
+
class PyQrackInterpreter(Interpreter, typing.Generic[MemoryType]):
|
|
120
141
|
keys = ["pyqrack", "main"]
|
|
121
|
-
memory:
|
|
142
|
+
memory: MemoryType = field(kw_only=True)
|
|
122
143
|
rng_state: np.random.Generator = field(
|
|
123
144
|
default_factory=np.random.default_rng, kw_only=True
|
|
124
145
|
)
|