Skip to content

analysis

schedule

StmtDag dataclass

StmtDag(
    id_table: IdTable[
        Statement
    ] = lambda: idtable.IdTable()(),
    stmts: Dict[str, Statement] = OrderedDict(),
    out_edges: Dict[str, Set[str]] = OrderedDict(),
    inc_edges: Dict[str, Set[str]] = OrderedDict(),
    stmt_index: Dict[Statement, int] = OrderedDict(),
)

Bases: Graph[Statement]

topological_groups

topological_groups()

Split the dag into topological groups where each group contains nodes that have no dependencies on each other, but have dependencies on nodes in one or more previous groups.

Yields:

Type Description

List[str]: A list of node ids in a topological group

Raises:

Type Description
ValueError

If a cyclic dependency is detected

The idea is to yield all nodes with no dependencies, then remove those nodes from the graph repeating until no nodes are left or we reach some upper limit. Worse case is a linear dag, so we can use len(dag.stmts) as the upper limit

If we reach the limit and there are still nodes left, then we have a cyclic dependency.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/analysis/schedule.py
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
def topological_groups(self):
    """Split the dag into topological groups where each group
    contains nodes that have no dependencies on each other, but
    have dependencies on nodes in one or more previous groups.

    Yields:
        List[str]: A list of node ids in a topological group


    Raises:
        ValueError: If a cyclic dependency is detected


    The idea is to yield all nodes with no dependencies, then remove
    those nodes from the graph repeating until no nodes are left
    or we reach some upper limit. Worse case is a linear dag,
    so we can use len(dag.stmts) as the upper limit

    If we reach the limit and there are still nodes left, then we
    have a cyclic dependency.
    """

    inc_edges = {k: set(v) for k, v in self.inc_edges.items()}

    check_next = inc_edges.keys()

    for _ in range(len(self.stmts)):
        if len(inc_edges) == 0:
            break

        group = [node_id for node_id in check_next if len(inc_edges[node_id]) == 0]
        yield group

        check_next = set()
        for n in group:
            inc_edges.pop(n)
            for m in self.out_edges[n]:
                check_next.add(m)
                inc_edges[m].remove(n)

    if inc_edges:
        raise ValueError("Cyclic dependency detected")

cirq

load_circuit

load_circuit(
    circuit: Circuit,
    kernel_name: str = "main",
    dialects: DialectGroup = kernel,
    globals: dict[str, Any] | None = None,
    file: str | None = None,
    lineno_offset: int = 0,
    col_offset: int = 0,
    compactify: bool = True,
)

Converts a cirq.Circuit object into a squin kernel.

Parameters:

Name Type Description Default
circuit Circuit

The circuit to load.

required

Other Parameters:

Name Type Description
kernel_name str

The name of the kernel to load. Defaults to "main".

dialects DialectGroup | None

The dialects to use. Defaults to squin.kernel.

globals dict[str, Any] | None

The global variables to use. Defaults to None.

file str | None

The file name for error reporting. Defaults to None.

lineno_offset int

The line number offset for error reporting. Defaults to 0.

col_offset int

The column number offset for error reporting. Defaults to 0.

compactify bool

Whether to compactify the output. Defaults to True.

Example:

# from cirq's "hello qubit" example
import cirq
from bloqade import squin

# Pick a qubit.
qubit = cirq.GridQubit(0, 0)

# Create a circuit.
circuit = cirq.Circuit(
    cirq.X(qubit)**0.5,  # Square root of NOT.
    cirq.measure(qubit, key='m')  # Measurement.
)

# load the circuit as squin
main = squin.load_circuit(circuit)

