Skip to content

Commit aec2735

Browse files
Remove Session from Executor (#321)
* fix input arguments in Session creation * black * removed service * removed service from the executor --------- Co-authored-by: Moritz <44642314+MoritzWillmann@users.noreply.github.com>
1 parent 071c811 commit aec2735

1 file changed

Lines changed: 34 additions & 87 deletions

File tree

src/squlearn/util/executor.py

Lines changed: 34 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,14 @@ class Executor:
215215
* A Qiskit backend, to run the jobs on IBM Quantum systems or simulators
216216
* A list of Qiskit backends for automatic backend selection later on
217217
* A QiskitRuntimeService, to run the jobs on the Qiskit Runtime service.
218-
In this case the backend has to be provided separately via ``backend=``
218+
In this case the backends are automatically selected based on the
219+
available backends of the service, similar to providing a list of backends.
219220
* A Session, to run the jobs on the Qiskit Runtime service
220221
* A Estimator primitive (either simulator or Qiskit Runtime primitive - V1 or V2)
221222
* A Sampler primitive (either simulator or Qiskit Runtime primitive - V1 or V2)
222223
223224
Default is the initialization with PennyLane's
224225
:class:`DefaultQubit <pennylane.devices.default_qubit.DefaultQubit>` simulator.
225-
backend (Union[Backend, str, None]): The backend that is used for the execution.
226-
Only mandatory if a service is provided.
227226
options_estimator (Union[Any]): The options for the created estimator primitives.
228227
options_sampler (Union[Any]): The options for the created sampler primitives.
229228
log_file (str): The name of the log file, if empty, no log file is created.
@@ -260,7 +259,6 @@ class Executor:
260259
is_statevector (Bool): Returns true if the backend is a statevector simulator.
261260
qpu_parallelization (Bool): Returns true if QPU parallelization is used.
262261
session (Session): The session that is used in the Executor.
263-
service (QiskitRuntimeService): The service that is used in the Executor.
264262
quantum_framework (str): The framework used in the Executor (``"qiskit"`` or
265263
``"pennylane"``).
266264
IBMQuantum (bool): Whether the backend is an IBM Quantum backend.
@@ -413,7 +411,6 @@ def __init__(
413411
BaseSamplerV2,
414412
PennylaneDevice,
415413
] = "pennylane",
416-
backend: Union[Backend, str, None] = None,
417414
options_estimator: Union[Any, None] = None,
418415
options_sampler: Union[Any, None] = None,
419416
log_file: str = "",
@@ -430,7 +427,6 @@ def __init__(
430427
# Default values for internal variables
431428
self._backend = None
432429
self._session = None
433-
self._service = None
434430
self._estimator = None
435431
self._sampler = None
436432
self._execution_origin = ""
@@ -552,8 +548,6 @@ def __init__(
552548

553549
elif isinstance(execution, Backend):
554550
# Execution is a backend class
555-
if hasattr(execution, "service"):
556-
self._service = execution.service
557551
self._backend = execution
558552
self._execution_origin = "Backend"
559553
if shots is None:
@@ -567,25 +561,11 @@ def __init__(
567561
self._backend = None
568562
self._backend_list = execution
569563
self._execution_origin = "BackendList"
570-
# Execution is a backend class
571-
if hasattr(execution[0], "service"):
572-
self._service = execution[0].service
573564
else:
574565
raise ValueError("Only list of backends are supported!")
575566
elif isinstance(execution, QiskitRuntimeService):
576-
self._service = execution
577-
if isinstance(backend, str):
578-
self._backend = self._service.backend(backend)
579-
elif isinstance(backend, Backend):
580-
self._backend = backend
581-
elif isinstance(backend, list):
582-
self._backend_list = backend
583-
self._backend = None
584-
elif backend is None:
585-
self._backend = None
586-
self._backend_list = self._service.backends()
587-
else:
588-
raise ValueError("Unknown backend type: " + backend)
567+
self._backend = None
568+
self._backend_list = execution.backends()
589569
if shots is None and self._backend is not None:
590570
shots = self._backend.options.shots
591571
if self.is_statevector:
@@ -594,8 +574,7 @@ def __init__(
594574
elif isinstance(execution, Session):
595575
# Execution is a active? session
596576
self._session = execution
597-
self._service = self._session.service
598-
self._backend = self._session.service.backend(self._session.backend())
577+
self._backend = self._session.service.get_backend(self._session.backend())
599578
self._execution_origin = "Session"
600579
if shots is None:
601580
shots = self._backend.options.shots
@@ -619,7 +598,6 @@ def __init__(
619598
# Real Backend
620599
elif isinstance(self._estimator, RuntimeEstimatorV1):
621600
self._session = self._estimator._session
622-
self._service = self._estimator._service
623601
self._backend = self._estimator._backend
624602
# TODO: check if this is duplicate
625603
if not shots:
@@ -649,7 +627,6 @@ def __init__(
649627
shots = shots_sampler
650628
elif isinstance(self._sampler, RuntimeSamplerV1):
651629
self._session = self._sampler._session
652-
self._service = self._sampler._service
653630
self._backend = self._sampler._backend
654631
# TODO: check if this is duplicate
655632
if not shots:
@@ -683,7 +660,6 @@ def __init__(
683660
self._session = self._estimator._session
684661
elif hasattr(self._estimator, "_mode"):
685662
self._session = self._estimator._mode
686-
self._service = self._estimator._service
687663
self._backend = self._estimator._backend
688664
if shots is None:
689665
if self._estimator.options.default_shots:
@@ -716,7 +692,6 @@ def __init__(
716692
self._session = self._sampler._session
717693
elif hasattr(self._sampler, "_mode"):
718694
self._session = self._sampler._mode
719-
self._service = self._sampler._service
720695
self._backend = self._sampler._backend
721696
if shots is None:
722697
if self._sampler.options.default_shots:
@@ -808,8 +783,6 @@ def __init__(
808783
self._logger.info(
809784
f"Executor initialized with backend list: {{}}".format(self._backend_list)
810785
)
811-
if self._service is not None:
812-
self._logger.info(f"Executor initialized with service: {{}}".format(self._service))
813786
if self._session is not None:
814787
self._logger.info(
815788
f"Executor initialized with session: {{}}".format(self._session.session_id)
@@ -1052,11 +1025,6 @@ def session(self) -> Session:
10521025
"""Returns the session that is used in the executor."""
10531026
return self._session
10541027

1055-
@property
1056-
def service(self) -> QiskitRuntimeService:
1057-
"""Returns the service that is used in the executor."""
1058-
return self._service
1059-
10601028
def _estimator_v1(self) -> BaseEstimatorV1:
10611029
"""Returns the Estimator V1 primitive that is used for the execution.
10621030
@@ -1089,25 +1057,22 @@ def _estimator_v1(self) -> BaseEstimatorV1:
10891057
self._estimator = RuntimeEstimatorV1(
10901058
session=self._session, options=self._options_estimator
10911059
)
1092-
elif self._service is not None:
1093-
# No session but service -> create a new session
1060+
else:
1061+
# No session -> create a new session
10941062
self.create_session()
10951063
self._estimator = RuntimeEstimatorV1(
10961064
session=self._session, options=self._options_estimator
10971065
)
1098-
else:
1099-
raise RuntimeError(
1100-
"Missing Qiskit Runtime service for Estimator initialization!"
1101-
)
1066+
11021067
else:
11031068
if self.is_statevector:
1104-
# No session, no service, but state_vector simulator -> Estimator
1069+
# No session, but state_vector simulator -> Estimator
11051070
self._estimator = PrimitiveEstimatorV1(options=self._options_estimator)
11061071
self._estimator.set_options(shots=self._shots)
11071072
elif self._backend is None:
11081073
raise RuntimeError("Backend missing for Estimator initialization!")
11091074
else:
1110-
# No session, no service and no state_vector simulator -> BackendEstimator
1075+
# No session and no state_vector simulator -> BackendEstimator
11111076
self._estimator = BackendEstimatorV1(
11121077
backend=self._backend, options=self._options_estimator
11131078
)
@@ -1190,8 +1155,8 @@ def _estimator_v2(self) -> BaseEstimatorV2:
11901155
self._estimator = RuntimeEstimatorV2(
11911156
mode=self._session, options=self._options_estimator
11921157
)
1193-
elif self._service is not None:
1194-
# No session but service -> create a new session
1158+
else:
1159+
# No session -> create a new session
11951160
self.create_session()
11961161
if QISKIT_RUNTIME_SMALLER_0_23:
11971162
self._estimator = RuntimeEstimatorV2(
@@ -1201,10 +1166,6 @@ def _estimator_v2(self) -> BaseEstimatorV2:
12011166
self._estimator = RuntimeEstimatorV2(
12021167
mode=self._session, options=self._options_estimator
12031168
)
1204-
else:
1205-
raise RuntimeError(
1206-
"Missing Qiskit Runtime service for Estimator initialization!"
1207-
)
12081169
else:
12091170
if "fake" in str(self._backend):
12101171
if shots:
@@ -1221,7 +1182,7 @@ def _estimator_v2(self) -> BaseEstimatorV2:
12211182
mode=self._backend, options=self._options_estimator
12221183
)
12231184
elif self.is_statevector:
1224-
# No session, no service, but state_vector simulator -> Estimator
1185+
# No session, but state_vector simulator -> Estimator
12251186
self._estimator = StatevectorEstimator(
12261187
default_precision=1 / shots**0.5 if shots else 0.0
12271188
)
@@ -1233,7 +1194,7 @@ def _estimator_v2(self) -> BaseEstimatorV2:
12331194
self._options_estimator = {"default_precision": 1 / shots**0.5}
12341195
else:
12351196
self._options_estimator["default_precision"] = 1 / shots**0.5
1236-
# No session, no service and no state_vector simulator -> BackendEstimator
1197+
# No session and no state_vector simulator -> BackendEstimator
12371198
self._estimator = BackendEstimatorV2(
12381199
backend=self._backend, options=self._options_estimator
12391200
)
@@ -1332,26 +1293,22 @@ def _sampler_v1(self) -> BaseSamplerV1:
13321293
session=self._session, options=self._options_sampler
13331294
)
13341295

1335-
elif self._service is not None:
1336-
# No session but service -> create a new session
1296+
else:
1297+
# No session -> create a new session
13371298
self.create_session()
13381299
self._sampler = RuntimeSamplerV1(
13391300
session=self._session,
13401301
options=self._options_sampler,
13411302
)
1342-
else:
1343-
raise RuntimeError(
1344-
"Missing Qiskit Runtime service for Sampler initialization!"
1345-
)
13461303
else:
13471304
if self.is_statevector:
1348-
# No session, no service, but state_vector simulator -> Sampler
1305+
# No session, but state_vector simulator -> Sampler
13491306
self._sampler = PrimitiveSamplerV1(options=self._options_sampler)
13501307
self._sampler.set_options(shots=self._shots)
13511308
elif self._backend is None:
13521309
raise RuntimeError("Backend missing for Sampler initialization!")
13531310
else:
1354-
# No session, no service and no state_vector simulator -> BackendSampler
1311+
# No session and no state_vector simulator -> BackendSampler
13551312
self._sampler = BackendSamplerV1(
13561313
backend=self._backend, options=self._options_sampler
13571314
)
@@ -1430,8 +1387,8 @@ def _sampler_v2(self) -> BaseSamplerV2:
14301387
mode=self._session, options=self._options_sampler
14311388
)
14321389

1433-
elif self._service is not None:
1434-
# No session but service -> create a new session
1390+
else:
1391+
# No session -> create a new session
14351392
self.create_session()
14361393
if QISKIT_RUNTIME_SMALLER_0_23:
14371394
self._sampler = RuntimeSamplerV2(
@@ -1443,11 +1400,6 @@ def _sampler_v2(self) -> BaseSamplerV2:
14431400
mode=self._session,
14441401
options=self._options_sampler,
14451402
)
1446-
1447-
else:
1448-
raise RuntimeError(
1449-
"Missing Qiskit Runtime service for Sampler initialization!"
1450-
)
14511403
else:
14521404
if "fake" in str(self._backend).lower():
14531405
if QISKIT_RUNTIME_SMALLER_0_23:
@@ -1459,7 +1411,7 @@ def _sampler_v2(self) -> BaseSamplerV2:
14591411
mode=self._backend, options=self._options_sampler
14601412
)
14611413
elif self.is_statevector:
1462-
# No session, no service, but state_vector simulator -> Sampler
1414+
# No session, but state_vector simulator -> Sampler
14631415
if shots:
14641416
self._sampler = StatevectorSampler(default_shots=shots)
14651417
else:
@@ -1468,7 +1420,7 @@ def _sampler_v2(self) -> BaseSamplerV2:
14681420
elif self._backend is None:
14691421
raise RuntimeError("Backend missing for Sampler initialization!")
14701422
else:
1471-
# No session, no service and no state_vector simulator -> BackendSampler
1423+
# No session and no state_vector simulator -> BackendSampler
14721424
self._sampler = BackendSamplerV2(
14731425
backend=self._backend, options=self._options_sampler
14741426
)
@@ -2348,16 +2300,11 @@ def create_session(self):
23482300
if not self.IBMQuantum:
23492301
raise RuntimeError("Sessions can only be created for IBM Quantum devices!")
23502302

2351-
if self._service is not None:
2352-
if self._backend is not None:
2353-
self._session = Session(
2354-
self._service, backend=self._backend, max_time=self._max_session_time
2355-
)
2356-
else:
2357-
raise RuntimeError("Session can not started because of missing backend!")
2358-
self._logger.info("Executor created a new session.")
2303+
if self._backend is not None:
2304+
self._session = Session(backend=self._backend, max_time=self._max_session_time)
23592305
else:
2360-
raise RuntimeError("Session can not started because of missing service!")
2306+
raise RuntimeError("Session can not started because of missing backend!")
2307+
self._logger.info("Executor created a new session.")
23612308

23622309
def close_session(self):
23632310
"""Closes the current session, is called automatically."""
@@ -2621,13 +2568,13 @@ def is_statevector(self) -> bool:
26212568

26222569
class ExecutorEstimatorV2(BaseEstimatorV2):
26232570
"""
2624-
Special Estimator V2 Primitive that uses the Executor service.
2571+
Special Estimator V2 Primitive that uses the Executor.
26252572
26262573
Usefull for automatic restarting sessions and caching results.
26272574
The object is created by the Executor method get_estimator()
26282575
26292576
Args:
2630-
executor (Executor): The executor service to use
2577+
executor (Executor): The executor to use
26312578
options: Options for the estimator
26322579
"""
26332580

@@ -2668,13 +2615,13 @@ def options(self):
26682615

26692616
class ExecutorSamplerV2(BaseSamplerV2):
26702617
"""
2671-
Special Sampler V2 Primitive that uses the Executor service.
2618+
Special Sampler V2 Primitive that uses the Executor.
26722619
26732620
Usefull for automatic restarting sessions and caching results.
26742621
The object is created by the Executor method get_sampler()
26752622
26762623
Args:
2677-
executor (Executor): The executor service to use
2624+
executor (Executor): The executor to use
26782625
"""
26792626

26802627
def __init__(self, executor: Executor):
@@ -2712,13 +2659,13 @@ def options(self):
27122659

27132660
class ExecutorEstimatorV1(BaseEstimatorV1):
27142661
"""
2715-
Special Estimator V1 Primitive that uses the Executor service.
2662+
Special Estimator V1 Primitive that uses the Executor.
27162663
27172664
Usefull for automatic restarting sessions and caching results.
27182665
The object is created by the Executor method get_estimator()
27192666
27202667
Args:
2721-
executor (Executor): The executor service to use
2668+
executor (Executor): The executor to use
27222669
options: Options for the estimator
27232670
27242671
"""
@@ -2837,13 +2784,13 @@ def set_options(self, **fields):
28372784

28382785
class ExecutorSamplerV1(BaseSamplerV1):
28392786
"""
2840-
Special Sampler V1 Primitive that uses the Executor service.
2787+
Special Sampler V1 Primitive that uses the Executor.
28412788
28422789
Useful for automatic restarting sessions and caching the results.
28432790
The object is created by the executor method get_sampler()
28442791
28452792
Args:
2846-
executor (Executor): The executor service to use
2793+
executor (Executor): The executor to use
28472794
options: Options for the sampler
28482795
28492796
"""

0 commit comments

Comments
 (0)