bloqade-circuit 0.4.0__tar.gz → 0.4.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.

Files changed (303) hide show
  1. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/PKG-INFO +1 -1
  2. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/pyproject.toml +1 -1
  3. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/__init__.py +1 -1
  4. bloqade_circuit-0.4.1/src/bloqade/pyqrack/squin/noise/__init__.py +1 -0
  5. bloqade_circuit-0.4.1/src/bloqade/pyqrack/squin/noise/native.py +72 -0
  6. bloqade_circuit-0.4.1/src/bloqade/squin/__init__.py +17 -0
  7. bloqade_circuit-0.4.1/src/bloqade/squin/cirq/__init__.py +89 -0
  8. bloqade_circuit-0.4.1/src/bloqade/squin/cirq/lowering.py +303 -0
  9. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/groups.py +3 -3
  10. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/noise/__init__.py +3 -1
  11. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/noise/_wrapper.py +7 -3
  12. bloqade_circuit-0.4.1/src/bloqade/squin/noise/rewrite.py +111 -0
  13. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/noise/stmts.py +21 -16
  14. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/op/stmts.py +1 -12
  15. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/op/types.py +2 -0
  16. bloqade_circuit-0.4.1/test/pyqrack/squin/test_noise.py +159 -0
  17. bloqade_circuit-0.4.1/test/squin/cirq/test_cirq_to_squin.py +161 -0
  18. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/uv.lock +1 -1
  19. bloqade_circuit-0.4.0/src/bloqade/squin/__init__.py +0 -8
  20. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/.github/dependabot.yml +0 -0
  21. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/.github/workflows/ci.yml +0 -0
  22. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/.github/workflows/isort.yml +0 -0
  23. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/.github/workflows/lint.yml +0 -0
  24. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/.github/workflows/release.yml +0 -0
  25. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/.gitignore +0 -0
  26. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/.pre-commit-config.yaml +0 -0
  27. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/LICENSE +0 -0
  28. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/README.md +0 -0
  29. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/_typos.toml +0 -0
  30. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/justfile +0 -0
  31. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/analysis/__init__.py +0 -0
  32. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/analysis/address/__init__.py +0 -0
  33. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/analysis/address/analysis.py +0 -0
  34. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/analysis/address/impls.py +0 -0
  35. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/analysis/address/lattice.py +0 -0
  36. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/analysis/fidelity/__init__.py +0 -0
  37. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/analysis/fidelity/analysis.py +0 -0
  38. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/device.py +0 -0
  39. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/base.py +0 -0
  40. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/device.py +0 -0
  41. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/noise/__init__.py +0 -0
  42. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/noise/native.py +0 -0
  43. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/qasm2/__init__.py +0 -0
  44. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/qasm2/core.py +0 -0
  45. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/qasm2/glob.py +0 -0
  46. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/qasm2/parallel.py +0 -0
  47. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/qasm2/uop.py +0 -0
  48. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/reg.py +0 -0
  49. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/squin/__init__.py +0 -0
  50. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/squin/op.py +0 -0
  51. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/squin/qubit.py +0 -0
  52. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/squin/runtime.py +0 -0
  53. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/squin/wire.py +0 -0
  54. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/target.py +0 -0
  55. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/pyqrack/task.py +0 -0
  56. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/__init__.py +0 -0
  57. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/_qasm_loading.py +0 -0
  58. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/_wrappers.py +0 -0
  59. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/__init__.py +0 -0
  60. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/core/__init__.py +0 -0
  61. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/core/_dialect.py +0 -0
  62. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/core/_emit.py +0 -0
  63. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/core/_typeinfer.py +0 -0
  64. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/core/address.py +0 -0
  65. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/core/stmts.py +0 -0
  66. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/expr/__init__.py +0 -0
  67. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/expr/_dialect.py +0 -0
  68. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/expr/_emit.py +0 -0
  69. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/expr/_from_python.py +0 -0
  70. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/expr/_interp.py +0 -0
  71. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/expr/stmts.py +0 -0
  72. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/glob.py +0 -0
  73. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/indexing.py +0 -0
  74. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/inline.py +0 -0
  75. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/noise/__init__.py +0 -0
  76. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/noise/_dialect.py +0 -0
  77. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/noise/fidelity.py +0 -0
  78. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/noise/model.py +0 -0
  79. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/noise/stmts.py +0 -0
  80. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/parallel.py +0 -0
  81. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/uop/__init__.py +0 -0
  82. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/uop/_dialect.py +0 -0
  83. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/uop/_emit.py +0 -0
  84. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/uop/schedule.py +0 -0
  85. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/dialects/uop/stmts.py +0 -0
  86. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/emit/__init__.py +0 -0
  87. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/emit/base.py +0 -0
  88. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/emit/gate.py +0 -0
  89. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/emit/impls/__init__.py +0 -0
  90. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/emit/impls/noise.py +0 -0
  91. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/emit/main.py +0 -0
  92. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/emit/target.py +0 -0
  93. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/glob.py +0 -0
  94. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/groups.py +0 -0
  95. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/noise.py +0 -0
  96. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/parallel.py +0 -0
  97. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/parse/__init__.py +0 -0
  98. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/parse/ast.py +0 -0
  99. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/parse/build.py +0 -0
  100. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/parse/lowering.py +0 -0
  101. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/parse/parser.py +0 -0
  102. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/parse/print.py +0 -0
  103. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/parse/qasm2.lark +0 -0
  104. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/parse/visitor.py +0 -0
  105. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/parse/visitor.pyi +0 -0
  106. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/passes/__init__.py +0 -0
  107. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/passes/fold.py +0 -0
  108. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/passes/glob.py +0 -0
  109. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/passes/lift_qubits.py +0 -0
  110. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/passes/noise.py +0 -0
  111. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/passes/parallel.py +0 -0
  112. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/passes/py2qasm.py +0 -0
  113. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/passes/qasm2py.py +0 -0
  114. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/passes/unroll_if.py +0 -0
  115. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/rewrite/__init__.py +0 -0
  116. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/rewrite/desugar.py +0 -0
  117. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/rewrite/glob.py +0 -0
  118. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/rewrite/insert_qubits.py +0 -0
  119. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/rewrite/native_gates.py +0 -0
  120. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/rewrite/noise/__init__.py +0 -0
  121. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/rewrite/noise/heuristic_noise.py +0 -0
  122. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/rewrite/noise/remove_noise.py +0 -0
  123. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/rewrite/parallel_to_uop.py +0 -0
  124. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/rewrite/register.py +0 -0
  125. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/rewrite/split_ifs.py +0 -0
  126. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/rewrite/uop_to_parallel.py +0 -0
  127. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qasm2/types.py +0 -0
  128. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qbraid/__init__.py +0 -0
  129. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qbraid/lowering.py +0 -0
  130. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qbraid/schema.py +0 -0
  131. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qbraid/simulation_result.py +0 -0
  132. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/qbraid/target.py +0 -0
  133. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/analysis/__init__.py +0 -0
  134. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/analysis/nsites/__init__.py +0 -0
  135. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/analysis/nsites/analysis.py +0 -0
  136. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/analysis/nsites/impls.py +0 -0
  137. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/analysis/nsites/lattice.py +0 -0
  138. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/analysis/schedule.py +0 -0
  139. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/lowering.py +0 -0
  140. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/noise/_dialect.py +0 -0
  141. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/op/__init__.py +0 -0
  142. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/op/_dialect.py +0 -0
  143. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/op/_wrapper.py +0 -0
  144. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/op/number.py +0 -0
  145. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/op/rewrite.py +0 -0
  146. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/op/stdlib.py +0 -0
  147. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/op/traits.py +0 -0
  148. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/passes/__init__.py +0 -0
  149. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/passes/stim.py +0 -0
  150. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/qubit.py +0 -0
  151. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/rewrite/__init__.py +0 -0
  152. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/rewrite/desugar.py +0 -0
  153. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/rewrite/qubit_to_stim.py +0 -0
  154. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/rewrite/squin_measure.py +0 -0
  155. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/rewrite/stim_rewrite_util.py +0 -0
  156. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/rewrite/wire_identity_elimination.py +0 -0
  157. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/rewrite/wire_to_stim.py +0 -0
  158. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/rewrite/wrap_analysis.py +0 -0
  159. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/squin/wire.py +0 -0
  160. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/__init__.py +0 -0
  161. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/_wrappers.py +0 -0
  162. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/__init__.py +0 -0
  163. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/auxiliary/__init__.py +0 -0
  164. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/auxiliary/_dialect.py +0 -0
  165. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/auxiliary/emit.py +0 -0
  166. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/auxiliary/interp.py +0 -0
  167. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/auxiliary/lowering.py +0 -0
  168. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/auxiliary/stmts/__init__.py +0 -0
  169. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/auxiliary/stmts/annotate.py +0 -0
  170. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/auxiliary/stmts/const.py +0 -0
  171. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/auxiliary/types.py +0 -0
  172. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/collapse/__init__.py +0 -0
  173. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/collapse/_dialect.py +0 -0
  174. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/collapse/emit_str.py +0 -0
  175. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/collapse/stmts/__init__.py +0 -0
  176. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/collapse/stmts/measure.py +0 -0
  177. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/collapse/stmts/pp_measure.py +0 -0
  178. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/collapse/stmts/reset.py +0 -0
  179. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/gate/__init__.py +0 -0
  180. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/gate/_dialect.py +0 -0
  181. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/gate/emit.py +0 -0
  182. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/gate/stmts/__init__.py +0 -0
  183. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/gate/stmts/base.py +0 -0
  184. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/gate/stmts/clifford_1q.py +0 -0
  185. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/gate/stmts/clifford_2q.py +0 -0
  186. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/gate/stmts/control_2q.py +0 -0
  187. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/gate/stmts/pp.py +0 -0
  188. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/noise/__init__.py +0 -0
  189. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/noise/_dialect.py +0 -0
  190. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/noise/emit.py +0 -0
  191. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/dialects/noise/stmts.py +0 -0
  192. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/emit/__init__.py +0 -0
  193. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/emit/stim_str.py +0 -0
  194. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/groups.py +0 -0
  195. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/parse/__init__.py +0 -0
  196. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/stim/parse/lowering.py +0 -0
  197. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/task.py +0 -0
  198. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/test_utils.py +0 -0
  199. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/types.py +0 -0
  200. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/visual/__init__.py +0 -0
  201. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/visual/animation/__init__.py +0 -0
  202. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/visual/animation/animate.py +0 -0
  203. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/visual/animation/base.py +0 -0
  204. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/visual/animation/gate_event.py +0 -0
  205. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/visual/animation/runtime/__init__.py +0 -0
  206. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/visual/animation/runtime/aod.py +0 -0
  207. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/visual/animation/runtime/atoms.py +0 -0
  208. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/visual/animation/runtime/ppoly.py +0 -0
  209. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/visual/animation/runtime/qpustate.py +0 -0
  210. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/src/bloqade/visual/animation/runtime/utils.py +0 -0
  211. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/__init__.py +0 -0
  212. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/analysis/address/test_analysis.py +0 -0
  213. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/analysis/address/test_lattice.py +0 -0
  214. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/analysis/fidelity/test_fidelity.py +0 -0
  215. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/pyqrack/__init__.py +0 -0
  216. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/pyqrack/runtime/__init__.py +0 -0
  217. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/pyqrack/runtime/noise/__init__.py +0 -0
  218. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/pyqrack/runtime/noise/qasm2/test_loss.py +0 -0
  219. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/pyqrack/runtime/noise/qasm2/test_pauli.py +0 -0
  220. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/pyqrack/runtime/test_dyn_memory.py +0 -0
  221. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/pyqrack/runtime/test_qrack.py +0 -0
  222. /bloqade_circuit-0.4.0/test/pyqrack/test_squin.py → /bloqade_circuit-0.4.1/test/pyqrack/squin/test_kernel.py +0 -0
  223. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/pyqrack/test_target.py +0 -0
  224. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/__init__.py +0 -0
  225. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/analysis/test_dag.py +0 -0
  226. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/emit/test_extended.py +0 -0
  227. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/emit/test_extended_noise.py +0 -0
  228. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/emit/test_qasm2.py +0 -0
  229. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/emit/test_qasm2_emit.py +0 -0
  230. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/__init__.py +0 -0
  231. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/invalid_programs/invalid_if.qasm +0 -0
  232. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/programs/README.md +0 -0
  233. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/programs/global.qasm +0 -0
  234. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/programs/iqft1.qasm +0 -0
  235. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/programs/main.qasm +0 -0
  236. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/programs/noise.qasm +0 -0
  237. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/programs/para.qasm +0 -0
  238. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/programs/process_tomo.qasm +0 -0
  239. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/programs/qelib1.inc +0 -0
  240. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/programs/qft.qasm +0 -0
  241. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/programs/qft2.qasm +0 -0
  242. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/programs/rb.qasm +0 -0
  243. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/programs/rep_code.qasm +0 -0
  244. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/programs/ripple_carry_adder.qasm +0 -0
  245. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/programs/tele.qasm +0 -0
  246. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/programs/valid_if.qasm +0 -0
  247. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/test_ast.py +0 -0
  248. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/parse/test_roundtrip.py +0 -0
  249. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/passes/__init__.py +0 -0
  250. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/passes/test_global_to_parallel.py +0 -0
  251. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/passes/test_global_to_uop.py +0 -0
  252. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/passes/test_heuristic_noise.py +0 -0
  253. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/passes/test_parallel_to_uop.py +0 -0
  254. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/passes/test_qasm2py.py +0 -0
  255. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/passes/test_unroll_if.py +0 -0
  256. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/passes/test_uop_to_parallel.py +0 -0
  257. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/test_count.py +0 -0
  258. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/test_inline.py +0 -0
  259. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/test_lowering.py +0 -0
  260. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/test_native.py +0 -0
  261. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qasm2/test_two2one.py +0 -0
  262. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qbraid/__init__.py +0 -0
  263. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qbraid/test_clean_circuit.py +0 -0
  264. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qbraid/test_lowering.py +0 -0
  265. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/qbraid/test_target.py +0 -0
  266. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/sample/__init__.py +0 -0
  267. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/sample/test_noise_model.py +0 -0
  268. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/squin/analysis/test_nsites_analysis.py +0 -0
  269. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/squin/op/test_reset.py +0 -0
  270. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/squin/stim/test_stim.py +0 -0
  271. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/squin/test_constprop.py +0 -0
  272. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/squin/test_mult_rewrite.py +0 -0
  273. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/squin/test_sugar.py +0 -0
  274. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/__init__.py +0 -0
  275. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/dialects/__init__.py +0 -0
  276. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/dialects/stim/__init__.py +0 -0
  277. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/dialects/stim/emit/__init__.py +0 -0
  278. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/dialects/stim/emit/base.py +0 -0
  279. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/dialects/stim/emit/test_stim_1q.py +0 -0
  280. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/dialects/stim/emit/test_stim_ctrl.py +0 -0
  281. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/dialects/stim/emit/test_stim_detector.py +0 -0
  282. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/dialects/stim/emit/test_stim_meas.py +0 -0
  283. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/dialects/stim/emit/test_stim_noise.py +0 -0
  284. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/dialects/stim/emit/test_stim_obs_inc.py +0 -0
  285. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/dialects/stim/emit/test_stim_ppmeas.py +0 -0
  286. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/dialects/stim/emit/test_stim_qubit_coords.py +0 -0
  287. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/dialects/stim/emit/test_stim_spp.py +0 -0
  288. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/dialects/stim/test_stim_circuits.py +0 -0
  289. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/dialects/stim/test_stim_const.py +0 -0
  290. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/parse/__init__.py +0 -0
  291. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/parse/base.py +0 -0
  292. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/parse/test_parse.py +0 -0
  293. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/parse/test_parse_clifford.py +0 -0
  294. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/parse/test_parse_control.py +0 -0
  295. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/parse/test_parse_custom.py +0 -0
  296. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/parse/test_parse_noise.py +0 -0
  297. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/parse/test_parse_spp.py +0 -0
  298. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/wrapper/__init__.py +0 -0
  299. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/stim/wrapper/test_wrapper.py +0 -0
  300. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/test_serialization.py +0 -0
  301. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/test_zone_model.py +0 -0
  302. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/visual/__init__.py +0 -0
  303. {bloqade_circuit-0.4.0 → bloqade_circuit-0.4.1}/test/visual/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bloqade-circuit