# print the resulting IR
main.print()
Source code in .venv/lib/python3.12/site-packages/bloqade/squin/cirq/__init__.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
def load_circuit(
    circuit: cirq.Circuit,
    kernel_name: str = "main",
    dialects: ir.DialectGroup = kernel,
    globals: dict[str, Any] | None = None,
    file: str | None = None,
    lineno_offset: int = 0,
    col_offset: int = 0,
    compactify: bool = True,
):
    """Converts a cirq.Circuit object into a squin kernel.

    Args:
        circuit (cirq.Circuit): The circuit to load.

    Keyword Args:
        kernel_name (str): The name of the kernel to load. Defaults to "main".
        dialects (ir.DialectGroup | None): The dialects to use. Defaults to `squin.kernel`.
        globals (dict[str, Any] | None): The global variables to use. Defaults to None.
        file (str | None): The file name for error reporting. Defaults to None.
        lineno_offset (int): The line number offset for error reporting. Defaults to 0.
        col_offset (int): The column number offset for error reporting. Defaults to 0.
        compactify (bool): Whether to compactify the output. Defaults to True.

    Example:

    ```python
    # from cirq's "hello qubit" example
    import cirq
    from bloqade import squin

    # Pick a qubit.
    qubit = cirq.GridQubit(0, 0)

    # Create a circuit.
    circuit = cirq.Circuit(
        cirq.X(qubit)**0.5,  # Square root of NOT.
        cirq.measure(qubit, key='m')  # Measurement.
    )

    # load the circuit as squin
    main = squin.load_circuit(circuit)

    # print the resulting IR
    main.print()
    ```
    """

    target = Squin(dialects=dialects, circuit=circuit)
    body = target.run(
        circuit,
        source=str(circuit),  # TODO: proper source string
        file=file,
        globals=globals,
        lineno_offset=lineno_offset,
        col_offset=col_offset,
        compactify=compactify,
    )

    # NOTE: no return value
    return_value = func.ConstantNone()
    body.blocks[0].stmts.append(return_value)
    body.blocks[0].stmts.append(func.Return(value_or_stmt=return_value))

    code = func.Function(
        sym_name=kernel_name,
        signature=func.Signature((), types.NoneType),
        body=body,
    )

    return ir.Method(
        mod=None,
        py_func=None,
        sym_name=kernel_name,
        arg_names=[],
        dialects=dialects,
        code=code,
    )

lowering

Squin dataclass

Squin(circuit: Circuit)

Bases: LoweringABC[CirqNode]

Lower a cirq.Circuit object to a squin kernel

lowering

ApplyAnyCallLowering dataclass

ApplyAnyCallLowering()

Bases: FromPythonCall['qubit.ApplyAny']

Custom lowering for ApplyAny that collects vararg qubits into a single tuple argument

noise

rewrite

stmts

Depolarize

Bases: NoiseChannel

Apply depolarize error to qubit

PPError

Bases: NoiseChannel

Pauli Product Error

op

rewrite

Rewrite py.binop.mult to Mult stmt

stdlib

ch

ch() -> types.Op

Control H gate.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/op/stdlib.py
53
54
55
56
@op
def ch() -> types.Op:
    """Control H gate."""
    return control(h(), n_controls=1)

cphase

cphase(theta: float) -> types.Op

Control Phase gate.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/op/stdlib.py
59
60
61
62
@op
def cphase(theta: float) -> types.Op:
    """Control Phase gate."""
    return control(phase(theta), n_controls=1)

cx

cx() -> types.Op

Controlled X gate.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/op/stdlib.py
35
36
37
38
@op
def cx() -> types.Op:
    """Controlled X gate."""
    return control(x(), n_controls=1)

cy

cy() -> types.Op

Controlled Y gate.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/op/stdlib.py
41
42
43
44
@op
def cy() -> types.Op:
    """Controlled Y gate."""
    return control(y(), n_controls=1)

cz

cz() -> types.Op

Control Z gate.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/op/stdlib.py
47
48
49
50
@op
def cz() -> types.Op:
    """Control Z gate."""
    return control(z(), n_controls=1)

rx

rx(theta: float) -> types.Op

Rotation X gate.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/op/stdlib.py
17
18
19
20
@op
def rx(theta: float) -> types.Op:
    """Rotation X gate."""
    return rot(x(), theta)

ry

ry(theta: float) -> types.Op

Rotation Y gate.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/op/stdlib.py
23
24
25
26
@op
def ry(theta: float) -> types.Op:
    """Rotation Y gate."""
    return rot(y(), theta)

