Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/bloqade/cirq_utils/emit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# NOTE: just to register methods
from . import op as op, noise as noise, qubit as qubit, clifford as clifford
from . import op as op, gate as gate, noise as noise, qubit as qubit
from .base import emit_circuit as emit_circuit
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,33 @@
import cirq
from kirin.interp import MethodTable, impl

from bloqade.squin import clifford
from bloqade.squin import gate

from .base import EmitCirq, EmitCirqFrame


@clifford.dialect.register(key="emit.cirq")
class __EmitCirqCliffordMethods(MethodTable):
@gate.dialect.register(key="emit.cirq")
class __EmitCirqGateMethods(MethodTable):

@impl(clifford.stmts.X)
@impl(clifford.stmts.Y)
@impl(clifford.stmts.Z)
@impl(clifford.stmts.H)
@impl(gate.stmts.X)
@impl(gate.stmts.Y)
@impl(gate.stmts.Z)
@impl(gate.stmts.H)
def hermitian(
self, emit: EmitCirq, frame: EmitCirqFrame, stmt: clifford.stmts.SingleQubitGate
self, emit: EmitCirq, frame: EmitCirqFrame, stmt: gate.stmts.SingleQubitGate
):
qubits = frame.get(stmt.qubits)
cirq_op = getattr(cirq, stmt.name.upper())
frame.circuit.append(cirq_op.on_each(qubits))
return ()

