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
@@ -101,7 +105,43 @@ def pauli_expectation(pauli: list[Pauli], qubits: list[PyQrackQubit]) -> float:
101105
102106@dataclass
103107class StackMemorySimulator (PyQrackSimulatorBase ):
104- """PyQrack simulator device with precalculated stack of qubits."""
108+ """
109+ PyQrack simulator device with preallocated stack of qubits.
110+
111+ This can be used to simulate kernels where the number of qubits is known
112+ ahead of time.
113+
114+ ## Usage examples
115+
116+ ```
117+ # Define a kernel
118+ @qasm2.main
119+ def main():
120+ q = qasm2.qreg(2)
121+ c = qasm2.creg(2)
122+
123+ qasm2.h(q[0])
124+ qasm2.cx(q[0], q[1])
125+
126+ qasm2.measure(q, c)
127+ return q
128+
129+ # Create the simulator object
130+ sim = StackMemorySimulator(min_qubits=2)
131+
132+ # Execute the kernel
133+ qubits = sim.run(main)
134+ ```
135+
136+ You can also obtain other information from it, such as the state vector:
137+
138+ ```
139+ ket = sim.state_vector(main)
140+
141+ from pyqrack.pauli import Pauli
142+ expectation_vals = sim.pauli_expectation([Pauli.PauliX, Pauli.PauliI], qubits)
143+ ```
144+ """
105145
106146 min_qubits : int = field (default = 0 , kw_only = True )
107147
@@ -111,6 +151,20 @@ def task(
111151 args : tuple [Any , ...] = (),
112152 kwargs : dict [str , Any ] | None = None ,
113153 ):
154+ """
155+ Args:
156+ kernel (ir.Method):
157+ The kernel method to run.
158+ args (tuple[Any, ...]):
159+ Positional arguments to pass to the kernel method.
160+ kwargs (dict[str, Any] | None):
161+ Keyword arguments to pass to the kernel method.
162+
163+ Returns:
164+ PyQrackSimulatorTask:
165+ The task object used to track execution.
166+
167+ """
114168 if kwargs is None :
115169 kwargs = {}
116170
@@ -136,31 +190,67 @@ def task(
136190
137191@dataclass
138192class DynamicMemorySimulator (PyQrackSimulatorBase ):
139- """PyQrack simulator device with dynamic qubit allocation."""
193+ """
194+
195+ PyQrack simulator device with dynamic qubit allocation.
196+
197+ This can be used to simulate kernels where the number of qubits is not known
198+ ahead of time.
199+
200+ ## Usage examples
201+
202+ ```
203+ # Define a kernel
204+ @qasm2.main
205+ def main():
206+ q = qasm2.qreg(2)
207+ c = qasm2.creg(2)
208+
209+ qasm2.h(q[0])
210+ qasm2.cx(q[0], q[1])
211+
212+ qasm2.measure(q, c)
213+ return q
214+
215+ # Create the simulator object
216+ sim = DynamicMemorySimulator()
217+
218+ # Execute the kernel
219+ qubits = sim.run(main)
220+ ```
221+
222+ You can also obtain other information from it, such as the state vector:
223+
224+ ```
225+ ket = sim.state_vector(main)
226+
227+ from pyqrack.pauli import Pauli
228+ expectation_vals = sim.pauli_expectation([Pauli.PauliX, Pauli.PauliI], qubits)
229+
230+ """
140231
141232 def task (
142233 self ,
143234 kernel : ir .Method [Params , RetType ],
144235 args : tuple [Any , ...] = (),
145236 kwargs : dict [str , Any ] | None = None ,
146237 ):
238+ """
239+ Args:
240+ kernel (ir.Method):
241+ The kernel method to run.
242+ args (tuple[Any, ...]):
243+ Positional arguments to pass to the kernel method.
244+ kwargs (dict[str, Any] | None):
245+ Keyword arguments to pass to the kernel method.
246+
247+ Returns:
248+ PyQrackSimulatorTask:
249+ The task object used to track execution.
250+
251+ """
147252 if kwargs is None :
148253 kwargs = {}
149254
150255 memory = DynamicMemory (self .options .copy ())
151256 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