rz

rz(theta: float) -> types.Op

Rotation Z gate.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/op/stdlib.py
29
30
31
32
@op
def rz(theta: float) -> types.Op:
    """Rotation Z gate."""
    return rot(z(), theta)

stmts

P0

Bases: ConstantOp

The \(P_0\) projection operator.

\[ P0 = \begin{bmatrix} 1 & 0 \\ 0 & 0 \end{bmatrix} \]

P1

Bases: ConstantOp

The \(P_1\) projection operator.

\[ P1 = \begin{bmatrix} 0 & 0 \\ 0 & 1 \end{bmatrix} \]

PhaseOp

Bases: PrimitiveOp

A phase operator.

\[ PhaseOp(theta) = e^{i heta} I \]

Reset

Bases: PrimitiveOp

Reset operator for qubits or wires.

ShiftOp

Bases: PrimitiveOp

A phase shift operator.

\[ Shift(theta) = \begin{bmatrix} 1 & 0 \\ 0 & e^{i \theta} \end{bmatrix} \]

Sn

Bases: ConstantOp

\(S_{-}\) operator.

\[ Sn = \frac{1}{2} (S_x - i S_y) = \frac{1}{2} \begin{bmatrix} 0 & 0 \\ 1 & 0 \end{bmatrix} \]

Sp

Bases: ConstantOp

\(S_{+}\) operator.

\[ Sp = \frac{1}{2} (S_x + i S_y) = \frac{1}{2}\begin{bmatrix} 0 & 1 \\ 0 & 0 \end{bmatrix} \]

traits

HasSites dataclass

HasSites()

Bases: StmtTrait

An operator with a sites attribute.

qubit

qubit dialect for squin language.

This dialect defines the operations that can be performed on qubits.

Depends on: - bloqade.squin.op: provides the OpType type and semantics for operators applied to qubits. - kirin.dialects.ilist: provides the ilist.IListType type for lists of qubits.

broadcast

broadcast(
    operator: Op, qubits: IList[Qubit, Any] | list[Qubit]
) -> None

Broadcast and apply an operator to a list of qubits. For example, an operator that expects 2 qubits can be applied to a list of 2n qubits, where n is an integer > 0.

For controlled operators, the list of qubits is interpreted as sets of (controls, targets). For example

apply(CX, [q0, q1, q2, q3])

is equivalent to

apply(CX, [q0, q1])
apply(CX, [q2, q3])

Parameters:

Name Type Description Default
operator Op

The operator to broadcast and apply.

required
qubits IList[Qubit, Any] | list[Qubit]

The list of qubits to broadcast and apply the operator to. The size of the list must be inferable and match the number of qubits expected by the operator.

required

Returns:

Type Description
None

None

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/qubit.py
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
@wraps(Broadcast)
def broadcast(operator: Op, qubits: ilist.IList[Qubit, Any] | list[Qubit]) -> None:
    """Broadcast and apply an operator to a list of qubits. For example, an operator
    that expects 2 qubits can be applied to a list of 2n qubits, where n is an integer > 0.

    For controlled operators, the list of qubits is interpreted as sets of (controls, targets).
    For example

    ```
    apply(CX, [q0, q1, q2, q3])
    ```

    is equivalent to

    ```
    apply(CX, [q0, q1])
    apply(CX, [q2, q3])
    ```

    Args:
        operator: The operator to broadcast and apply.
        qubits: The list of qubits to broadcast and apply the operator to. The size of the list
            must be inferable and match the number of qubits expected by the operator.

    Returns:
        None
    """
    ...

measure

measure(input: Qubit) -> bool
measure(
    input: IList[Qubit, Any] | list[Qubit],
) -> ilist.IList[bool, Any]
measure(input: Any) -> Any

Measure a qubit or qubits in the list.

Parameters:

Name Type Description Default
input Any

A qubit or a list of qubits to measure.

required

Returns:

Type Description
Any

