2525
2626@dataclass
2727class PyQrackSimulatorBase (AbstractSimulatorDevice [PyQrackSimulatorTask ]):
28+ """PyQrack simulation device base class."""
29+
2830 options : PyQrackOptions = field (default_factory = _default_pyqrack_args )
31+ """options (PyQrackOptions): options passed into the pyqrack simulator."""
32+
2933 loss_m_result : Measurement = field (default = Measurement .One , kw_only = True )
3034 rng_state : np .random .Generator = field (
3135 default_factory = np .random .default_rng , kw_only = True
@@ -99,7 +103,43 @@ def pauli_expectation(pauli: list[Pauli], qubits: list[PyQrackQubit]) -> float:
99103
100104@dataclass
101105class StackMemorySimulator (PyQrackSimulatorBase ):
102- """PyQrack simulator device with precalculated stack of qubits."""
106+ """
107+ PyQrack simulator device with preallocated stack of qubits.
108+
109+ This can be used to simulate kernels where the number of qubits is known
110+ ahead of time.
111+
112+ ## Usage examples
113+
114+ ```
115+ # Define a kernel
116+ @qasm2.main
117+ def main():
118+ q = qasm2.qreg(2)
119+ c = qasm2.creg(2)
120+
121+ qasm2.h(q[0])
122+ qasm2.cx(q[0], q[1])
123+
124+ qasm2.measure(q, c)
125+ return q
126+
127+ # Create the simulator object
128+ sim = StackMemorySimulator(min_qubits=2)
129+
130+ # Execute the kernel
131+ qubits = sim.run(main)
132+ ```
133+
134+ You can also obtain other information from it, such as the state vector:
135+
136+ ```
137+ ket = sim.state_vector(main)
138+
139+ from pyqrack.pauli import Pauli
140+ expectation_vals = sim.pauli_expectation([Pauli.PauliX, Pauli.PauliI], qubits)
141+ ```
142+ """
103143
104144 min_qubits : int = field (default = 0 , kw_only = True )
105145
@@ -109,6 +149,20 @@ def task(
109149 args : tuple [Any , ...] = (),
110150 kwargs : dict [str , Any ] | None = None ,
111151 ):
152+ """
153+ Args:
154+ kernel (ir.Method):
155+ The kernel method to run.
156+ args (tuple[Any, ...]):
157+ Positional arguments to pass to the kernel method.
158+ kwargs (dict[str, Any] | None):
159+ Keyword arguments to pass to the kernel method.
160+
161+ Returns:
162+ PyQrackSimulatorTask:
163+ The task object used to track execution.
164+
165+ """
112166 if kwargs is None :
113167 kwargs = {}
114168
@@ -134,31 +188,67 @@ def task(
134188
135189@dataclass
136190class DynamicMemorySimulator (PyQrackSimulatorBase ):
137- """PyQrack simulator device with dynamic qubit allocation."""
191+ """
192+
193+ PyQrack simulator device with dynamic qubit allocation.
194+
195+ This can be used to simulate kernels where the number of qubits is not known
196+ ahead of time.
197+
198+ ## Usage examples
199+
200+ ```
201+ # Define a kernel
202+ @qasm2.main
203+ def main():
204+ q = qasm2.qreg(2)
205+ c = qasm2.creg(2)
206+
207+ qasm2.h(q[0])
208+ qasm2.cx(q[0], q[1])
209+
210+ qasm2.measure(q, c)
211+ return q
212+
213+ # Create the simulator object
214+ sim = DynamicMemorySimulator()
215+
216+ # Execute the kernel
217+ qubits = sim.run(main)
218+ ```
219+
220+ You can also obtain other information from it, such as the state vector:
221+
222+ ```
223+ ket = sim.state_vector(main)
224+
225+ from pyqrack.pauli import Pauli
226+ expectation_vals = sim.pauli_expectation([Pauli.PauliX, Pauli.PauliI], qubits)
227+
228+ """
138229
139230 def task (
140231 self ,
141232 kernel : ir .Method [Params , RetType ],
142233 args : tuple [Any , ...] = (),
143234 kwargs : dict [str , Any ] | None = None ,
144235 ):
236+ """
237+ Args:
238+ kernel (ir.Method):
239+ The kernel method to run.
240+ args (tuple[Any, ...]):
241+ Positional arguments to pass to the kernel method.
242+ kwargs (dict[str, Any] | None):
243+ Keyword arguments to pass to the kernel method.
244+
245+ Returns:
246+ PyQrackSimulatorTask:
247+ The task object used to track execution.
248+
249+ """
145250 if kwargs is None :
146251 kwargs = {}
147252
148253 memory = DynamicMemory (self .options .copy ())
149254 return self .new_task (kernel , args , kwargs , memory )
150-
151-
152- def test ():
153- from bloqade .qasm2 import extended
154-
155- @extended
156- def main ():
157- return 1
158-
159- @extended
160- def obs (result : int ) -> int :
161- return result
162-
163- res = DynamicMemorySimulator ().task (main )
164- return res .run ()
0 commit comments