Skip to content

dialects

auxiliary

stmts

const

ConstBool

Bases: Statement

IR Statement representing a constant boolean value.

result class-attribute instance-attribute
result: ResultValue = result(Bool)

result (Float): The result value.

value class-attribute instance-attribute
value: bool = attribute(Bool)

value (float): The constant float value.

ConstFloat

Bases: Statement

IR Statement representing a constant float value.

result class-attribute instance-attribute
result: ResultValue = result(Float)

result (Float): The result value.

value class-attribute instance-attribute
value: float = attribute(Float)

value (float): The constant float value.

ConstInt

Bases: Statement

IR Statement representing a constant integer value.

result class-attribute instance-attribute
result: ResultValue = result(Int)

result (Int): The result value.

value class-attribute instance-attribute
value: int = attribute(Int)

value (int): The constant integer value.

ConstStr

Bases: Statement

IR Statement representing a constant str value.

result class-attribute instance-attribute
result: ResultValue = result(String)

result (str): The result value.

value class-attribute instance-attribute
value: str = attribute(String)

value (str): The constant str value.

Neg

Bases: Statement

IR Statement representing a negation operation.

collapse

stmts

measure

Measurement

Bases: Statement

p class-attribute instance-attribute
p: SSAValue = argument(Float)

probability of noise introduced by measurement. For example 0.01 means 1% the measurement will be flipped

pp_measure

PPMeasurement

Bases: Statement

p class-attribute instance-attribute
p: SSAValue = argument(Float)

probability of noise introduced by measurement. For example 0.01 means 1% the measurement will be flipped

parse

lowering

One-to-one lowering routine from stim circuit to a stim-dialect kirin kernel.

loads

loads(
    stim_str: str,
    *,
    kernel_name: str = "main",
    ignore_unknown_stim: bool = False,
    error_unknown_nonstim: bool = False,
    nonstim_noise_ops: dict[str, type[Statement]] = {},
    dialects: DialectGroup | None = None,
    globals: dict[str, Any] | None = None,
    file: str | None = None,
    lineno_offset: int = 0,
    col_offset: int = 0,
    compactify: bool = True
) -> ir.Method[[], None]

Loads a STIM string and returns the corresponding kernel object.

Parameters:

Name Type Description Default
stim_str str

The string representation of a STIM circuit to load.

required

Other Parameters:

Name Type Description
kernel_name str

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

ignore_unknown_stim bool

If True, don't throw a build error on an unimplemented stim instruction.

error_unknown_nonstim bool

If True, throw a build error if an unknown tag is used on the I_ERROR instruction.

nonstim_noise_ops dict[str, Statement]

Additional statements to represent non-standard stim operations. The dictionary key should match the tag used to identify it in stim (stim format I_ERROR[MY_NOISE](0.05) 0 1 2 3 or I_ERROR[MY_CORRELATED_NOISE:2417696374](0.03) 1 3 5).

dialects DialectGroup | None