bool | list[bool]: The result of the measurement. If a single qubit is measured, a single boolean is returned. If a list of qubits is measured, a list of booleans is returned.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/qubit.py
139
140
141
142
143
144
145
146
147
148
149
150
151
@wraps(MeasureAny)
def measure(input: Any) -> Any:
    """Measure a qubit or qubits in the list.

    Args:
        input: A qubit or a list of qubits to measure.

    Returns:
        bool | list[bool]: The result of the measurement. If a single qubit is measured,
            a single boolean is returned. If a list of qubits is measured, a list of booleans
            is returned.
    """
    ...

new

new(n_qubits: int) -> ilist.IList[Qubit, Any]

Create a new list of qubits.

Parameters:

Name Type Description Default
n_qubits(int)

The number of qubits to create.

required

Returns:

Type Description
IList[Qubit, Any]

(ilist.IList[Qubit, n_qubits]) A list of qubits.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/qubit.py
82
83
84
85
86
87
88
89
90
91
92
@wraps(New)
def new(n_qubits: int) -> ilist.IList[Qubit, Any]:
    """Create a new list of qubits.

    Args:
        n_qubits(int): The number of qubits to create.

    Returns:
        (ilist.IList[Qubit, n_qubits]) A list of qubits.
    """
    ...

rewrite

desugar

ApplyDesugarRule

Bases: RewriteRule

Desugar apply operators in the kernel.

MeasureDesugarRule

Bases: RewriteRule

Desugar measure operations in the circuit.

qubit_to_stim

SquinQubitToStim

Bases: RewriteRule

rewrite_Apply_and_Broadcast

rewrite_Apply_and_Broadcast(
    stmt: Apply | Broadcast,
) -> RewriteResult

Rewrite Apply and Broadcast nodes to their stim equivalent statements.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/rewrite/qubit_to_stim.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
def rewrite_Apply_and_Broadcast(
    self, stmt: qubit.Apply | qubit.Broadcast
) -> RewriteResult:
    """
    Rewrite Apply and Broadcast nodes to their stim equivalent statements.
    """

    # this is an SSAValue, need it to be the actual operator
    applied_op = stmt.operator.owner
    assert isinstance(applied_op, op.stmts.Operator)

    if isinstance(applied_op, op.stmts.Control):
        return rewrite_Control(stmt)

    # need to handle Control through separate means
    # but we can handle X, Y, Z, H, and S here just fine
    stim_1q_op = SQUIN_STIM_GATE_MAPPING.get(type(applied_op))
    if stim_1q_op is None:
        return RewriteResult()

    address_attr = stmt.qubits.hints.get("address")
    if address_attr is None:
        return RewriteResult()

    assert isinstance(address_attr, AddressAttribute)
    qubit_idx_ssas = insert_qubit_idx_from_address(
        address=address_attr, stmt_to_insert_before=stmt
    )

    if qubit_idx_ssas is None:
        return RewriteResult()

    stim_1q_stmt = stim_1q_op(targets=tuple(qubit_idx_ssas))
    stmt.replace_by(stim_1q_stmt)

    return RewriteResult(has_done_something=True)

squin_measure

SquinMeasureToStim

Bases: RewriteRule

Rewrite squin measure-related statements to stim statements.

get_qubit_idx_ssas

get_qubit_idx_ssas(
    measure_stmt: MeasureQubit | MeasureQubitList | Measure,
) -> tuple[ir.SSAValue, ...] | None

Extract the address attribute and insert qubit indices for the given measure statement.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/rewrite/squin_measure.py
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
def get_qubit_idx_ssas(
    self, measure_stmt: qubit.MeasureQubit | qubit.MeasureQubitList | wire.Measure
) -> tuple[ir.SSAValue, ...] | None:
    """
    Extract the address attribute and insert qubit indices for the given measure statement.
    """
    match measure_stmt:
        case qubit.MeasureQubit():
            address_attr = measure_stmt.qubit.hints.get("address")
        case qubit.MeasureQubitList():
            address_attr = measure_stmt.qubits.hints.get("address")
        case wire.Measure():
            address_attr = measure_stmt.wire.hints.get("address")
        case _:
            return None

    if address_attr is None:
        return None

    assert isinstance(address_attr, AddressAttribute)

    qubit_idx_ssas = insert_qubit_idx_from_address(
        address=address_attr, stmt_to_insert_before=measure_stmt
    )

    return qubit_idx_ssas

