Skip to content

Commit fd8a0ef

Browse files
committed
WIP completely unifying qiskit-based devices under the Scaleway device's logic.
1 parent 109d963 commit fd8a0ef

File tree

2 files changed

+104
-69
lines changed

2 files changed

+104
-69
lines changed

pennylane_scaleway/aer_device.py

Lines changed: 97 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
from dataclasses import fields
16+
from inspect import signature
1617
import numpy as np
1718
from tenacity import retry, stop_after_attempt, stop_after_delay
1819
from typing import Callable, Iterable, List, Sequence, Tuple
@@ -113,10 +114,13 @@ def circuit():
113114
```
114115
"""
115116

117+
self._default_shots = None
116118
if shots and not isinstance(shots, int):
117119
raise ValueError(
118120
"Only integer number of shots is supported on this device (vectors are not supported either). The set 'shots' value will be ignored."
119121
)
122+
elif isinstance(shots, int):
123+
self._default_shots = shots
120124

121125
if isinstance(seed, int):
122126
kwargs.update({"seed_simulator": seed})
@@ -125,86 +129,110 @@ def circuit():
125129

126130
self._handle_kwargs(**kwargs)
127131

132+
# def _handle_kwargs(self, **kwargs):
133+
# ### Extract Estimator/Sampler-specific options
134+
# self._sampler_options = {
135+
# k: v
136+
# for k, v in kwargs.items()
137+
# if k in (field.name for field in fields(SamplerOptions))
138+
# }
139+
# self._estimator_options = {
140+
# k: v
141+
# for k, v in kwargs.items()
142+
# if k in (field.name for field in fields(EstimatorOptions))
143+
# }
144+
# [
145+
# kwargs.pop(k)
146+
# for k in (self._sampler_options.keys() | self._estimator_options.keys())
147+
# ]
148+
149+
# if len(kwargs) > 0:
150+
# warnings.warn(
151+
# f"The following keyword arguments are not supported by '{self.name}' device: {list(kwargs.keys())}",
152+
# UserWarning,
153+
# )
154+
128155
def _handle_kwargs(self, **kwargs):
129-
### Extract Estimator/Sampler-specific options
130-
self._sampler_options = {
156+
### Extract runner-specific arguments
157+
self._run_options = {
131158
k: v
132159
for k, v in kwargs.items()
133-
if k in (field.name for field in fields(SamplerOptions))
160+
if k in signature(self._platform.run).parameters.keys()
134161
}
135-
self._estimator_options = {
136-
k: v
137-
for k, v in kwargs.items()
138-
if k in (field.name for field in fields(EstimatorOptions))
139-
}
140-
[
141-
kwargs.pop(k)
142-
for k in (self._sampler_options.keys() | self._estimator_options.keys())
143-
]
162+
[kwargs.pop(k) for k in self._run_options.keys()]
163+
self._run_options.update(
164+
{
165+
"session_name": self._session_options.get("name"),
166+
"session_max_duration": self._session_options.get("max_duration"),
167+
"session_max_idle_duration": self._session_options.get(
168+
"max_idle_duration"
169+
),
170+
}
171+
)
144172

145173
if len(kwargs) > 0:
146174
warnings.warn(
147175
f"The following keyword arguments are not supported by '{self.name}' device: {list(kwargs.keys())}",
148176
UserWarning,
149177
)
150178

151-
def preprocess(
152-
self,
153-
execution_config: ExecutionConfig | None = None,
154-
) -> tuple[TransformProgram, ExecutionConfig]:
155-
transform_program, config = super().preprocess(execution_config)
156-
transform_program.add_transform(split_execution_types)
157-
return transform_program, config
158-
159-
def execute(
160-
self,
161-
circuits: QuantumScriptOrBatch,
162-
execution_config: ExecutionConfig | None = None,
163-
) -> List:
164-
165-
if not self._session_id:
166-
raise RuntimeError(
167-
"No active session. Please instanciate the device using a context manager, or call start() first. You can also attach to an existing deduplication_id."
168-
)
169-
170-
if isinstance(circuits, QuantumScript):
171-
circuits = [circuits]
172-
173-
estimator_indices = []
174-
estimator_circuits = []
175-
sampler_circuits = []
176-
177-
for i, circuit in enumerate(circuits):
178-
if circuit.shots and len(circuit.shots.shot_vector) > 1:
179-
raise ValueError(
180-
f"Setting shot vector {circuit.shots.shot_vector} is not supported for {self.name}."
181-
"Please use a single integer instead when specifying the number of shots."
182-
)
183-
184-
if isinstance(
185-
circuit.measurements[0], (ExpectationMP, VarianceMP)
186-
) and getattr(circuit.measurements[0].obs, "pauli_rep", None):
187-
estimator_indices.append(i)
188-
estimator_circuits.append(circuit)
189-
else:
190-
sampler_circuits.append(circuit)
191-
192-
if sampler_circuits:
193-
sampler_results = self._run_sampler(sampler_circuits)
194-
if estimator_circuits:
195-
estimator_results = self._run_estimator(estimator_circuits)
196-
results = []
197-
s, e = 0, 0
198-
199-
for i, circuit in enumerate(circuits):
200-
if i in estimator_indices:
201-
results.append(estimator_results[e])
202-
e += 1
203-
else:
204-
results.append(sampler_results[s])
205-
s += 1
206-
207-
return results
179+
# def preprocess(
180+
# self,
181+
# execution_config: ExecutionConfig | None = None,
182+
# ) -> tuple[TransformProgram, ExecutionConfig]:
183+
# transform_program, config = super().preprocess(execution_config)
184+
# transform_program.add_transform(split_execution_types)
185+
# return transform_program, config
186+
187+
# def execute(
188+
# self,
189+
# circuits: QuantumScriptOrBatch,
190+
# execution_config: ExecutionConfig | None = None,
191+
# ) -> List:
192+
193+
# if not self._session_id:
194+
# raise RuntimeError(
195+
# "No active session. Please instanciate the device using a context manager, or call start() first. You can also attach to an existing deduplication_id."
196+
# )
197+
198+
# if isinstance(circuits, QuantumScript):
199+
# circuits = [circuits]
200+
201+
# estimator_indices = []
202+
# estimator_circuits = []
203+
# sampler_circuits = []
204+
205+
# for i, circuit in enumerate(circuits):
206+
# if circuit.shots and len(circuit.shots.shot_vector) > 1:
207+
# raise ValueError(
208+
# f"Setting shot vector {circuit.shots.shot_vector} is not supported for {self.name}."
209+
# "Please use a single integer instead when specifying the number of shots."
210+
# )
211+
212+
# if isinstance(
213+
# circuit.measurements[0], (ExpectationMP, VarianceMP)
214+
# ) and getattr(circuit.measurements[0].obs, "pauli_rep", None):
215+
# estimator_indices.append(i)
216+
# estimator_circuits.append(circuit)
217+
# else:
218+
# sampler_circuits.append(circuit)
219+
220+
# if sampler_circuits:
221+
# sampler_results = self._run_sampler(sampler_circuits)
222+
# if estimator_circuits:
223+
# estimator_results = self._run_estimator(estimator_circuits)
224+
# results = []
225+
# s, e = 0, 0
226+
227+
# for i, circuit in enumerate(circuits):
228+
# if i in estimator_indices:
229+
# results.append(estimator_results[e])
230+
# e += 1
231+
# else:
232+
# results.append(sampler_results[s])
233+
# s += 1
234+
235+
# return results
208236

209237
def _run_estimator(self, circuits: Iterable[QuantumScript]) -> List[Tuple]:
210238
qcircs = [

pennylane_scaleway/scw_device.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,13 @@ def execute(
182182
if circuits[0].shots and circuits[0].shots.total_shots:
183183
shots = circuits[0].shots.total_shots
184184

185+
if shots is None:
186+
raise ValueError(
187+
"Number of shots must be specified, "
188+
"either through a default value when instanciating the device, "
189+
"or preferably using the set_shots() decorator on the circuit."
190+
)
191+
185192
@retry(stop=stop_after_attempt(3) | stop_after_delay(3 * 60), reraise=True)
186193
def run() -> Union[Result, List[Result]]:
187194
return self._platform.run(

0 commit comments

Comments
 (0)