The dialects to use. Defaults to stim.main.

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 bloqade.stim.lowering import loads
method = loads('''
    X 0 2 4
    DEPOLARIZE1(0.01) 0
    I_ERROR[CUSTOM_ERROR](0.02) 2 4
    M 0 2 4
    DETECTOR rec[-1] rec[-2]
''')
Source code in .venv/lib/python3.12/site-packages/bloqade/stim/parse/lowering.py
 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
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
def loads(
    stim_str: str,
    *,
    kernel_name: str = "main",
    ignore_unknown_stim: bool = False,
    error_unknown_nonstim: bool = False,
    nonstim_noise_ops: dict[str, type[kirin.ir.Statement]] = {},
    dialects: ir.DialectGroup | None = None,
    globals: dict[str, Any] | None = None,
    file: str | None = None,
    lineno_offset: int = 0,
    col_offset: int = 0,
    compactify: bool = True,
) -> ir.Method[[], None]:
    """Loads a STIM string and returns the corresponding kernel object.

    Args:
        stim_str: The string representation of a STIM circuit to load.

    Keyword Args:
        kernel_name (str): The name of the kernel to load. Defaults to "main".
        ignore_unknown_stim (bool): If True, don't throw a build error on an
            unimplemented stim instruction.
        error_unknown_nonstim (bool): If True, throw a build error if an unknown tag is
            used on the `I_ERROR` instruction.
        nonstim_noise_ops (dict[str, kirin.ir.Statement]): Additional statements to
            represent non-standard stim operations.  The dictionary key should match the
            tag used to identify it in stim (stim format
            `I_ERROR[MY_NOISE](0.05) 0 1 2 3` or
            `I_ERROR[MY_CORRELATED_NOISE:2417696374](0.03) 1 3 5`).
        dialects (ir.DialectGroup | None): The dialects to use. Defaults to `stim.main`.
        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 bloqade.stim.lowering import loads
    method = loads('''
        X 0 2 4
        DEPOLARIZE1(0.01) 0
        I_ERROR[CUSTOM_ERROR](0.02) 2 4
        M 0 2 4
        DETECTOR rec[-1] rec[-2]
    ''')
    ```
    """
    import stim  # Optional dependency required to lower stim circuits

    circ = stim.Circuit(stim_str)
    stim_lowering = Stim(
        kstim.main if dialects is None else dialects,
        ignore_unknown_stim=ignore_unknown_stim,
        error_unknown_nonstim=error_unknown_nonstim,
        nonstim_noise_ops=nonstim_noise_ops,
    )
    frame = stim_lowering.get_frame(
        circ,
        source=stim_str,
        file=file,
        globals=globals,
        lineno_offset=lineno_offset,
        col_offset=col_offset,
        compactify=compactify,
    )

    return_value = func.ConstantNone()  # No return value
    frame.push(return_value)
    return_node = frame.push(func.Return(value_or_stmt=return_value))

    body = frame.curr_region
    code = func.Function(
        sym_name=kernel_name,
        signature=func.Signature((), return_node.value.type),
        body=body,
    )
    return ir.Method(
        mod=None,
        py_func=None,
        sym_name=kernel_name,
        arg_names=[],
        dialects=kstim.dialects,
        code=code,
    )

rewrite

ifs_to_stim

IfElseSimplification dataclass

IfElseSimplification()

contains_ifelse

contains_ifelse(stmt: IfElse) -> bool

Check if the IfElse statement contains another IfElse statement.

Source code in .venv/lib/python3.12/site-packages/bloqade/stim/rewrite/ifs_to_stim.py
35
36
37
38
39
40
def contains_ifelse(self, stmt: scf.IfElse) -> bool:
    """Check if the IfElse statement contains another IfElse statement."""
    for child in stmt.walk(include_self=False):
        if isinstance(child, scf.IfElse):
            return True
    return False

has_else_body

has_else_body(stmt: IfElse) -> bool

Check if the IfElse statement has an else body.

Source code in .venv/lib/python3.12/site-packages/bloqade/stim/rewrite/ifs_to_stim.py
57
58
59
60
61
62
63
64
65
66
def has_else_body(self, stmt: scf.IfElse) -> bool:
    """Check if the IfElse statement has an else body."""
    if stmt.else_body.blocks and not (
        len(stmt.else_body.blocks[0].stmts) == 1
        and isinstance(else_term := stmt.else_body.blocks[0].last_stmt, scf.Yield)
        and not else_term.values  # empty yield
    ):
        return True

    return False

is_nested_ifelse

is_nested_ifelse(stmt: IfElse) -> bool

Check if the IfElse statement is nested.

Source code in .venv/lib/python3.12/site-packages/bloqade/stim/rewrite/ifs_to_stim.py
45
46
47
48
49
50
51
52
53
54
55
def is_nested_ifelse(self, stmt: scf.IfElse) -> bool:
    """Check if the IfElse statement is nested."""
    if stmt.parent_stmt is not None:
        if isinstance(stmt.parent_stmt, scf.IfElse) or isinstance(
            stmt.parent_stmt.parent_stmt, scf.IfElse
        ):
            return True
        else:
            return False
    else:
        return False

IfToStim dataclass

IfToStim(
    measure_analysis: dict[SSAValue, MeasureId],
    measure_count: int,
)

Bases: IfElseSimplification, RewriteRule

Rewrite if statements to stim equivalent statements.

StimSplitIfStmts dataclass

StimSplitIfStmts()

Bases: IfElseSimplification, SplitIfStmts

Splits the then body of an if-else statement into multiple if statements

Given an IfElse with multiple valid statements in the then-body:

if measure_result

squin.qubit.apply(op.X, q0) squin.qubit.apply(op.Y, q1)

this should be rewritten to:

if measure_result

squin.qubit.apply(op.X, q0)

if measure_result

squin.qubit.apply(op.Y, q1)

qubit_to_stim

SquinQubitToStim

Bases: RewriteRule

NOTE this require address analysis result to be wrapped before using this rule.

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/stim/rewrite/qubit_to_stim.py
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
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

    if isinstance(applied_op, noise.stmts.QubitLoss):
        return rewrite_QubitLoss(stmt)

    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

    # check if its adjoint, assume its canonicalized so no nested adjoints.
    is_conj = False
    if isinstance(applied_op, op.stmts.Adjoint):
        if not applied_op.is_unitary:
            return RewriteResult()

        is_conj = True
        applied_op = applied_op.op.owner

    stim_1q_op = SQUIN_STIM_OP_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()

    if isinstance(stim_1q_op, gate.stmts.Gate):
        stim_1q_stmt = stim_1q_op(targets=tuple(qubit_idx_ssas), dagger=is_conj)
    else:
        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 dataclass

SquinMeasureToStim(
    measure_id_result: dict[SSAValue, MeasureId],
    total_measure_count: int,
)

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/stim/rewrite/squin_measure.py
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
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

insert_get_record_list

insert_get_record_list(
    node: Statement,
    measure_id_tuple: MeasureIdTuple,
    meas_count: int,
)

Insert GetRecord statements before the given node

Source code in .venv/lib/python3.12/site-packages/bloqade/stim/rewrite/squin_measure.py
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
def insert_get_record_list(
    node: ir.Statement, measure_id_tuple: MeasureIdTuple, meas_count: int
):
    """
    Insert GetRecord statements before the given node
    """
    get_record_ssas = []
    for measure_id_bool in measure_id_tuple.data:
        assert isinstance(measure_id_bool, MeasureIdBool)
        target_rec_idx = (measure_id_bool.idx - 1) - meas_count
        idx_stmt = py.constant.Constant(target_rec_idx)
        idx_stmt.insert_before(node)
        get_record_stmt = auxiliary.GetRecord(idx_stmt.result)
        get_record_stmt.insert_before(node)
        get_record_ssas.append(get_record_stmt.result)

    node.replace_by(ilist.New(values=get_record_ssas))

squin_noise

SquinNoiseToStim dataclass

SquinNoiseToStim()

Bases: RewriteRule

rewrite_Apply_and_Broadcast

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

Rewrite Apply and Broadcast to their stim statements.

Source code in .venv/lib/python3.12/site-packages/bloqade/stim/rewrite/squin_noise.py
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
def rewrite_Apply_and_Broadcast(
    self, stmt: qubit.Apply | qubit.Broadcast
) -> RewriteResult:
    """Rewrite Apply and Broadcast to their stim statements."""

    # this is an SSAValue, need it to be the actual operator
    applied_op = stmt.operator.owner

    if isinstance(applied_op, squin_noise.stmts.QubitLoss):
        return RewriteResult()

    if isinstance(applied_op, squin_noise.stmts.NoiseChannel):

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

        rewrite_method = getattr(self, f"rewrite_{type(applied_op).__name__}")
        stim_stmt = rewrite_method(stmt, qubit_idx_ssas)

        if isinstance(stmt, (wire.Apply, wire.Broadcast)):
            create_wire_passthrough(stmt)

        if stim_stmt is not None:
            stmt.replace_by(stim_stmt)
        if len(stmt.operator.owner.result.uses) == 0:
            stmt.operator.owner.delete()

        return RewriteResult(has_done_something=True)
    return RewriteResult()

rewrite_Depolarize

rewrite_Depolarize(
    stmt: Apply | Broadcast | Broadcast | Apply,
    qubit_idx_ssas: Tuple[SSAValue],
) -> Statement

Rewrite squin.noise.Depolarize to stim.Depolarize1.