stim_rewrite_util

insert_qubit_idx_after_apply

insert_qubit_idx_after_apply(
    stmt: Apply | Apply | Broadcast | Broadcast,
) -> tuple[ir.SSAValue, ...] | None

Extract qubit indices from Apply or Broadcast statements.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/rewrite/stim_rewrite_util.py
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
def insert_qubit_idx_after_apply(
    stmt: wire.Apply | qubit.Apply | wire.Broadcast | qubit.Broadcast,
) -> tuple[ir.SSAValue, ...] | None:
    """
    Extract qubit indices from Apply or Broadcast statements.
    """
    if isinstance(stmt, (qubit.Apply, qubit.Broadcast)):
        qubits = stmt.qubits
        address_attribute = qubits.hints.get("address")
        if address_attribute is None:
            return
        assert isinstance(address_attribute, AddressAttribute)
        return insert_qubit_idx_from_address(
            address=address_attribute, stmt_to_insert_before=stmt
        )
    elif isinstance(stmt, (wire.Apply, wire.Broadcast)):
        wire_ssas = stmt.inputs
        return insert_qubit_idx_from_wire_ssa(
            wire_ssas=wire_ssas, stmt_to_insert_before=stmt
        )

insert_qubit_idx_from_address

insert_qubit_idx_from_address(
    address: AddressAttribute,
    stmt_to_insert_before: Statement,
) -> tuple[ir.SSAValue, ...] | None

Extract qubit indices from an AddressAttribute and insert them into the SSA form.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/rewrite/stim_rewrite_util.py
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def insert_qubit_idx_from_address(
    address: AddressAttribute, stmt_to_insert_before: ir.Statement
) -> tuple[ir.SSAValue, ...] | None:
    """
    Extract qubit indices from an AddressAttribute and insert them into the SSA form.
    """
    address_data = address.address
    qubit_idx_ssas = []

    if isinstance(address_data, AddressTuple):
        for address_qubit in address_data.data:
            if not isinstance(address_qubit, AddressQubit):
                return
            qubit_idx = address_qubit.data
            qubit_idx_stmt = py.Constant(qubit_idx)
            qubit_idx_stmt.insert_before(stmt_to_insert_before)
            qubit_idx_ssas.append(qubit_idx_stmt.result)
    elif isinstance(address_data, AddressWire):
        address_qubit = address_data.origin_qubit
        qubit_idx = address_qubit.data
        qubit_idx_stmt = py.Constant(qubit_idx)
        qubit_idx_stmt.insert_before(stmt_to_insert_before)
        qubit_idx_ssas.append(qubit_idx_stmt.result)
    else:
        return

    return tuple(qubit_idx_ssas)

insert_qubit_idx_from_wire_ssa

insert_qubit_idx_from_wire_ssa(
    wire_ssas: tuple[SSAValue, ...],
    stmt_to_insert_before: Statement,
) -> tuple[ir.SSAValue, ...] | None

Extract qubit indices from wire SSA values and insert them into the SSA form.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/rewrite/stim_rewrite_util.py
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
def insert_qubit_idx_from_wire_ssa(
    wire_ssas: tuple[ir.SSAValue, ...], stmt_to_insert_before: ir.Statement
) -> tuple[ir.SSAValue, ...] | None:
    """
    Extract qubit indices from wire SSA values and insert them into the SSA form.
    """
    qubit_idx_ssas = []
    for wire_ssa in wire_ssas:
        address_attribute = wire_ssa.hints.get("address")
        if address_attribute is None:
            return
        assert isinstance(address_attribute, AddressAttribute)
        wire_address = address_attribute.address
        assert isinstance(wire_address, AddressWire)
        qubit_idx = wire_address.origin_qubit.data
        qubit_idx_stmt = py.Constant(qubit_idx)
        qubit_idx_ssas.append(qubit_idx_stmt.result)
        qubit_idx_stmt.insert_before(stmt_to_insert_before)

    return tuple(qubit_idx_ssas)

