Skip to content

base

DynamicMemory dataclass

DynamicMemory(
    pyqrack_options: PyQrackOptions = _default_pyqrack_args(),
)

Bases: MemoryABC

allocate

allocate(n_qubits: int)

Allocate n_qubits qubits and return their ids.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/base.py
128
129
130
131
132
133
def allocate(self, n_qubits: int):
    start = self.sim_reg.num_qubits()
    for i in range(start, start + n_qubits):
        self.sim_reg.allocate_qubit(i)

    return tuple(range(start, start + n_qubits))

MemoryABC dataclass

MemoryABC(
    pyqrack_options: PyQrackOptions = _default_pyqrack_args(),
)

Bases: ABC

allocate abstractmethod

allocate(n_qubits: int) -> tuple[int, ...]

Allocate n_qubits qubits and return their ids.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/base.py
66
67
68
69
@abc.abstractmethod
def allocate(self, n_qubits: int) -> tuple[int, ...]:
    """Allocate `n_qubits` qubits and return their ids."""
    ...

reset

reset()

Reset the memory, releasing all qubits.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/base.py
71
72
73
74
75
76
77
def reset(self):
    """Reset the memory, releasing all qubits."""
    from pyqrack import QrackSimulator

    # do not reset the simulator it might be used by
    # results of the simulation
    self.sim_reg = QrackSimulator(**self.pyqrack_options)

MockMemory dataclass

MockMemory(
    pyqrack_options: PyQrackOptions = _default_pyqrack_args(),
)

Bases: MemoryABC

Mock memory for testing purposes.

allocate

allocate(n_qubits: int)

Allocate n_qubits qubits and return their ids.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/base.py
86
87
88
89
90
def allocate(self, n_qubits: int):
    allocated = self.allocated + n_qubits
    result = tuple(range(self.allocated, allocated))
    self.allocated = allocated
    return result

reset

reset()

Reset the memory, releasing all qubits.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/base.py
92
93
94
def reset(self):
    self.allocated = 0
    self.sim_reg = Mock()

PyQrackInterpreter dataclass

PyQrackInterpreter(
    *,
    memory: MemoryType,
    rng_state: Generator = np.random.default_rng(),
    loss_m_result: Measurement = Measurement.One
)

Bases: Interpreter, Generic[MemoryType]

loss_m_result class-attribute instance-attribute

loss_m_result: Measurement = field(
    default=One, kw_only=True
)

The value of a measurement result when a qubit is lost.

StackMemory dataclass

StackMemory(
    pyqrack_options: PyQrackOptions = _default_pyqrack_args(),
    *,
    total: int
)

Bases: MemoryABC

allocate

allocate(n_qubits: int)

Allocate n_qubits qubits and return their ids.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/base.py
102
103
104
105
106
107
108
109
110
111
112
113
def allocate(self, n_qubits: int):
    curr_allocated = self.allocated
    self.allocated += n_qubits

    if self.allocated > self.total:
        raise InterpreterError(
            f"qubit allocation exceeds memory, "
            f"{self.total} qubits, "
            f"{self.allocated} allocated"
        )

    return tuple(range(curr_allocated, self.allocated))

reset

reset()

Reset the memory, releasing all qubits.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/base.py
115
116
117
def reset(self):
    super().reset()
    self.allocated = 0

device

DynamicMemorySimulator dataclass

DynamicMemorySimulator(
    options: PyQrackOptions = _default_pyqrack_args(),
    *,
    loss_m_result: Measurement = Measurement.One,
    rng_state: Generator = np.random.default_rng()
)

Bases: PyQrackSimulatorBase

PyQrack simulator device with dynamic qubit allocation.

This can be used to simulate kernels where the number of qubits is not known ahead of time.

Usage examples

# Define a kernel
@qasm2.main
def main():
    q = qasm2.qreg(2)
    c = qasm2.creg(2)

    qasm2.h(q[0])
    qasm2.cx(q[0], q[1])

    qasm2.measure(q, c)
    return q

# Create the simulator object
sim = DynamicMemorySimulator()