Source code in .venv/lib/python3.12/site-packages/bloqade/stim/rewrite/squin_noise.py
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
def rewrite_Depolarize(
    self,
    stmt: qubit.Apply | qubit.Broadcast | wire.Broadcast | wire.Apply,
    qubit_idx_ssas: Tuple[SSAValue],
) -> Statement:
    """Rewrite squin.noise.Depolarize to stim.Depolarize1."""

    squin_channel = stmt.operator.owner
    assert isinstance(squin_channel, squin_noise.stmts.Depolarize)

    p = get_const_value(float, squin_channel.p)
    p_stmt = py.Constant(p)
    p_stmt.insert_before(stmt)

    stim_stmt = stim_noise.Depolarize1(targets=qubit_idx_ssas, p=p_stmt.result)
    return stim_stmt

rewrite_Depolarize2

rewrite_Depolarize2(
    stmt: Apply | Broadcast | Broadcast | Apply,
    qubit_idx_ssas: Tuple[SSAValue],
) -> Statement

Rewrite squin.noise.Depolarize2 to stim.Depolarize2.

Source code in .venv/lib/python3.12/site-packages/bloqade/stim/rewrite/squin_noise.py
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
def rewrite_Depolarize2(
    self,
    stmt: qubit.Apply | qubit.Broadcast | wire.Broadcast | wire.Apply,
    qubit_idx_ssas: Tuple[SSAValue],
) -> Statement:
    """Rewrite squin.noise.Depolarize2 to stim.Depolarize2."""

    squin_channel = stmt.operator.owner
    assert isinstance(squin_channel, squin_noise.stmts.Depolarize2)

    p = get_const_value(float, squin_channel.p)
    p_stmt = py.Constant(p)
    p_stmt.insert_before(stmt)

    stim_stmt = stim_noise.Depolarize2(targets=qubit_idx_ssas, p=p_stmt.result)
    return stim_stmt

rewrite_PauliError

rewrite_PauliError(
    stmt: Apply | Broadcast | Broadcast | Apply,
    qubit_idx_ssas: Tuple[SSAValue],
) -> Statement

Rewrite squin.noise.PauliError to XError, YError, ZError.

Source code in .venv/lib/python3.12/site-packages/bloqade/stim/rewrite/squin_noise.py
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
def rewrite_PauliError(
    self,
    stmt: qubit.Apply | qubit.Broadcast | wire.Broadcast | wire.Apply,
    qubit_idx_ssas: Tuple[SSAValue],
) -> Statement:
    """Rewrite squin.noise.PauliError to XError, YError, ZError."""
    squin_channel = stmt.operator.owner
    assert isinstance(squin_channel, squin_noise.stmts.PauliError)
    basis = squin_channel.basis.owner
    assert isinstance(basis, op.stmts.PauliOp)
    p = get_const_value(float, squin_channel.p)

    p_stmt = py.Constant(p)
    p_stmt.insert_before(stmt)

    if isinstance(basis, op.stmts.X):
        stim_stmt = stim_noise.XError(targets=qubit_idx_ssas, p=p_stmt.result)
    elif isinstance(basis, op.stmts.Y):
        stim_stmt = stim_noise.YError(targets=qubit_idx_ssas, p=p_stmt.result)
    else:
        stim_stmt = stim_noise.ZError(targets=qubit_idx_ssas, p=p_stmt.result)
    return stim_stmt

rewrite_SingleQubitPauliChannel

rewrite_SingleQubitPauliChannel(
    stmt: Apply | Broadcast | Broadcast | Apply,
    qubit_idx_ssas: Tuple[SSAValue],
) -> Statement

Rewrite squin.noise.SingleQubitPauliChannel to stim.PauliChannel1.

Source code in .venv/lib/python3.12/site-packages/bloqade/stim/rewrite/squin_noise.py
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
def rewrite_SingleQubitPauliChannel(
    self,
    stmt: qubit.Apply | qubit.Broadcast | wire.Broadcast | wire.Apply,
    qubit_idx_ssas: Tuple[SSAValue],
) -> Statement:
    """Rewrite squin.noise.SingleQubitPauliChannel to stim.PauliChannel1."""

    squin_channel = stmt.operator.owner
    assert isinstance(squin_channel, squin_noise.stmts.SingleQubitPauliChannel)

    params = get_const_value(ilist.IList, squin_channel.params)
    new_stmts = [
        p_x := py.Constant(params[0]),
        p_y := py.Constant(params[1]),
        p_z := py.Constant(params[2]),
    ]
    for new_stmt in new_stmts:
        new_stmt.insert_before(stmt)

    stim_stmt = stim_noise.PauliChannel1(
        targets=qubit_idx_ssas,
        px=p_x.result,
        py=p_y.result,
        pz=p_z.result,
    )
    return stim_stmt