is_measure_result_used

is_measure_result_used(
    stmt: MeasureQubit | MeasureQubitList | Measure,
) -> bool

Check if the result of a measure statement is used in the program.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/rewrite/stim_rewrite_util.py
147
148
149
150
151
152
153
def is_measure_result_used(
    stmt: qubit.MeasureQubit | qubit.MeasureQubitList | wire.Measure,
) -> bool:
    """
    Check if the result of a measure statement is used in the program.
    """
    return bool(stmt.result.uses)

rewrite_Control

rewrite_Control(
    stmt_with_ctrl: Apply | Apply | Broadcast | Broadcast,
) -> RewriteResult

Handle control gates for Apply and Broadcast statements.

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/rewrite/stim_rewrite_util.py
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
def rewrite_Control(
    stmt_with_ctrl: qubit.Apply | wire.Apply | qubit.Broadcast | wire.Broadcast,
) -> RewriteResult:
    """
    Handle control gates for Apply and Broadcast statements.
    """
    ctrl_op = stmt_with_ctrl.operator.owner
    assert isinstance(ctrl_op, op.stmts.Control)

    ctrl_op_target_gate = ctrl_op.op.owner
    assert isinstance(ctrl_op_target_gate, op.stmts.Operator)

    qubit_idx_ssas = insert_qubit_idx_after_apply(stmt=stmt_with_ctrl)
    if qubit_idx_ssas is None:
        return RewriteResult()

    # Separate control and target qubits
    target_qubits = []
    ctrl_qubits = []
    for i in range(len(qubit_idx_ssas)):
        if (i % 2) == 0:
            ctrl_qubits.append(qubit_idx_ssas[i])
        else:
            target_qubits.append(qubit_idx_ssas[i])

    target_qubits = tuple(target_qubits)
    ctrl_qubits = tuple(ctrl_qubits)

    supported_gate_mapping = {
        op.stmts.X: gate.CX,
        op.stmts.Y: gate.CY,
        op.stmts.Z: gate.CZ,
    }

    stim_gate = supported_gate_mapping.get(type(ctrl_op_target_gate))
    if stim_gate is None:
        return RewriteResult()

    stim_stmt = stim_gate(controls=ctrl_qubits, targets=target_qubits)

    if isinstance(stmt_with_ctrl, (wire.Apply, wire.Broadcast)):
        # have to "reroute" the input of these statements to directly plug in
        # to subsequent statements, remove dependency on the current statement
        for input_wire, output_wire in zip(
            stmt_with_ctrl.inputs, stmt_with_ctrl.results
        ):
            output_wire.replace_by(input_wire)

    stmt_with_ctrl.replace_by(stim_stmt)

    return RewriteResult(has_done_something=True)

wire_identity_elimination

SquinWireIdentityElimination

Bases: RewriteRule

rewrite_Statement

rewrite_Statement(node: Statement) -> RewriteResult

Handle the case where an unwrap feeds a wire directly into a wrap, equivalent to nothing happening/identity operation

w = unwrap(qubit) wrap(qubit, w)

Source code in .venv/lib/python3.12/site-packages/bloqade/squin/rewrite/wire_identity_elimination.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def rewrite_Statement(self, node: ir.Statement) -> RewriteResult:
    """
    Handle the case where an unwrap feeds a wire directly into a wrap,
    equivalent to nothing happening/identity operation

    w = unwrap(qubit)
    wrap(qubit, w)
    """
    if isinstance(node, wire.Wrap):
        wire_origin_stmt = node.wire.owner
        if isinstance(wire_origin_stmt, wire.Unwrap):
            node.delete()  # get rid of wrap
            wire_origin_stmt.delete()  # get rid of the unwrap
            return RewriteResult(has_done_something=True)

    return RewriteResult()

wire

A NVIDIA QUAKE-like wire dialect.

This dialect is expected to be used in combination with the operator dialect as an intermediate representation for analysis and optimization of quantum circuits. Thus we do not define wrapping functions for the statements in this dialect.