32
32
from numpy import split
33
33
from pyquil .api import QAM , MemoryMap , QAMExecutionResult , QuantumComputer , get_qc
34
34
from pyquil .quil import Program
35
- from qcs_sdk import ExecutionData , RegisterData , ResultData # pylint: disable=no-name-in-module
35
+ from qcs_sdk import ( # pylint: disable=no-name-in-module
36
+ ExecutionData ,
37
+ RegisterData ,
38
+ ResultData ,
39
+ )
36
40
from qcs_sdk .qvm import QVMResultData # pylint: disable=no-name-in-module
37
41
from wrapt import ObjectProxy
38
42
@@ -103,19 +107,82 @@ def compile(
103
107
"""
104
108
return AzureProgram (program , skip_quilc = not to_native_gates )
105
109
106
- def run_batch (
110
+
111
+ def run_with_memory_map_batch (
107
112
self ,
108
113
executable : AzureProgram ,
109
114
memory_maps : Sequence [MemoryMap ],
110
115
** __kwargs : Any ,
111
116
) -> List [QAMExecutionResult ]:
112
- """Run a sequence of memory values through the program.
117
+ """Run the executable for each of the ``memory_maps``.
118
+
119
+ Args:
120
+ executable: The AzureProgram to run.
121
+ memory_maps: An iterable containing ``MemoryMaps`` with desired mappings of parameter names to parameter values.
122
+ Each value is a list as long as the number of elements in the register. So if the register was ``DECLARE theta REAL[2]``
123
+ then the key in the dictionary would be ``theta`` and the value would be a list of length 2. The entire program
124
+ will be run (for shot count) once for each ``MemoryMap``. (If no memory maps are provided, the program will be run once.)
125
+ name: An optional name for the job which will show up in the Azure Quantum UI.
126
+
127
+ Returns:
128
+ A list of ``QAMExecutionResult`` objects, one for each ``MemoryMap``.
129
+
130
+ ```pycon
131
+
132
+ >>> import numpy as np
133
+ >>> from pyquil import Program
134
+ >>> from pyquil.gates import CNOT, MEASURE, RX, H
135
+ >>> from pyquil.quilatom import MemoryReference
136
+ >>> from pyquil.quilbase import Declare
137
+ >>> from pyquil_for_azure_quantum import get_qvm
138
+ >>> qvm = get_qvm()
139
+ >>> program = Program(\
140
+ Declare("ro", "BIT", 1), \
141
+ Declare("theta", "REAL", 1), \
142
+ RX(MemoryReference("theta"), 0), \
143
+ MEASURE(0, ("ro", 0)), \
144
+ ).wrap_in_numshots_loop(1000)
145
+ >>> compiled = qvm.compile(program)
146
+ >>> results = qvm.run_batch(compiled, [{"theta": [value]} for value in [0.0, np.pi, 2 * np.pi]}])
147
+ >>> assert len(results) == 3 # 3 values for theta—each a list of length 1
148
+ >>> results_0 = results[0].readout_data["ro"]
149
+ >>> assert len(results_0) == 1000 # 1000 shots
150
+ >>> assert np.mean(results_0) == 0
151
+ >>> results_pi = results[1].readout_data["ro"]
152
+ >>> assert len(results_pi) == 1000
153
+ >>> assert np.mean(results_pi) == 1
154
+
155
+ ```
113
156
114
157
See Also:
115
158
* [`AzureQuantumMachine.execute_with_memory_map_batch`][pyquil_for_azure_quantum.AzureQuantumMachine.execute_with_memory_map_batch]
116
159
"""
117
160
qam = cast (AzureQuantumMachine , self .qam )
118
- return qam .execute_with_memory_map_batch (executable , memory_maps )
161
+ azure_job = qam .execute_with_memory_map_batch (executable , memory_maps )
162
+ # `execute_with_memory_map_batch` always returns a list of length 1.
163
+ assert len (azure_job ) == 1
164
+
165
+ combined_result = qam .get_result (azure_job [0 ])
166
+
167
+ num_executions = len (memory_maps )
168
+ if num_executions in (0 , 1 ):
169
+ return combined_result
170
+
171
+ ro_matrix = combined_result .data .result_data .to_register_map ().get_register_matrix ("ro" )
172
+ if ro_matrix is None :
173
+ return []
174
+
175
+ return [
176
+ QAMExecutionResult (
177
+ executable ,
178
+ ExecutionData (
179
+ ResultData .from_qvm (
180
+ QVMResultData .from_memory_map (memory = {"ro" : RegisterData (split_result .tolist ())})
181
+ )
182
+ ),
183
+ )
184
+ for split_result in split (ro_matrix .to_ndarray (), num_executions )
185
+ ]
119
186
120
187
121
188
def get_qpu (qpu_name : str ) -> AzureQuantumComputer :
@@ -269,7 +336,7 @@ def execute_with_memory_map_batch(
269
336
memory_maps : Iterable [MemoryMap ],
270
337
name : str = "pyquil-azure-job" ,
271
338
** _kwargs : Any ,
272
- ) -> List [QAMExecutionResult ]:
339
+ ) -> List [AzureJob ]:
273
340
"""Run the executable for each of the ``memory_maps``.
274
341
275
342
Args:
@@ -281,34 +348,10 @@ def execute_with_memory_map_batch(
281
348
name: An optional name for the job which will show up in the Azure Quantum UI.
282
349
283
350
Returns:
284
- A list of ``QAMExecutionResult`` objects, one for each ``MemoryMap``.
285
-
286
- ```pycon
287
-
288
- >>> import numpy as np
289
- >>> from pyquil import Program
290
- >>> from pyquil.gates import CNOT, MEASURE, RX, H
291
- >>> from pyquil.quilatom import MemoryReference
292
- >>> from pyquil.quilbase import Declare
293
- >>> from pyquil_for_azure_quantum import get_qvm
294
- >>> qvm = get_qvm()
295
- >>> program = Program(\
296
- Declare("ro", "BIT", 1), \
297
- Declare("theta", "REAL", 1), \
298
- RX(MemoryReference("theta"), 0), \
299
- MEASURE(0, ("ro", 0)), \
300
- ).wrap_in_numshots_loop(1000)
301
- >>> compiled = qvm.compile(program)
302
- >>> results = qvm.execute_with_memory_map_batch(compiled, [{"theta": [value]} for value in [0.0, np.pi, 2 * np.pi]}])
303
- >>> assert len(results) == 3 # 3 values for theta—each a list of length 1
304
- >>> results_0 = results[0].readout_data["ro"]
305
- >>> assert len(results_0) == 1000 # 1000 shots
306
- >>> assert np.mean(results_0) == 0
307
- >>> results_pi = results[1].readout_data["ro"]
308
- >>> assert len(results_pi) == 1000
309
- >>> assert np.mean(results_pi) == 1
351
+ A list of ``AzureJob`` object; because ``AzureJob`` is not
352
+ considered done until the entire batch is done, this is always a
353
+ list of length one.
310
354
311
- ```
312
355
"""
313
356
executable = executable .copy ()
314
357
memory_maps = list (memory_maps )
@@ -323,27 +366,7 @@ def execute_with_memory_map_batch(
323
366
input_params = input_params ,
324
367
)
325
368
azure_job = AzureJob (job = job , executable = executable )
326
- combined_result = self .get_result (azure_job )
327
-
328
- num_executions = len (memory_maps )
329
- if num_executions in (0 , 1 ):
330
- return [combined_result ]
331
-
332
- ro_matrix = combined_result .data .result_data .to_register_map ().get_register_matrix ("ro" )
333
- if ro_matrix is None :
334
- return []
335
-
336
- return [
337
- QAMExecutionResult (
338
- executable ,
339
- ExecutionData (
340
- ResultData .from_qvm (
341
- QVMResultData .from_memory_map (memory = {"ro" : RegisterData (split_result .tolist ())})
342
- )
343
- ),
344
- )
345
- for split_result in split (ro_matrix .to_ndarray (), num_executions )
346
- ]
369
+ return [azure_job ]
347
370
348
371
349
372
def _make_substitutions_from_memory_maps (
0 commit comments