# Execute the kernel
qubits = sim.run(main)

You can also obtain other information from it, such as the state vector:

``` ket = sim.state_vector(main)

from pyqrack.pauli import Pauli expectation_vals = sim.pauli_expectation([Pauli.PauliX, Pauli.PauliI], qubits)

task

task(
    kernel: Method[Params, RetType],
    args: tuple[Any, ...] = (),
    kwargs: dict[str, Any] | None = None,
)

Parameters:

Name Type Description Default
kernel Method

The kernel method to run.

required
args tuple[Any, ...]

Positional arguments to pass to the kernel method.

()
kwargs dict[str, Any] | None

Keyword arguments to pass to the kernel method.

None

Returns:

Name Type Description
PyQrackSimulatorTask

The task object used to track execution.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/device.py
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
def task(
    self,
    kernel: ir.Method[Params, RetType],
    args: tuple[Any, ...] = (),
    kwargs: dict[str, Any] | None = None,
):
    """
    Args:
        kernel (ir.Method):
            The kernel method to run.
        args (tuple[Any, ...]):
            Positional arguments to pass to the kernel method.
        kwargs (dict[str, Any] | None):
            Keyword arguments to pass to the kernel method.

    Returns:
        PyQrackSimulatorTask:
            The task object used to track execution.

    """
    if kwargs is None:
        kwargs = {}

    memory = DynamicMemory(self.options.copy())
    return self.new_task(kernel, args, kwargs, memory)

PyQrackSimulatorBase dataclass

PyQrackSimulatorBase(
    options: PyQrackOptions = _default_pyqrack_args(),
    *,
    loss_m_result: Measurement = Measurement.One,
    rng_state: Generator = np.random.default_rng()
)

Bases: AbstractSimulatorDevice[PyQrackSimulatorTask]

PyQrack simulation device base class.

options class-attribute instance-attribute

options: PyQrackOptions = field(
    default_factory=_default_pyqrack_args
)

options (PyQrackOptions): options passed into the pyqrack simulator.

pauli_expectation staticmethod

pauli_expectation(
    pauli: list[Pauli], qubits: list[PyQrackQubit]
) -> float

Returns the expectation value of the given Pauli operator given a list of Pauli operators and qubits.

Parameters:

Name Type Description Default
pauli list[Pauli]

List of Pauli operators to compute the expectation value for.

required
qubits list[PyQrackQubit]

List of qubits corresponding to the Pauli operators.

required

Returns:

Name Type Description
float float

The expectation value of the Pauli operator.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/device.py
 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
@staticmethod
def pauli_expectation(pauli: list[Pauli], qubits: list[PyQrackQubit]) -> float:
    """Returns the expectation value of the given Pauli operator given a list of Pauli operators and qubits.

    Args:
        pauli (list[Pauli]):
            List of Pauli operators to compute the expectation value for.
        qubits (list[PyQrackQubit]):
            List of qubits corresponding to the Pauli operators.

    returns:
        float:
            The expectation value of the Pauli operator.

    """

    if len(pauli) == 0:
        return 0.0

    if len(pauli) != len(qubits):
        raise ValueError("Length of Pauli and qubits must match.")

    sim_reg = qubits[0].sim_reg

    if any(qubit.sim_reg is not sim_reg for qubit in qubits):
        raise ValueError("All qubits must belong to the same simulator register.")

    qubit_ids = [qubit.addr for qubit in qubits]

    if len(qubit_ids) != len(set(qubit_ids)):
        raise ValueError("Qubits must be unique.")

    return sim_reg.pauli_expectation(qubit_ids, pauli)

state_vector

state_vector(
    kernel: Method[Params, RetType],
    args: tuple[Any, ...] = (),
    kwargs: dict[str, Any] | None = None,
) -> list[complex]

Runs task and returns the state vector.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/device.py
60
61
62
63
64
65
66
67
68
69
def state_vector(
    self,
    kernel: ir.Method[Params, RetType],
    args: tuple[Any, ...] = (),
    kwargs: dict[str, Any] | None = None,
) -> list[complex]:
    """Runs task and returns the state vector."""
    task = self.task(kernel, args, kwargs)
    task.run()
    return task.state.sim_reg.out_ket()

StackMemorySimulator dataclass

StackMemorySimulator(
    options: PyQrackOptions = _default_pyqrack_args(),
    *,
    loss_m_result: Measurement = Measurement.One,
    rng_state: Generator = np.random.default_rng(),
    min_qubits: int = 0
)

Bases: PyQrackSimulatorBase

PyQrack simulator device with preallocated stack of qubits.

This can be used to simulate kernels where the number of qubits is known ahead of time.

Usage examples

# Define a kernel
@qasm2.main
def main():
    q = qasm2.qreg(2)
    c = qasm2.creg(2)

    qasm2.h(q[0])
    qasm2.cx(q[0], q[1])

    qasm2.measure(q, c)
    return q

# Create the simulator object
sim = StackMemorySimulator(min_qubits=2)

# Execute the kernel
qubits = sim.run(main)

You can also obtain other information from it, such as the state vector:

ket = sim.state_vector(main)

from pyqrack.pauli import Pauli
expectation_vals = sim.pauli_expectation([Pauli.PauliX, Pauli.PauliI], qubits)

task

task(
    kernel: Method[Params, RetType],
    args: tuple[Any, ...] = (),
    kwargs: dict[str, Any] | None = None,
)

Parameters:

Name Type Description Default
kernel Method

The kernel method to run.

required
args tuple[Any, ...]

Positional arguments to pass to the kernel method.

()
kwargs dict[str, Any] | None

Keyword arguments to pass to the kernel method.

None

Returns:

Name Type Description
PyQrackSimulatorTask

The task object used to track execution.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/device.py
148
149
150
151
152
153
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
182
183
184
185
186
187
188
def task(
    self,
    kernel: ir.Method[Params, RetType],
    args: tuple[Any, ...] = (),
    kwargs: dict[str, Any] | None = None,
):
    """
    Args:
        kernel (ir.Method):
            The kernel method to run.
        args (tuple[Any, ...]):
            Positional arguments to pass to the kernel method.
        kwargs (dict[str, Any] | None):
            Keyword arguments to pass to the kernel method.

    Returns:
        PyQrackSimulatorTask:
            The task object used to track execution.

    """
    if kwargs is None:
        kwargs = {}

    address_analysis = AddressAnalysis(dialects=kernel.dialects)
    frame, _ = address_analysis.run_analysis(kernel)
    if self.min_qubits == 0 and any(
        isinstance(a, AnyAddress) for a in frame.entries.values()
    ):
        raise ValueError(
            "All addresses must be resolved. Or set min_qubits to a positive integer."
        )

    num_qubits = max(address_analysis.qubit_count, self.min_qubits)
    options = self.options.copy()
    options["qubitCount"] = num_qubits
    memory = StackMemory(
        options,
        total=num_qubits,
    )

    return self.new_task(kernel, args, kwargs, memory)

reg

CBitRef dataclass

CBitRef(ref: CRegister, pos: int)

Object representing a reference to a classical bit.

pos instance-attribute

pos: int

The position of this bit in the classical register.

ref instance-attribute

ref: CRegister

The classical register that is holding this bit.

CRegister

CRegister(size: int)

Bases: list[Measurement]

Runtime representation of a classical register.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/reg.py
22
23
def __init__(self, size: int):
    super().__init__(Measurement.Zero for _ in range(size))

Measurement

Bases: IntEnum

Enumeration of measurement results.

PyQrackQubit dataclass

PyQrackQubit(
    addr: int, sim_reg: QrackSimulator, state: QubitState
)

Bases: Qubit

The runtime representation of a qubit reference.

addr instance-attribute

addr: int

The address of this qubit in the quantum register.

sim_reg instance-attribute

sim_reg: QrackSimulator

The register of the simulator.

state instance-attribute

state: QubitState

The state of the qubit (active/lost)

drop

drop()

Drop the qubit in-place.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/reg.py
70
71
72
def drop(self):
    """Drop the qubit in-place."""
    self.state = QubitState.Lost

is_active

is_active() -> bool

Check if the qubit is active.

Returns True if the qubit is active, False otherwise.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/reg.py
61
62
63
64
65
66
67
68
def is_active(self) -> bool:
    """Check if the qubit is active.

    Returns
        True if the qubit is active, False otherwise.

    """
    return self.state is QubitState.Active

squin

runtime

OperatorRuntimeABC dataclass

OperatorRuntimeABC()

The number of sites the operator applies to (including controls)

target

PyQrack dataclass

PyQrack(
    min_qubits: int = 0,
    dynamic_qubits: bool = False,
    pyqrack_options: PyQrackOptions = _default_pyqrack_args(),
)

PyQrack target runtime for Bloqade.

dynamic_qubits class-attribute instance-attribute

dynamic_qubits: bool = False

Whether to use dynamic qubit allocation. Cannot use with tensor network simulations.

min_qubits class-attribute instance-attribute

min_qubits: int = 0

Minimum number of qubits required for the PyQrack simulator. Useful when address analysis fails to determine the number of qubits.

pyqrack_options class-attribute instance-attribute

pyqrack_options: PyQrackOptions = field(
    default_factory=_default_pyqrack_args
)

Options to pass to the QrackSimulator object, node qubitCount will be overwritten.

multi_run

multi_run(
    mt: Method[Params, RetType],
    _shots: int,
    *args: args,
    **kwargs: kwargs
) -> List[RetType]

Run the given kernel method on the PyQrack _shots times, caching analysis results.

Args mt (Method): The kernel method to run. _shots (int): The number of times to run the kernel method.

Returns List of results of the kernel method, one for each shot.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/target.py
 92
 93
 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
def multi_run(
    self,
    mt: ir.Method[Params, RetType],
    _shots: int,
    *args: Params.args,
    **kwargs: Params.kwargs,
) -> List[RetType]:
    """Run the given kernel method on the PyQrack `_shots` times, caching analysis results.

    Args
        mt (Method):
            The kernel method to run.
        _shots (int):
            The number of times to run the kernel method.

    Returns
        List of results of the kernel method, one for each shot.

    """
    fold = Fold(mt.dialects)
    fold(mt)

    interpreter = self._get_interp(mt)
    batched_results = []
    for _ in range(_shots):
        batched_results.append(interpreter.run(mt, args, kwargs))

    return batched_results

run

run(
    mt: Method[Params, RetType],
    *args: args,
    **kwargs: kwargs
) -> RetType

Run the given kernel method on the PyQrack simulator.

Args mt (Method): The kernel method to run.

Returns The result of the kernel method, if any.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/target.py
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
def run(
    self,
    mt: ir.Method[Params, RetType],
    *args: Params.args,
    **kwargs: Params.kwargs,
) -> RetType:
    """Run the given kernel method on the PyQrack simulator.

    Args
        mt (Method):
            The kernel method to run.

    Returns
        The result of the kernel method, if any.

    """
    fold = Fold(mt.dialects)
    fold(mt)
    return self._get_interp(mt).run(mt, args, kwargs)

task

PyQrackSimulatorTask dataclass

PyQrackSimulatorTask(
    kernel: Method[Params, RetType],
    args: tuple[Any, ...],
    kwargs: dict[str, Any],
    pyqrack_interp: PyQrackInterpreter[MemoryType],
)

Bases: AbstractSimulatorTask[Param, RetType, MemoryType]

PyQrack simulator task for Bloqade.

state property

state: MemoryType

Returns the state of the simulator after running the task.

run

run() -> RetType

Executes the kernel and returns the result.

Source code in .venv/lib/python3.12/site-packages/bloqade/pyqrack/task.py
21
22
23
24
25
26
def run(self) -> RetType:
    return self.pyqrack_interp.run(
        self.kernel,
        args=self.args,
        kwargs=self.kwargs,
    )