@impl(clifford.stmts.S)
@impl(clifford.stmts.T)
@impl(gate.stmts.S)
@impl(gate.stmts.T)
def unitary(
self,
emit: EmitCirq,
frame: EmitCirqFrame,
stmt: clifford.stmts.SingleQubitNonHermitianGate,
stmt: gate.stmts.SingleQubitNonHermitianGate,
):
qubits = frame.get(stmt.qubits)
cirq_op = getattr(cirq, stmt.name.upper())
Expand All @@ -39,33 +39,33 @@ def unitary(
frame.circuit.append(cirq_op.on_each(qubits))
return ()

@impl(clifford.stmts.SqrtX)
@impl(clifford.stmts.SqrtY)
@impl(gate.stmts.SqrtX)
@impl(gate.stmts.SqrtY)
def sqrt(
self,
emit: EmitCirq,
frame: EmitCirqFrame,
stmt: clifford.stmts.SqrtX | clifford.stmts.SqrtY,
stmt: gate.stmts.SqrtX | gate.stmts.SqrtY,
):
qubits = frame.get(stmt.qubits)

exponent = 0.5
if stmt.adjoint:
exponent *= -1

if isinstance(stmt, clifford.stmts.SqrtX):
if isinstance(stmt, gate.stmts.SqrtX):
cirq_op = cirq.XPowGate(exponent=exponent)
else:
cirq_op = cirq.YPowGate(exponent=exponent)

frame.circuit.append(cirq_op.on_each(qubits))
return ()

@impl(clifford.stmts.CX)
@impl(clifford.stmts.CY)
@impl(clifford.stmts.CZ)
@impl(gate.stmts.CX)
@impl(gate.stmts.CY)
@impl(gate.stmts.CZ)
def control(
self, emit: EmitCirq, frame: EmitCirqFrame, stmt: clifford.stmts.ControlledGate
self, emit: EmitCirq, frame: EmitCirqFrame, stmt: gate.stmts.ControlledGate
):
controls = frame.get(stmt.controls)
targets = frame.get(stmt.targets)
Expand All @@ -74,12 +74,10 @@ def control(
frame.circuit.append(cirq_op.on_each(cirq_qubits))
return ()

@impl(clifford.stmts.Rx)
@impl(clifford.stmts.Ry)
@impl(clifford.stmts.Rz)
def rot(
self, emit: EmitCirq, frame: EmitCirqFrame, stmt: clifford.stmts.RotationGate
):
@impl(gate.stmts.Rx)
@impl(gate.stmts.Ry)
@impl(gate.stmts.Rz)
def rot(self, emit: EmitCirq, frame: EmitCirqFrame, stmt: gate.stmts.RotationGate):
qubits = frame.get(stmt.qubits)

turns = frame.get(stmt.angle)
Expand Down
50 changes: 23 additions & 27 deletions src/bloqade/cirq_utils/lowering.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from kirin.rewrite import Walk, CFGCompactify
from kirin.dialects import py, scf, func, ilist

from bloqade.squin import noise, qubit, kernel, clifford
from bloqade.squin import gate, noise, qubit, kernel


def load_circuit(
Expand Down Expand Up @@ -411,27 +411,27 @@ def visit_SingleQubitPauliStringGateOperation(
node: cirq.SingleQubitPauliStringGateOperation,
):
if isinstance(node.pauli, cirq.IdentityGate):
# TODO: do we need an identity gate in clifford?
# TODO: do we need an identity gate in gate?
return

qargs = self.lower_qubit_getindices(state, (node.qubit,))
match node.pauli:
case cirq.X:
clifford_stmt = clifford.stmts.X
gate_stmt = gate.stmts.X
case cirq.Y:
clifford_stmt = clifford.stmts.Y
gate_stmt = gate.stmts.Y
case cirq.Z:
clifford_stmt = clifford.stmts.Z
gate_stmt = gate.stmts.Z
case _:
raise lowering.BuildError(f"Unexpected Pauli operation {node.pauli}")

return state.current_frame.push(clifford_stmt(qargs))
return state.current_frame.push(gate_stmt(qargs))

def visit_HPowGate(self, state: lowering.State[cirq.Circuit], node: cirq.HPowGate):
qargs = self.lower_qubit_getindices(state, node.qubits)

if node.gate.exponent % 2 == 1:
return state.current_frame.push(clifford.stmts.H(qargs))
return state.current_frame.push(gate.stmts.H(qargs))

# NOTE: decompose into products of paulis for arbitrary exponents according to _decompose_ method
for subnode in cirq.decompose_once(node):
Expand All @@ -442,20 +442,20 @@ def visit_XPowGate(
):
qargs = self.lower_qubit_getindices(state, node.qubits)
if node.gate.exponent % 2 == 1:
return state.current_frame.push(clifford.stmts.X(qargs))
return state.current_frame.push(gate.stmts.X(qargs))

angle = state.current_frame.push(py.Constant(0.5 * node.gate.exponent))
return state.current_frame.push(clifford.stmts.Rx(angle.result, qargs))
return state.current_frame.push(gate.stmts.Rx(angle.result, qargs))

def visit_YPowGate(
self, state: lowering.State[cirq.Circuit], node: cirq.GateOperation
):
qargs = self.lower_qubit_getindices(state, node.qubits)
if node.gate.exponent % 2 == 1:
return state.current_frame.push(clifford.stmts.Y(qargs))
return state.current_frame.push(gate.stmts.Y(qargs))

angle = state.current_frame.push(py.Constant(0.5 * node.gate.exponent))
return state.current_frame.push(clifford.stmts.Ry(angle.result, qargs))
return state.current_frame.push(gate.stmts.Ry(angle.result, qargs))

def visit_ZPowGate(
self, state: lowering.State[cirq.Circuit], node: cirq.GateOperation
Expand All @@ -464,36 +464,32 @@ def visit_ZPowGate(

if abs(node.gate.exponent) == 0.5:
adjoint = node.gate.exponent < 0
return state.current_frame.push(
clifford.stmts.S(adjoint=adjoint, qubits=qargs)
)
return state.current_frame.push(gate.stmts.S(adjoint=adjoint, qubits=qargs))

if abs(node.gate.exponent) == 0.25:
adjoint = node.gate.exponent < 0
return state.current_frame.push(
clifford.stmts.T(adjoint=adjoint, qubits=qargs)
)
return state.current_frame.push(gate.stmts.T(adjoint=adjoint, qubits=qargs))

if node.gate.exponent % 2 == 1:
return state.current_frame.push(clifford.stmts.Z(qubits=qargs))
return state.current_frame.push(gate.stmts.Z(qubits=qargs))

angle = state.current_frame.push(py.Constant(0.5 * node.gate.exponent))
return state.current_frame.push(clifford.stmts.Rz(angle.result, qargs))
return state.current_frame.push(gate.stmts.Rz(angle.result, qargs))

def visit_Rx(self, state: lowering.State[cirq.Circuit], node: cirq.GateOperation):
qargs = self.lower_qubit_getindices(state, node.qubits)
angle = state.current_frame.push(py.Constant(value=0.5 * node.gate.exponent))
return state.current_frame.push(clifford.stmts.Rx(angle.result, qargs))
return state.current_frame.push(gate.stmts.Rx(angle.result, qargs))

def visit_Ry(self, state: lowering.State[cirq.Circuit], node: cirq.GateOperation):
qargs = self.lower_qubit_getindices(state, node.qubits)
angle = state.current_frame.push(py.Constant(value=0.5 * node.gate.exponent))
return state.current_frame.push(clifford.stmts.Ry(angle.result, qargs))
return state.current_frame.push(gate.stmts.Ry(angle.result, qargs))

def visit_Rz(self, state: lowering.State[cirq.Circuit], node: cirq.GateOperation):
qargs = self.lower_qubit_getindices(state, node.qubits)
angle = state.current_frame.push(py.Constant(value=0.5 * node.gate.exponent))
return state.current_frame.push(clifford.stmts.Rz(angle.result, qargs))
return state.current_frame.push(gate.stmts.Rz(angle.result, qargs))

def visit_CXPowGate(
self, state: lowering.State[cirq.Circuit], node: cirq.GateOperation
Expand All @@ -508,7 +504,7 @@ def visit_CXPowGate(
control_qarg = self.lower_qubit_getindices(state, (control,))
target_qarg = self.lower_qubit_getindices(state, (target,))
return state.current_frame.push(
clifford.stmts.CX(controls=control_qarg, targets=target_qarg)
gate.stmts.CX(controls=control_qarg, targets=target_qarg)
)

def visit_CZPowGate(
Expand All @@ -524,19 +520,19 @@ def visit_CZPowGate(
control_qarg = self.lower_qubit_getindices(state, (control,))
target_qarg = self.lower_qubit_getindices(state, (target,))
return state.current_frame.push(
clifford.stmts.CZ(controls=control_qarg, targets=target_qarg)
gate.stmts.CZ(controls=control_qarg, targets=target_qarg)
)

def visit_ControlledOperation(
self, state: lowering.State[cirq.Circuit], node: cirq.ControlledOperation
):
match node.gate.sub_gate:
case cirq.X:
stmt = clifford.stmts.CX
stmt = gate.stmts.CX
case cirq.Y:
stmt = clifford.stmts.CY
stmt = gate.stmts.CY
case cirq.Z:
stmt = clifford.stmts.CZ
stmt = gate.stmts.CZ
case _:
raise lowering.BuildError(
f"Cannot lowering controlled operation: {node}"
Expand Down
8 changes: 4 additions & 4 deletions src/bloqade/native/upstream/squin2native.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from kirin.analysis.callgraph import CallGraph

from bloqade.native import kernel, broadcast
from bloqade.squin.clifford import stmts, dialect as clifford_dialect
from bloqade.squin.gate import stmts, dialect as gate_dialect


class GateRule(RewriteRule):
Expand Down Expand Up @@ -103,10 +103,10 @@ def unsafe_run(self, mt: ir.Method) -> RewriteResult:


class SquinToNative:
"""A Target that converts Squin Clifford gates to native gates."""
"""A Target that converts Squin gates to native gates."""

def emit(self, mt: ir.Method, *, no_raise=True) -> ir.Method:
"""Convert Squin Clifford gates to native gates.
"""Convert Squin gates to native gates.

Args:
mt (ir.Method): The method to convert.
Expand All @@ -120,7 +120,7 @@ def emit(self, mt: ir.Method, *, no_raise=True) -> ir.Method:
ker.dialects.data for kers in old_callgraph.defs.values() for ker in kers
)
new_dialects = (
mt.dialects.union(all_dialects).discard(clifford_dialect).union(kernel)
mt.dialects.union(all_dialects).discard(gate_dialect).union(kernel)
)

out = mt.similar(new_dialects)
Expand Down
2 changes: 1 addition & 1 deletion src/bloqade/pyqrack/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# NOTE: The following import is for registering the method tables
from .noise import native as native
from .qasm2 import uop as uop, core as core, glob as glob, parallel as parallel
from .squin import op as op, noise as noise, qubit as qubit, clifford as clifford
from .squin import op as op, gate as gate, noise as noise, qubit as qubit
from .device import (
StackMemorySimulator as StackMemorySimulator,
DynamicMemorySimulator as DynamicMemorySimulator,
Expand Down
1 change: 0 additions & 1 deletion src/bloqade/pyqrack/squin/clifford/__init__.py

This file was deleted.

1 change: 1 addition & 0 deletions src/bloqade/pyqrack/squin/gate/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import gate as gate
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
from kirin import interp
from kirin.dialects import ilist

from bloqade.squin import clifford
from bloqade.squin import gate
from pyqrack.pauli import Pauli
from bloqade.pyqrack.reg import PyQrackQubit
from bloqade.pyqrack.target import PyQrackInterpreter
from bloqade.squin.clifford.stmts import (
from bloqade.squin.gate.stmts import (
CX,
CY,
CZ,
Expand All @@ -26,7 +26,7 @@
)


@clifford.dialect.register(key="pyqrack")
@gate.dialect.register(key="pyqrack")
class PyQrackMethods(interp.MethodTable):

@interp.impl(X)
Expand Down
3 changes: 1 addition & 2 deletions src/bloqade/squin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from . import (
op as op,
gate as gate,
wire as wire,
noise as noise,
qubit as qubit,
Expand Down Expand Up @@ -42,8 +43,6 @@

# NOTE: it's important to keep these imports here since they import squin.kernel
# we skip isort here
from . import parallel as parallel # isort: skip
from .stdlib import ( # isort: skip
gate as gate,
broadcast as broadcast,
)
3 changes: 0 additions & 3 deletions src/bloqade/squin/clifford/_dialect.py

This file was deleted.

3 changes: 3 additions & 0 deletions src/bloqade/squin/gate/_dialect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from kirin import ir

dialect = ir.Dialect("squin.gate")
File renamed without changes.
4 changes: 2 additions & 2 deletions src/bloqade/squin/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
from kirin.rewrite import Walk, Chain
from kirin.dialects import ilist

from . import op, wire, noise, qubit, clifford
from . import op, gate, wire, noise, qubit
from .op.rewrite import PyMultToSquinMult
from .rewrite.desugar import ApplyDesugarRule, MeasureDesugarRule


@ir.dialect_group(structural_no_opt.union([op, qubit, noise, clifford]))
@ir.dialect_group(structural_no_opt.union([op, qubit, noise, gate]))
def kernel(self):
fold_pass = passes.Fold(self)
typeinfer_pass = passes.TypeInfer(self)
Expand Down
Loading