Skip to content

Commit b51fd12

Browse files
committed
Add some basic dosctrings and usage examples to pyqrack simulator devices
1 parent 89ffbab commit b51fd12

File tree

1 file changed

+111
-18
lines changed

1 file changed

+111
-18
lines changed

src/bloqade/pyqrack/device.py

Lines changed: 111 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@
2525

2626
@dataclass
2727
class PyQrackSimulatorBase(AbstractSimulatorDevice[PyQrackSimulatorTask]):
28+
"""PyQrack simulation device base class.
29+
30+
Args:
31+
options (PyQrackOptions):
32+
Options passed into the PyQrack simulator
33+
"""
34+
2835
options: PyQrackOptions = field(default_factory=_default_pyqrack_args)
2936
loss_m_result: Measurement = field(default=Measurement.One, kw_only=True)
3037
rng_state: np.random.Generator = field(
@@ -96,12 +103,48 @@ def pauli_expectation(pauli: list[Pauli], qubits: list[PyQrackQubit]) -> float:
96103
if len(qubit_ids) != len(set(qubit_ids)):
97104
raise ValueError("Qubits must be unique.")
98105

99-
return sim_reg.pauli_expectation(pauli, qubit_ids)
106+
return sim_reg.pauli_expectation(qubit_ids, pauli)
100107

101108

102109
@dataclass
103110
class StackMemorySimulator(PyQrackSimulatorBase):
104-
"""PyQrack simulator device with precalculated stack of qubits."""
111+
"""
112+
PyQrack simulator device with preallocated stack of qubits.
113+
114+
This can be used to simulate kernels where the number of qubits is known
115+
ahead of time.
116+
117+
## Usage examples
118+
119+
```
120+
# Define a kernel
121+
@qasm2.main
122+
def main():
123+
q = qasm2.qreg(2)
124+
c = qasm2.creg(2)
125+
126+
qasm2.h(q[0])
127+
qasm2.cx(q[0], q[1])
128+
129+
qasm2.measure(q, c)
130+
return q
131+
132+
# Create the simulator object
133+
sim = StackMemorySimulator(min_qubits=2)
134+
135+
# Execute the kernel
136+
qubits = sim.run(main)
137+
```
138+
139+
You can also obtain other information from it, such as the state vector:
140+
141+
```
142+
ket = sim.state_vector(main)
143+
144+
from pyqrack.pauli import Pauli
145+
expectation_vals = sim.pauli_expectation([Pauli.PauliX, Pauli.PauliI], qubits)
146+
```
147+
"""
105148

106149
min_qubits: int = field(default=0, kw_only=True)
107150

@@ -111,6 +154,20 @@ def task(
111154
args: tuple[Any, ...] = (),
112155
kwargs: dict[str, Any] | None = None,
113156
):
157+
"""
158+
Args:
159+
kernel (ir.Method):
160+
The kernel method to run.
161+
args (tuple[Any, ...]):
162+
Positional arguments to pass to the kernel method.
163+
kwargs (dict[str, Any] | None):
164+
Keyword arguments to pass to the kernel method.
165+
166+
Returns:
167+
PyQrackSimulatorTask:
168+
The task object used to track execution.
169+
170+
"""
114171
if kwargs is None:
115172
kwargs = {}
116173

@@ -136,31 +193,67 @@ def task(
136193

137194
@dataclass
138195
class DynamicMemorySimulator(PyQrackSimulatorBase):
139-
"""PyQrack simulator device with dynamic qubit allocation."""
196+
"""
197+
198+
PyQrack simulator device with dynamic qubit allocation.
199+
200+
This can be used to simulate kernels where the number of qubits is not known
201+
ahead of time.
202+
203+
## Usage examples
204+
205+
```
206+
# Define a kernel
207+
@qasm2.main
208+
def main():
209+
q = qasm2.qreg(2)
210+
c = qasm2.creg(2)
211+
212+
qasm2.h(q[0])
213+
qasm2.cx(q[0], q[1])
214+
215+
qasm2.measure(q, c)
216+
return q
217+
218+
# Create the simulator object
219+
sim = DynamicMemorySimulator()
220+
221+
# Execute the kernel
222+
qubits = sim.run(main)
223+
```
224+
225+
You can also obtain other information from it, such as the state vector:
226+
227+
```
228+
ket = sim.state_vector(main)
229+
230+
from pyqrack.pauli import Pauli
231+
expectation_vals = sim.pauli_expectation([Pauli.PauliX, Pauli.PauliI], qubits)
232+
233+
"""
140234

141235
def task(
142236
self,
143237
kernel: ir.Method[Params, RetType],
144238
args: tuple[Any, ...] = (),
145239
kwargs: dict[str, Any] | None = None,
146240
):
241+
"""
242+
Args:
243+
kernel (ir.Method):
244+
The kernel method to run.
245+
args (tuple[Any, ...]):
246+
Positional arguments to pass to the kernel method.
247+
kwargs (dict[str, Any] | None):
248+
Keyword arguments to pass to the kernel method.
249+
250+
Returns:
251+
PyQrackSimulatorTask:
252+
The task object used to track execution.
253+
254+
"""
147255
if kwargs is None:
148256
kwargs = {}
149257

150258
memory = DynamicMemory(self.options.copy())
151259
return self.new_task(kernel, args, kwargs, memory)
152-
153-
154-
def test():
155-
from bloqade.qasm2 import extended
156-
157-
@extended
158-
def main():
159-
return 1
160-
161-
@extended
162-
def obs(result: int) -> int:
163-
return result
164-
165-
res = DynamicMemorySimulator().task(main)
166-
return res.run()

0 commit comments

Comments
 (0)