rewrite_TwoQubitPauliChannel

rewrite_TwoQubitPauliChannel(
    stmt: Apply | Broadcast | Broadcast | Apply,
    qubit_idx_ssas: Tuple[SSAValue],
) -> Statement

Rewrite squin.noise.SingleQubitPauliChannel to stim.PauliChannel1.

Source code in .venv/lib/python3.12/site-packages/bloqade/stim/rewrite/squin_noise.py
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
def rewrite_TwoQubitPauliChannel(
    self,
    stmt: qubit.Apply | qubit.Broadcast | wire.Broadcast | wire.Apply,
    qubit_idx_ssas: Tuple[SSAValue],
) -> Statement:
    """Rewrite squin.noise.SingleQubitPauliChannel to stim.PauliChannel1."""

    squin_channel = stmt.operator.owner
    assert isinstance(squin_channel, squin_noise.stmts.TwoQubitPauliChannel)

    params = get_const_value(ilist.IList, squin_channel.params)
    param_stmts = [py.Constant(p) for p in params]
    for param_stmt in param_stmts:
        param_stmt.insert_before(stmt)

    stim_stmt = stim_noise.PauliChannel2(
        targets=qubit_idx_ssas,
        pix=param_stmts[0].result,
        piy=param_stmts[1].result,
        piz=param_stmts[2].result,
        pxi=param_stmts[3].result,
        pxx=param_stmts[4].result,
        pxy=param_stmts[5].result,
        pxz=param_stmts[6].result,
        pyi=param_stmts[7].result,
        pyx=param_stmts[8].result,
        pyy=param_stmts[9].result,
        pyz=param_stmts[10].result,
        pzi=param_stmts[11].result,
        pzx=param_stmts[12].result,
        pzy=param_stmts[13].result,
        pzz=param_stmts[14].result,
    )
    return stim_stmt

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/stim/rewrite/util.py
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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/stim/rewrite/util.py
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
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
            create_and_insert_qubit_idx_stmt(
                address_qubit.data, stmt_to_insert_before, qubit_idx_ssas
            )
    elif isinstance(address_data, AddressReg):
        for qubit_idx in address_data.data:
            create_and_insert_qubit_idx_stmt(
                qubit_idx, stmt_to_insert_before, qubit_idx_ssas
            )
    elif isinstance(address_data, AddressQubit):
        create_and_insert_qubit_idx_stmt(
            address_data.data, stmt_to_insert_before, qubit_idx_ssas
        )
    elif isinstance(address_data, AddressWire):
        address_qubit = address_data.origin_qubit
        create_and_insert_qubit_idx_stmt(
            address_qubit.data, stmt_to_insert_before, qubit_idx_ssas
        )
    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/stim/rewrite/util.py
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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/stim/rewrite/util.py
200
201
202
203
204
205
206
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/stim/rewrite/util.py
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
159
160
161
162
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)

    stim_gate = SQUIN_STIM_CONTROL_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)):
        create_wire_passthrough(stmt_with_ctrl)

    stmt_with_ctrl.replace_by(stim_stmt)

    return RewriteResult(has_done_something=True)

rewrite_QubitLoss

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

Rewrite QubitLoss statements to Stim's TrivialError.

Source code in .venv/lib/python3.12/site-packages/bloqade/stim/rewrite/util.py
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
def rewrite_QubitLoss(
    stmt: qubit.Apply | qubit.Broadcast | wire.Broadcast | wire.Apply,
) -> RewriteResult:
    """
    Rewrite QubitLoss statements to Stim's TrivialError.
    """

    squin_loss_op = stmt.operator.owner
    assert isinstance(squin_loss_op, squin_noise.stmts.QubitLoss)

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

    stim_loss_stmt = stim_noise.QubitLoss(
        targets=qubit_idx_ssas,
        probs=(squin_loss_op.p,),
    )

    if isinstance(stmt, (wire.Apply, wire.Broadcast)):
        create_wire_passthrough(stmt)

    stmt.replace_by(stim_loss_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/stim/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()