3
- Version: 0.4.0
3
+ Version: 0.4.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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "bloqade-circuit"
3
- version = "0.4.0"
3
+ version = "0.4.1"
4
4
  description = "The software development toolkit for neutral atom arrays."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -16,7 +16,7 @@ from .task import PyQrackSimulatorTask as PyQrackSimulatorTask
16
16
  # NOTE: The following import is for registering the method tables
17
17
  from .noise import native as native
18
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
19
+ from .squin import op as op, noise as noise, qubit as qubit
20
20
  from .device import (
21
21
  StackMemorySimulator as StackMemorySimulator,
22
22
  DynamicMemorySimulator as DynamicMemorySimulator,
@@ -0,0 +1 @@
1
+ from . import native as native
@@ -0,0 +1,72 @@
1
+ import random
2
+ import typing
3
+ from dataclasses import dataclass
4
+
5
+ from kirin import interp
6
+ from kirin.dialects import ilist
7
+
8
+ from bloqade.pyqrack import QubitState, PyQrackQubit, PyQrackInterpreter
9
+ from bloqade.squin.noise.stmts import QubitLoss, StochasticUnitaryChannel
10
+ from bloqade.squin.noise._dialect import dialect as squin_noise_dialect
11
+
12
+ from ..runtime import OperatorRuntimeABC
13
+
14
+
15
+ @dataclass(frozen=True)
16
+ class StochasticUnitaryChannelRuntime(OperatorRuntimeABC):
17
+ operators: ilist.IList[OperatorRuntimeABC, typing.Any]
18
+ probabilities: ilist.IList[float, typing.Any]
19
+
20
+ @property
21
+ def n_sites(self) -> int:
22
+ n = self.operators[0].n_sites
23
+ for op in self.operators[1:]:
24
+ assert (
25
+ op.n_sites == n
26
+ ), "Encountered a stochastic unitary channel with operators of different size!"
27
+ return n
28
+
29
+ def apply(self, *qubits: PyQrackQubit, adjoint: bool = False) -> None:
30
+ # NOTE: probabilities don't necessarily sum to 1; could be no noise event should occur
31
+ p_no_op = 1 - sum(self.probabilities)
32
+ if random.uniform(0.0, 1.0) < p_no_op:
33
+ return
34
+
35
+ selected_ops = random.choices(self.operators, weights=self.probabilities)
36
+ for op in selected_ops:
37
+ op.apply(*qubits, adjoint=adjoint)
38
+
39
+
40
+ @dataclass(frozen=True)
41
+ class QubitLossRuntime(OperatorRuntimeABC):
42
+ p: float
43
+
44
+ @property
45
+ def n_sites(self) -> int:
46
+ return 1
47
+
48
+ def apply(self, qubit: PyQrackQubit, adjoint: bool = False) -> None:
49
+ if random.uniform(0.0, 1.0) < self.p:
50
+ qubit.state = QubitState.Lost
51
+
52
+
53
+ @squin_noise_dialect.register(key="pyqrack")
54
+ class PyQrackMethods(interp.MethodTable):
55
+ @interp.impl(StochasticUnitaryChannel)
56
+ def stochastic_unitary_channel(
57
+ self,
58
+ interp: PyQrackInterpreter,
59
+ frame: interp.Frame,
60
+ stmt: StochasticUnitaryChannel,
61
+ ):
62
+ operators = frame.get(stmt.operators)
63
+ probabilities = frame.get(stmt.probabilities)
64
+
65
+ return (StochasticUnitaryChannelRuntime(operators, probabilities),)
66
+
67
+ @interp.impl(QubitLoss)
68
+ def qubit_loss(
69
+ self, interp: PyQrackInterpreter, frame: interp.Frame, stmt: QubitLoss
70
+ ):
71
+ p = frame.get(stmt.p)
72
+ return (QubitLossRuntime(p),)
@@ -0,0 +1,17 @@
1
+ from . import (
2
+ op as op,
3
+ wire as wire,
4
+ noise as noise,
5
+ qubit as qubit,
6
+ lowering as lowering,
7
+ )
8
+ from .groups import wired as wired, kernel as kernel
9
+
10
+ try:
11
+ # NOTE: make sure optional cirq dependency is installed
12
+ import cirq as cirq_package # noqa: F401
13
+ except ImportError:
14
+ pass
15
+ else:
16
+ from . import cirq as cirq
17
+ from .cirq import load_circuit as load_circuit
@@ -0,0 +1,89 @@
1
+ from typing import Any
2
+
3
+ import cirq
4
+ from kirin import ir, types
5
+ from kirin.dialects import func
6
+
7
+ from . import lowering as lowering
8
+ from .. import kernel
9
+ from .lowering import Squin
10
+
11
+
12
+ def load_circuit(
13
+ circuit: cirq.Circuit,
14
+ kernel_name: str = "main",
15
+ dialects: ir.DialectGroup = kernel,
16
+ globals: dict[str, Any] | None = None,
17
+ file: str | None = None,
18
+ lineno_offset: int = 0,
19
+ col_offset: int = 0,
20
+ compactify: bool = True,
21
+ ):
22
+ """Converts a cirq.Circuit object into a squin kernel.
23
+
24
+ Args:
25
+ circuit (cirq.Circuit): The circuit to load.
26
+
27
+ Keyword Args:
28
+ kernel_name (str): The name of the kernel to load. Defaults to "main".
29
+ dialects (ir.DialectGroup | None): The dialects to use. Defaults to `squin.kernel`.
30
+ globals (dict[str, Any] | None): The global variables to use. Defaults to None.
31
+ file (str | None): The file name for error reporting. Defaults to None.
32
+ lineno_offset (int): The line number offset for error reporting. Defaults to 0.
33
+ col_offset (int): The column number offset for error reporting. Defaults to 0.
34
+ compactify (bool): Whether to compactify the output. Defaults to True.
35
+
36
+ Example:
37
+
38
+ ```python
39
+ # from cirq's "hello qubit" example
40
+ import cirq
41
+ from bloqade import squin
42
+
43
+ # Pick a qubit.
44
+ qubit = cirq.GridQubit(0, 0)
45
+
46
+ # Create a circuit.
47
+ circuit = cirq.Circuit(
48
+ cirq.X(qubit)**0.5, # Square root of NOT.
49
+ cirq.measure(qubit, key='m') # Measurement.
50
+ )
51
+
52
+ # load the circuit as squin
53
+ main = squin.load_circuit(circuit)
54
+
55
+ # print the resulting IR
56
+ main.print()
57
+ ```
58
+ """
59
+
60
+ target = Squin(dialects=dialects, circuit=circuit)
61
+ body = target.run(
62
+ circuit,
63
+ source=str(circuit), # TODO: proper source string
64
+ file=file,
65
+ globals=globals,
66
+ lineno_offset=lineno_offset,
67
+ col_offset=col_offset,
68
+ compactify=compactify,
69
+ )
70
+
71
+ # NOTE: no return value
72
+ return_value = func.ConstantNone()
73
+ body.blocks[0].stmts.append(return_value)
74
+ body.blocks[0].stmts.append(func.Return(value_or_stmt=return_value))
75
+
76
+ code = func.Function(
77
+ sym_name=kernel_name,
78
+ signature=func.Signature((), types.NoneType),
79
+ body=body,
80
+ )
81
+
82
+ return ir.Method(
83
+ mod=None,
84
+ py_func=None,
85
+ sym_name=kernel_name,
86
+ arg_names=[],
87
+ dialects=dialects,
88
+ code=code,
89
+ )
@@ -0,0 +1,303 @@
1
+ import math
2
+ from typing import Any
3
+ from dataclasses import field, dataclass
4
+
5
+ import cirq
6
+ from kirin import ir, lowering
7
+ from kirin.rewrite import Walk, CFGCompactify
8
+ from kirin.dialects import py, ilist
9
+
10
+ from .. import op, noise, qubit
11
+
12
+ CirqNode = cirq.Circuit | cirq.Moment | cirq.Gate | cirq.Qid | cirq.Operation
13
+
14
+ DecomposeNode = (
15
+ cirq.SwapPowGate
16
+ | cirq.ISwapPowGate
17
+ | cirq.PhasedXPowGate
18
+ | cirq.PhasedXZGate
19
+ | cirq.CSwapGate
20
+ )
21
+
22
+
23
+ @dataclass
24
+ class Squin(lowering.LoweringABC[CirqNode]):
25
+ """Lower a cirq.Circuit object to a squin kernel"""
26
+
27
+ circuit: cirq.Circuit
28
+ qreg: qubit.New = field(init=False)
29
+ qreg_index: dict[cirq.Qid, int] = field(init=False, default_factory=dict)
30
+ next_qreg_index: int = field(init=False, default=0)
31
+
32
+ def lower_qubit_getindex(self, state: lowering.State[CirqNode], qid: cirq.Qid):
33
+ index = self.qreg_index.get(qid)
34
+
35
+ if index is None:
36
+ index = self.next_qreg_index
37
+ self.qreg_index[qid] = index
38
+ self.next_qreg_index += 1
39
+
40
+ index_ssa = state.current_frame.push(py.Constant(index)).result
41
+ qbit_getitem = state.current_frame.push(py.GetItem(self.qreg.result, index_ssa))
42
+ return qbit_getitem.result
43
+
44
+ def lower_qubit_getindices(
45
+ self, state: lowering.State[CirqNode], qids: list[cirq.Qid]
46
+ ):
47
+ qbits_getitem = [self.lower_qubit_getindex(state, qid) for qid in qids]
48
+ qbits_stmt = ilist.New(values=qbits_getitem)
49
+ qbits_result = state.current_frame.get(qbits_stmt.name)
50
+
51
+ if qbits_result is not None:
52
+ return qbits_result
53
+
54
+ state.current_frame.push(qbits_stmt)
55
+ return qbits_stmt.result
56
+
57
+ def run(
58
+ self,
59
+ stmt: CirqNode,
60
+ *,
61
+ source: str | None = None,
62
+ globals: dict[str, Any] | None = None,
63
+ file: str | None = None,
64
+ lineno_offset: int = 0,
65
+ col_offset: int = 0,
66
+ compactify: bool = True,
67
+ ) -> ir.Region:
68
+
69
+ state = lowering.State(
70
+ self,
71
+ file=file,
72
+ lineno_offset=lineno_offset,
73
+ col_offset=col_offset,
74
+ )
75
+
76
+ with state.frame(
77
+ [stmt],
78
+ globals=globals,
79
+ finalize_next=False,
80
+ ) as frame:
81
+ # NOTE: create a global register of qubits first
82
+ # TODO: can there be a circuit without qubits?
83
+ n_qubits = cirq.num_qubits(self.circuit)
84
+ n = frame.push(py.Constant(n_qubits))
85
+ self.qreg = frame.push(qubit.New(n_qubits=n.result))
86
+
87
+ self.visit(state, stmt)
88
+
89
+ if compactify:
90
+ Walk(CFGCompactify()).rewrite(frame.curr_region)
91
+
92
+ region = frame.curr_region
93
+
94
+ return region
95
+
96
+ def visit(self, state: lowering.State[CirqNode], node: CirqNode) -> lowering.Result:
97
+ name = node.__class__.__name__
98
+ return getattr(self, f"visit_{name}", self.generic_visit)(state, node)
99
+
100
+ def generic_visit(self, state: lowering.State[CirqNode], node: CirqNode):
101
+ if isinstance(node, CirqNode):
102
+ raise lowering.BuildError(
103
+ f"Cannot lower {node.__class__.__name__} node: {node}"
104
+ )
105
+ raise lowering.BuildError(
106
+ f"Unexpected `{node.__class__.__name__}` node: {repr(node)} is not an AST node"
107
+ )
108
+
109
+ def lower_literal(self, state: lowering.State[CirqNode], value) -> ir.SSAValue:
110
+ raise lowering.BuildError("Literals not supported in cirq circuit")
111
+
112
+ def lower_global(
113
+ self, state: lowering.State[CirqNode], node: CirqNode
114
+ ) -> lowering.LoweringABC.Result:
115
+ raise lowering.BuildError("Literals not supported in cirq circuit")
116
+
117
+ def visit_Circuit(
118
+ self, state: lowering.State[CirqNode], node: cirq.Circuit
119
+ ) -> lowering.Result:
120
+ for moment in node:
121
+ state.lower(moment)
122
+
123
+ def visit_Moment(
124
+ self, state: lowering.State[CirqNode], node: cirq.Moment
125
+ ) -> lowering.Result:
126
+ for op_ in node.operations:
127
+ state.lower(op_)
128
+
129
+ def visit_GateOperation(
130
+ self, state: lowering.State[CirqNode], node: cirq.GateOperation
131
+ ):
132
+ if isinstance(node.gate, cirq.MeasurementGate):
133
+ # NOTE: special dispatch here, since measurement is a gate + a qubit in cirq,
134
+ # but a single statement in squin
135
+ return self.lower_measurement(state, node)
136
+
137
+ if isinstance(node.gate, DecomposeNode):
138
+ # NOTE: easier to decompose these, but for that we need the qubits too,
139
+ # so we need to do this within this method
140
+ for subnode in cirq.decompose_once(node):
141
+ state.lower(subnode)
142
+ return
143
+
144
+ op_ = state.lower(node.gate).expect_one()
145
+ qbits = self.lower_qubit_getindices(state, node.qubits)
146
+ return state.current_frame.push(qubit.Apply(operator=op_, qubits=qbits))
147
+
148
+ def lower_measurement(
149
+ self, state: lowering.State[CirqNode], node: cirq.GateOperation
150
+ ):
151
+ if len(node.qubits) == 1:
152
+ qbit = self.lower_qubit_getindex(state, node.qubits[0])
153
+ return state.current_frame.push(qubit.MeasureQubit(qbit))
154
+
155
+ qbits = self.lower_qubit_getindices(state, node.qubits)
156
+ return state.current_frame.push(qubit.MeasureQubitList(qbits))
157
+
158
+ def visit_SingleQubitPauliStringGateOperation(
159
+ self,
160
+ state: lowering.State[CirqNode],
161
+ node: cirq.SingleQubitPauliStringGateOperation,
162
+ ):
163
+
164
+ match node.pauli:
165
+ case cirq.X:
166
+ op_ = op.stmts.X()
167
+ case cirq.Y:
168
+ op_ = op.stmts.Y()
169
+ case cirq.Z:
170
+ op_ = op.stmts.Z()
171
+ case cirq.I:
172
+ op_ = op.stmts.Identity(sites=1)
173
+ case _:
174
+ raise lowering.BuildError(f"Unexpected Pauli operation {node.pauli}")
175
+
176
+ state.current_frame.push(op_)
177
+ qargs = self.lower_qubit_getindices(state, [node.qubit])
178
+ return state.current_frame.push(qubit.Apply(op_.result, qargs))
179
+
180
+ def visit_HPowGate(self, state: lowering.State[CirqNode], node: cirq.HPowGate):
181
+ if node.exponent == 1:
182
+ return state.current_frame.push(op.stmts.H())
183
+
184
+ return state.lower(node.in_su2())
185
+
186
+ def visit_XPowGate(self, state: lowering.State[CirqNode], node: cirq.XPowGate):
187
+ if node.exponent == 1:
188
+ return state.current_frame.push(op.stmts.X())
189
+
190
+ return self.visit(state, node.in_su2())
191
+
192
+ def visit_YPowGate(self, state: lowering.State[CirqNode], node: cirq.YPowGate):
193
+ if node.exponent == 1:
194
+ return state.current_frame.push(op.stmts.Y())
195
+
196
+ return self.visit(state, node.in_su2())
197
+
198
+ def visit_ZPowGate(self, state: lowering.State[CirqNode], node: cirq.ZPowGate):
199
+ if node.exponent == 0.5:
200
+ return state.current_frame.push(op.stmts.S())
201
+
202
+ if node.exponent == 0.25:
203
+ return state.current_frame.push(op.stmts.T())
204
+
205
+ if node.exponent == 1:
206
+ return state.current_frame.push(op.stmts.Z())
207
+
208
+ # NOTE: just for the Z gate, an arbitrary exponent is equivalent to the ShiftOp
209
+ t = node.exponent
210
+ theta = state.current_frame.push(py.Constant(math.pi * t))
211
+ return state.current_frame.push(op.stmts.ShiftOp(theta=theta.result))
212
+
213
+ def visit_Rx(self, state: lowering.State[CirqNode], node: cirq.Rx):
214
+ x = state.current_frame.push(op.stmts.X())
215
+ angle = state.current_frame.push(py.Constant(value=math.pi * node.exponent))
216
+ return state.current_frame.push(op.stmts.Rot(axis=x.result, angle=angle.result))
217
+
218
+ def visit_Ry(self, state: lowering.State[CirqNode], node: cirq.Ry):
219
+ y = state.current_frame.push(op.stmts.Y())
220
+ angle = state.current_frame.push(py.Constant(value=math.pi * node.exponent))
221
+ return state.current_frame.push(op.stmts.Rot(axis=y.result, angle=angle.result))
222
+
223
+ def visit_Rz(self, state: lowering.State[CirqNode], node: cirq.Rz):
224
+ z = state.current_frame.push(op.stmts.Z())
225
+ angle = state.current_frame.push(py.Constant(value=math.pi * node.exponent))
226
+ return state.current_frame.push(op.stmts.Rot(axis=z.result, angle=angle.result))
227
+
228
+ def visit_CXPowGate(self, state: lowering.State[CirqNode], node: cirq.CXPowGate):
229
+ x = state.lower(cirq.XPowGate(exponent=node.exponent)).expect_one()
230
+ return state.current_frame.push(op.stmts.Control(x, n_controls=1))
231
+
232
+ def visit_CZPowGate(self, state: lowering.State[CirqNode], node: cirq.CZPowGate):
233
+ z = state.lower(cirq.ZPowGate(exponent=node.exponent)).expect_one()
234
+ return state.current_frame.push(op.stmts.Control(z, n_controls=1))
235
+
236
+ def visit_ControlledOperation(
237
+ self, state: lowering.State[CirqNode], node: cirq.ControlledOperation
238
+ ):
239
+ return self.visit_GateOperation(state, node)
240
+
241
+ def visit_ControlledGate(
242
+ self, state: lowering.State[CirqNode], node: cirq.ControlledGate
243
+ ):
244
+ op_ = state.lower(node.sub_gate).expect_one()
245
+ n_controls = node.num_controls()
246
+ return state.current_frame.push(op.stmts.Control(op_, n_controls=n_controls))
247
+
248
+ def visit_XXPowGate(self, state: lowering.State[CirqNode], node: cirq.XXPowGate):
249
+ x = state.lower(cirq.XPowGate(exponent=node.exponent)).expect_one()
250
+ return state.current_frame.push(op.stmts.Kron(x, x))
251
+
252
+ def visit_YYPowGate(self, state: lowering.State[CirqNode], node: cirq.YYPowGate):
253
+ y = state.lower(cirq.YPowGate(exponent=node.exponent)).expect_one()
254
+ return state.current_frame.push(op.stmts.Kron(y, y))
255
+
256
+ def visit_ZZPowGate(self, state: lowering.State[CirqNode], node: cirq.ZZPowGate):
257
+ z = state.lower(cirq.ZPowGate(exponent=node.exponent)).expect_one()
258
+ return state.current_frame.push(op.stmts.Kron(z, z))
259
+
260
+ def visit_CCXPowGate(self, state: lowering.State[CirqNode], node: cirq.CCXPowGate):
261
+ x = state.lower(cirq.XPowGate(exponent=node.exponent)).expect_one()
262
+ return state.current_frame.push(op.stmts.Control(x, n_controls=2))
263
+
264
+ def visit_CCZPowGate(self, state: lowering.State[CirqNode], node: cirq.CCZPowGate):
265
+ z = state.lower(cirq.ZPowGate(exponent=node.exponent)).expect_one()
266
+ return state.current_frame.push(op.stmts.Control(z, n_controls=2))
267
+
268
+ def visit_BitFlipChannel(
269
+ self, state: lowering.State[CirqNode], node: cirq.BitFlipChannel
270
+ ):
271
+ x = state.current_frame.push(op.stmts.X())
272
+ p = state.current_frame.push(py.Constant(node.p))
273
+ return state.current_frame.push(
274
+ noise.stmts.PauliError(basis=x.result, p=p.result)
275
+ )
276
+
277
+ def visit_AmplitudeDampingChannel(
278
+ self, state: lowering.State[CirqNode], node: cirq.AmplitudeDampingChannel
279
+ ):
280
+ r = state.current_frame.push(op.stmts.Reset())
281
+ p = state.current_frame.push(py.Constant(node.gamma))
282
+
283
+ # TODO: do we need a dedicated noise stmt for this? Using PauliError
284
+ # with this basis feels like a hack
285
+ noise_channel = state.current_frame.push(
286
+ noise.stmts.PauliError(basis=r.result, p=p.result)
287
+ )
288
+
289
+ return noise_channel
290
+
291
+ def visit_GeneralizedAmplitudeDampingChannel(
292
+ self,
293
+ state: lowering.State[CirqNode],
294
+ node: cirq.GeneralizedAmplitudeDampingChannel,
295
+ ):
296
+ raise NotImplementedError("TODO: needs a new operator statement")
297
+ # p = state.current_frame.push(py.Constant(node.p))
298
+ # gamma = state.current_frame.push(py.Constant(node.gamma))
299
+
300
+ # p1 =
301
+
302
+ # x = state.current_frame.push(op.stmts.X())
303
+ # noise_channel1 = noise.stmts.PauliError(basis=x.result, p=)
@@ -3,12 +3,12 @@ from kirin.prelude import structural_no_opt
3
3
  from kirin.rewrite import Walk, Chain
4
4
  from kirin.dialects import ilist
5
5
 
6
- from . import op, wire, qubit
6
+ from . import op, wire, noise, qubit
7
7
  from .op.rewrite import PyMultToSquinMult
8
8
  from .rewrite.desugar import ApplyDesugarRule, MeasureDesugarRule
9
9
 
10
10
 
11
- @ir.dialect_group(structural_no_opt.union([op, qubit]))
11
+ @ir.dialect_group(structural_no_opt.union([op, qubit, noise]))
12
12
  def kernel(self):
13
13
  fold_pass = passes.Fold(self)
14
14
  typeinfer_pass = passes.TypeInfer(self)
@@ -36,7 +36,7 @@ def kernel(self):
36
36
  return run_pass
37
37
 
38
38
 
39
- @ir.dialect_group(structural_no_opt.union([op, wire]))
39
+ @ir.dialect_group(structural_no_opt.union([op, wire, noise]))
40
40
  def wired(self):
41
41
  py_mult_to_mult_pass = PyMultToSquinMult(self)
42
42
 
@@ -4,5 +4,7 @@ from ._wrapper import (
4
4
  pp_error as pp_error,
5
5
  depolarize as depolarize,
6
6
  qubit_loss as qubit_loss,
7
- pauli_channel as pauli_channel,
7
+ pauli_error as pauli_error,
8
+ two_qubit_pauli_channel as two_qubit_pauli_channel,
9
+ single_qubit_pauli_channel as single_qubit_pauli_channel,
8
10
  )
@@ -14,11 +14,15 @@ def pp_error(op: Op, p: float) -> Op: ...
14
14
 
15
15
 
16
16
  @wraps(stmts.Depolarize)
17
- def depolarize(n_qubits: int, p: float) -> Op: ...
17
+ def depolarize(p: float) -> Op: ...
18
18
 
19
19
 
20
- @wraps(stmts.PauliChannel)
21
- def pauli_channel(n_qubits: int, params: tuple[float, ...]) -> Op: ...
20
+ @wraps(stmts.SingleQubitPauliChannel)
21
+ def single_qubit_pauli_channel(params: tuple[float, float, float]) -> Op: ...
22
+
23
+
24
+ @wraps(stmts.TwoQubitPauliChannel)
25
+ def two_qubit_pauli_channel(params: tuple[float, ...]) -> Op: ...
22
26
 
23
27
 
24
28
  @wraps(stmts.QubitLoss)
@@ -0,0 +1,111 @@
1
+ import itertools
2
+
3
+ from kirin import ir
4
+ from kirin.passes import Pass
5
+ from kirin.rewrite import Walk
6
+ from kirin.dialects import ilist
7
+ from kirin.rewrite.abc import RewriteRule, RewriteResult
8
+
9
+ from .stmts import (
10
+ PPError,
11
+ QubitLoss,
12
+ Depolarize,
13
+ PauliError,
14
+ NoiseChannel,
15
+ TwoQubitPauliChannel,
16
+ SingleQubitPauliChannel,
17
+ StochasticUnitaryChannel,
18
+ )
19
+ from ..op.stmts import X, Y, Z, Kron, Identity
20
+
21
+
22
+ class _RewriteNoiseStmts(RewriteRule):
23
+ """Rewrites squin noise statements to StochasticUnitaryChannel"""
24
+
25
+ def rewrite_Statement(self, node: ir.Statement) -> RewriteResult:
26
+ if not isinstance(node, NoiseChannel) or isinstance(node, QubitLoss):
27
+ return RewriteResult()
28
+
29
+ return getattr(self, "rewrite_" + node.name)(node)
30
+
31
+ def rewrite_pauli_error(self, node: PauliError) -> RewriteResult:
32
+ (operators := ilist.New(values=(node.basis,))).insert_before(node)
33
+ (ps := ilist.New(values=(node.p,))).insert_before(node)
34
+ stochastic_channel = StochasticUnitaryChannel(
35
+ operators=operators.result, probabilities=ps.result
36
+ )
37
+
38
+ node.replace_by(stochastic_channel)
39
+ return RewriteResult(has_done_something=True)
40
+
41
+ def rewrite_single_qubit_pauli_channel(
42
+ self, node: SingleQubitPauliChannel
43
+ ) -> RewriteResult:
44
+ paulis = (X(), Y(), Z())
45
+ paulis_ssa: list[ir.SSAValue] = []
46
+ for op in paulis:
47
+ op.insert_before(node)
48
+ paulis_ssa.append(op.result)
49
+
50
+ (pauli_ops := ilist.New(values=paulis_ssa)).insert_before(node)
51
+
52
+ stochastic_unitary = StochasticUnitaryChannel(
53
+ operators=pauli_ops.result, probabilities=node.params
54
+ )
55
+ node.replace_by(stochastic_unitary)
56
+ return RewriteResult(has_done_something=True)
57
+
58
+ def rewrite_two_qubit_pauli_channel(
59
+ self, node: TwoQubitPauliChannel
60
+ ) -> RewriteResult:
61
+ paulis = (X(), Y(), Z(), Identity(sites=1))
62
+ for op in paulis:
63
+ op.insert_before(node)
64
+
65
+ # NOTE: collect list so we can skip the last entry, which will be two identities
66
+ combinations = list(itertools.product(paulis, repeat=2))[:-1]
67
+ operators: list[ir.SSAValue] = []
68
+ for pauli_1, pauli_2 in combinations:
69
+ op = Kron(pauli_1.result, pauli_2.result)
70
+ op.insert_before(node)
71
+ operators.append(op.result)
72
+
73
+ (operator_list := ilist.New(values=operators)).insert_before(node)
74
+ stochastic_unitary = StochasticUnitaryChannel(
75
+ operators=operator_list.result, probabilities=node.params
76
+ )
77
+
78
+ node.replace_by(stochastic_unitary)
79
+ return RewriteResult(has_done_something=True)
80
+
81
+ def rewrite_p_p_error(self, node: PPError) -> RewriteResult:
82
+ (operators := ilist.New(values=(node.op,))).insert_before(node)
83
+ (ps := ilist.New(values=(node.p,))).insert_before(node)
84
+ stochastic_channel = StochasticUnitaryChannel(
85
+ operators=operators.result, probabilities=ps.result
86
+ )
87
+
88
+ node.replace_by(stochastic_channel)
89
+ return RewriteResult(has_done_something=True)
90
+
91
+ def rewrite_depolarize(self, node: Depolarize) -> RewriteResult:
92
+ paulis = (X(), Y(), Z())
93
+ operators: list[ir.SSAValue] = []
94
+ for op in paulis:
95
+ op.insert_before(node)
96
+ operators.append(op.result)
97
+
98
+ (operator_list := ilist.New(values=operators)).insert_before(node)
99
+ (ps := ilist.New(values=[node.p for _ in range(3)])).insert_before(node)
100
+
101
+ stochastic_unitary = StochasticUnitaryChannel(
102
+ operators=operator_list.result, probabilities=ps.result
103
+ )
104
+ node.replace_by(stochastic_unitary)
105
+
106
+ return RewriteResult(has_done_something=True)
107
+
108
+
109
+ class RewriteNoiseStmts(Pass):
110
+ def unsafe_run(self, mt: ir.Method):
111
+ return Walk(_RewriteNoiseStmts()).rewrite(mt.code)