Skip to content

Commit

Permalink
Task support in v2 primitives (#1224)
Browse files Browse the repository at this point in the history
* Add experimental options (#1067)

* add options

* fix mypy

* rename meas err mit

* Add additional resilience options

* Add additional execution options for twirling

* A twirling strategy option and validation

* handle default resilience options

* add _experimental

* Update default resilience options (#1062)

* remove default resilience options

* add reno

* add logic to override default

* add test

* purge None values from options

(cherry picked from commit 76603f2)

* add finalize options

* add tests

* Update qiskit_ibm_runtime/options/resilience_options.py

* add validation

* lint

* lint again

* lint again

* Allow None values for specific options to be passed through

* Fix parameter validation, allow computational basis

* black

* Fix ZneExtrapolatorType validation

* lint

* lint again

* fix mypy

* Fix ZNE extrapolator default option

* fix level options

* black

* use _isreal

* Disable gate twirling for default lvl 1 opts

* Support for legacy options

---------

Co-authored-by: Christopher J. Wood <[email protected]>
Co-authored-by: Kevin Tian <[email protected]>
Co-authored-by: mberna <[email protected]>
Co-authored-by: Mariana C Bernagozzi <[email protected]>

* fix merge issues

* add pydantic

* black

* lint

* Fast forward experimental to latest main (#1178)

* Remove min execution time check (#1065)

* Remove min execution time check

* update unit test

* remove integration test

* Update `max_execution_time` docstrings (#1059)

* Update max_execution_time docstrings

* add commas

* Update qiskit_ibm_runtime/options/options.py

Co-authored-by: Rebecca Dimock <[email protected]>

* Update qiskit_ibm_runtime/options/options.py

Co-authored-by: Rebecca Dimock <[email protected]>

* Update qiskit_ibm_runtime/runtime_options.py

Co-authored-by: Rebecca Dimock <[email protected]>

* Update releasenotes/notes/max-execution-time-definition-196cb6297693c0f2.yaml

Co-authored-by: Rebecca Dimock <[email protected]>

---------

Co-authored-by: Rebecca Dimock <[email protected]>

* Removed remaining code related to Schedules (#1068)

Co-authored-by: Kevin Tian <[email protected]>

* Enable datetime parameter for backend properties (#1070)

* enable datetime param for backend properties

* add test & reno

* improve test

* Update default resilience options (#1062)

* remove default resilience options

* add reno

* add logic to override default

* add test

* purge None values from options

* fix test (#1074)

* Prepare release 0.12.1 (#1075)

* Update main branch veresion 0.12.2 (#1076)

* use ibmq_qasm_simulator (#1078)

* Add reason code to error message (#1072)

* Add reason code to error message

* add reno

* Remove importing PauliSumOp, which is deprecated. (#1079)

---------

Co-authored-by: Jake Lishman <[email protected]>
Co-authored-by: Kevin Tian <[email protected]>

* Adjusts default value for optimization_level (#1082)

* add instance info (#1083)

* add instance info

* Add cloud note

* Update README.md

Co-authored-by: Kevin Tian <[email protected]>

---------

Co-authored-by: Kevin Tian <[email protected]>

* Fix links to options in README.md (#1084)

* Remove auth parameter (#1077)

* Removed auth parameter

* Removed calls to migrate()

* black and lint

---------

Co-authored-by: Kevin Tian <[email protected]>

* Remove opflow and algorithms from serialization tests (#1085)

* Remove opflow from tests

* Re-add test for PauliSumOp

* Fix lint

* Fix black

---------

Co-authored-by: Kevin Tian <[email protected]>

* RuntimeJobTimeoutError should inherit from JobTimeoutError (#1090)

* RuntimeJobTimeoutError inherits from JobTimeoutError

* black

---------

Co-authored-by: Kevin Tian <[email protected]>

* Allow user to define a default account as an environment variable (#1018)

* Allow user to define a default account as an environment variable

* Fixed test

* Fixed mistaken paste

* Cleaned up test

* Moved test to TestAccountManager

* Added ability to define default channel in save_account

* Cleaned up code, fixed bugs

* Changed name of parameter

* Added test. Cleaned up code surrounding preferences of channel selection

* black and lint

* Fixed bug when json file was empty

* Code cleanup and documentation

* Documentation

* Removed channel from condition, because unnecessary

* changed default_channel to default_account

* Changed saving and getting default channel to default account

* black

* Documentation

* Release notes

* Reverted diff that was unnecessary

---------

Co-authored-by: Kevin Tian <[email protected]>

* Skip test_job_logs (#1094)

* Update session max_time docstring (#1089)

* Update session max_time docstring

* Update qiskit_ibm_runtime/session.py

Co-authored-by: Rebecca Dimock <[email protected]>

---------

Co-authored-by: Rebecca Dimock <[email protected]>

* Fix unit tests against qiskit/main (#1099)

* Add measurements to sampler

* Remove observables from sampler run

---------

Co-authored-by: Kevin Tian <[email protected]>

* fix iqp link (#1096)

Co-authored-by: Kevin Tian <[email protected]>

* Only return channel strategy supported backends  (#1095)

* Q-CTRL Backend filters

* add reno

* fix unit tests

* Attempt to fix terra unit tests (#1102)

* Attempt to fix terra unit tests

* test on my fork

* revert coder_qc change

* Making account code more generic  (#1060)

* Making account code more generic by defining subclasses for channel types

* Removed channel parameter from _assert_valid_instance

* mypy, lint and black

* Changed order of decorators

* Code cleanup

* Documentation fixes

* black

---------

Co-authored-by: Kevin Tian <[email protected]>

* Remove old deprecations (#1106)

* removing old deprecations

* update unit tests

* Open plan updates (#1105)

* Initial edits

* edit

* Update docs/faqs/max_execution_time.rst

* Update docs/faqs/max_execution_time.rst

* Update docs/faqs/max_execution_time.rst

* Update docs/faqs/max_execution_time.rst

* Update docs/faqs/max_execution_time.rst

* Update docs/faqs/max_execution_time.rst

Co-authored-by: Jessie Yu <[email protected]>

* Jessie comments

* Update docs/faqs/max_execution_time.rst

Co-authored-by: Jessie Yu <[email protected]>

* Update docs/faqs/max_execution_time.rst

Co-authored-by: Jessie Yu <[email protected]>

* Update docs/sessions.rst

* Update docs/faqs/max_execution_time.rst

---------

Co-authored-by: Jessie Yu <[email protected]>

* New method to create a new Session object with a given id (#1101)

* Added the Session.from_id method

* release notes

* Added integration test

---------

Co-authored-by: Kevin Tian <[email protected]>

* fix test_session_from_id (#1110)

* Warn users if job submitted will exceed quota (#1100)

* Warn users if job will exceed quota

* update reno

* update reno again

* Removed support for backend as session parameter (#1091)

Co-authored-by: Kevin Tian <[email protected]>

* Fix minor todos (#1112)

* Change qpu complex wording (#1109)

* Don't use QPU complex

* don't use the word 'limit'

* Update docs/faqs/max_execution_time.rst

* Update qiskit_ibm_runtime/options/options.py

* Update qiskit_ibm_runtime/runtime_job.py

* Update releasenotes/notes/0.11/job-cost-estimation-d0ba83dbc95c3f67.yaml

* Clarify usage

* reclarify reset time

* rogue comma

* fix whitespace & formatting

* job -> system execution time

---------

Co-authored-by: Kevin Tian <[email protected]>

* Add IBM Cloud channel (#1113)

* Changes for #1806

* Update docs/faqs/max_execution_time.rst

Co-authored-by: Jessie Yu <[email protected]>

---------

Co-authored-by: Kevin Tian <[email protected]>
Co-authored-by: Jessie Yu <[email protected]>
Co-authored-by: Kevin Tian <[email protected]>

* Prepare release 0.12.2 (#1115)

* Update main branch 0.13.0 (#1116)

* remove error message test (#1125)

* Exceptions should inherit from Terra where suitable (#1120)

* Changed RuntimeJobFailureError to inherit from JobError

* Changed error type

---------

Co-authored-by: Kevin Tian <[email protected]>

* update docstring & remove max_time (#1137)

* Expose new session details  (#1119)

* add session details method

* add reno

* support iqp urls

* update details mehotd, add status()

* update status() to use enum

* revert previous change, wait for impl details

* update fields returned

* update status method

* update docstring & reno

* update docstrings for both methods

* fix docs build

* address comments

* fix docs build

* fix typo

* docs build again

* fix indent

* fix indent again

* fix indent 3rd time

* Support only LocalFoldingAmplifier as noise_amplifier option (#1093)

* Removed support for all noise_amplifier options other than LocalFoldingAmplifier. Removed deprecation warning.

* Removed tests that covered deprecation. Updated documentation

---------

Co-authored-by: Kevin Tian <[email protected]>

* Fix target_history date bug  (#1143)

* fix target_history datetime bug

* add reno

* add test

* Fixed bug when defining shots as int64 (#1151)

* Log instance on initialization and when running a job (#1150)

* log instances

* add _default_instance & fix lint

* add test

* change var name to current_instance

* Move methods into class pages for docs (#1144)

* Fix link to `Close a session` (#1152)

[1] links to [2] but doesn't go directly to the target section.

[1] https://qiskit.org/ecosystem/ibm-runtime/sessions.html#what-happens-when-a-session-ends
[2] https://qiskit.org/ecosystem/ibm-runtime/how_to/run_session.html#close-a-session

Co-authored-by: Kevin Tian <[email protected]>

* logging instance test is IQP channel only (#1154)

* Update deploy yml (#1148)

* Allow users to indicate they are done submitting jobs to a session (#1139)

* copy changes over

* clean up branch again

* address comments, update docstrings

* catch appropriate error code

* update status code to 404

* Update qiskit_ibm_runtime/session.py

Co-authored-by: Jessie Yu <[email protected]>

* set self._active & remove runtime_session

* Update releasenotes/notes/session-accepting-jobs-d7ef6b60c0f5527b.yaml

Co-authored-by: Jessie Yu <[email protected]>

---------

Co-authored-by: Jessie Yu <[email protected]>

* Prepare release 0.13 (#1157)

* Update main branch 0.13.1 (#1158)

* Update Sphinx theme (#1156)

Co-authored-by: Kevin Tian <[email protected]>

* Added IBM Quantum logo (#1164)

* sessions changes (#1169)

* sessions changes

* add more ticks

* fix link

* fix links

* Update docs/sessions.rst

Co-authored-by: abbycross <[email protected]>

* Update docs/sessions.rst

Co-authored-by: abbycross <[email protected]>

---------

Co-authored-by: abbycross <[email protected]>

* Disallow unsupported options (#1108)

* Disallow unsupported options

* Moved checking of unsupported options to 'flexible' decorator

* Modified the test to give TypeError where needed

* Removed empty newline

* Moved tests from test_ibm_primitives to test_options, because they don't require a primitive

* typo

* Release note

* black and lint

* black again

* Fixed test failing in CI

* Removed _flexible decorator. Moved _post_init into Options class

* lint

* lint

* Fixed bug

* lint

---------

Co-authored-by: Kevin Tian <[email protected]>

* fix merge issues

* black

* lint

---------

Co-authored-by: Kevin Tian <[email protected]>
Co-authored-by: Rebecca Dimock <[email protected]>
Co-authored-by: merav-aharoni <[email protected]>
Co-authored-by: Luciano Bello <[email protected]>
Co-authored-by: Jake Lishman <[email protected]>
Co-authored-by: Esteban Ginez <[email protected]>
Co-authored-by: Kevin Tian <[email protected]>
Co-authored-by: mberna <[email protected]>
Co-authored-by: Elena Peña Tapia <[email protected]>
Co-authored-by: Arnau Casau <[email protected]>
Co-authored-by: Matt Riedemann <[email protected]>
Co-authored-by: abbycross <[email protected]>

* v2 options

* estimator options

* update test

* lint

* fix merge issues

* black

* fix noise model type

* lint again

* fix header

* fix mypy

* use v2 as default

* cleanup terra options

* black

* options need not be callable

* fix doc

* fix tests

* fix version

* add sampler option

* lint

* freeze constants

* freeze constants

* remove is_simulator

* make image work

* fix merge issues

* fix tests

* use base classes

* lint

* clean up unused code

* fix tests

* lint

* add seed_estimator

* resolve merge issues

* update docstring

* lint

* 3.8 mapping

* v2 result

* estimator result version

* line

* 3.8 support

* also 3.8 support

* fix tests with no inputs

* fix version passing

* fix decoder param

* disable samplerv2

* disable samplerv2 tests

* lint

---------

Co-authored-by: Christopher J. Wood <[email protected]>
Co-authored-by: Kevin Tian <[email protected]>
Co-authored-by: mberna <[email protected]>
Co-authored-by: Mariana C Bernagozzi <[email protected]>
Co-authored-by: Rebecca Dimock <[email protected]>
Co-authored-by: merav-aharoni <[email protected]>
Co-authored-by: Luciano Bello <[email protected]>
Co-authored-by: Jake Lishman <[email protected]>
Co-authored-by: Esteban Ginez <[email protected]>
Co-authored-by: Kevin Tian <[email protected]>
Co-authored-by: Elena Peña Tapia <[email protected]>
Co-authored-by: Arnau Casau <[email protected]>
Co-authored-by: Matt Riedemann <[email protected]>
Co-authored-by: abbycross <[email protected]>
  • Loading branch information
15 people authored Nov 29, 2023
1 parent b73fdac commit 73b3385
Show file tree
Hide file tree
Showing 38 changed files with 1,874 additions and 963 deletions.
2 changes: 1 addition & 1 deletion qiskit_ibm_runtime/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,4 +204,4 @@ def result_callback(job_id, result):
QISKIT_IBM_RUNTIME_LOG_FILE = "QISKIT_IBM_RUNTIME_LOG_FILE"
"""The environment variable name that is used to set the file for the IBM Quantum logger."""

warnings.warn("You are using the experimental branch. Stability is not guaranteed.")
warnings.warn("You are using the experimental-0.2 branch. Stability is not guaranteed.")
70 changes: 33 additions & 37 deletions qiskit_ibm_runtime/base_primitive.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,18 @@

from qiskit_ibm_provider.session import get_cm_session as get_cm_provider_session

from .options import BaseOptions, Options
from .options import Options
from .options.options import BaseOptions, OptionsV2
from .options.utils import merge_options, set_default_error_levels
from .runtime_job import RuntimeJob
from .ibm_backend import IBMBackend
from .utils.default_session import get_cm_session
from .constants import DEFAULT_DECODERS
from .qiskit_runtime_service import QiskitRuntimeService

# TODO: remove when we have real v2 base estimator
from .qiskit.primitives import EstimatorTask, SamplerTask

# pylint: disable=unused-import,cyclic-import
from .session import Session

Expand All @@ -41,7 +45,7 @@
class BasePrimitiveV2(ABC):
"""Base class for Qiskit Runtime primitives."""

_OPTIONS_CLASS: type[BaseOptions] = Options
_options_class: Optional[type[BaseOptions]] = OptionsV2
version = 2

def __init__(
Expand Down Expand Up @@ -75,16 +79,7 @@ def __init__(
self._service: QiskitRuntimeService = None
self._backend: Optional[IBMBackend] = None

opt_cls = self._OPTIONS_CLASS
if options is None:
self.options = opt_cls()
elif isinstance(options, opt_cls):
self.options = replace(options)
elif isinstance(options, dict):
default_options = opt_cls()
self.options = opt_cls(**merge_options(default_options, options))
else:
raise ValueError(f"Invalid 'options' type. It can only be a dictionary of {opt_cls}")
self._set_options(options)

if isinstance(session, Session):
self._session = session
Expand Down Expand Up @@ -123,36 +118,33 @@ def __init__(
"A backend or session must be specified when not using ibm_cloud channel."
)

def _run_primitive(self, primitive_inputs: Dict, user_kwargs: Dict) -> RuntimeJob:
def _run(self, tasks: Union[list[EstimatorTask], list[SamplerTask]]) -> RuntimeJob:
"""Run the primitive.
Args:
primitive_inputs: Inputs to pass to the primitive.
user_kwargs: Individual options to overwrite the default primitive options.
tasks: Inputs tasks to pass to the primitive.
Returns:
Submitted job.
"""
logger.debug("Merging current options %s with %s", self.options, user_kwargs)
combined = merge_options(self.options, user_kwargs)
primitive_inputs = {"tasks": tasks}
options_dict = asdict(self.options)
self._validate_options(options_dict)
primitive_inputs.update(self._options_class._get_program_inputs(options_dict))
runtime_options = self._options_class._get_runtime_options(options_dict)

self._validate_options(combined)

primitive_inputs.update(self._OPTIONS_CLASS._get_program_inputs(combined))
runtime_options = self._OPTIONS_CLASS._get_runtime_options(combined)
if self._backend and options_dict["transpilation"]["skip_transpilation"]:
for task in tasks:
self._backend.check_faulty(task.circuit)

if self._backend and combined["transpilation"]["skip_transpilation"]:
for circ in primitive_inputs["circuits"]:
self._backend.check_faulty(circ)

logger.info("Submitting job using options %s", combined)
logger.info("Submitting job using options %s", options_dict)

if self._session:
return self._session.run(
program_id=self._program_id(),
inputs=primitive_inputs,
options=runtime_options,
callback=combined.get("environment", {}).get("callback", None),
callback=options_dict.get("environment", {}).get("callback", None),
result_decoder=DEFAULT_DECODERS.get(self._program_id()),
)

Expand All @@ -165,7 +157,7 @@ def _run_primitive(self, primitive_inputs: Dict, user_kwargs: Dict) -> RuntimeJo
program_id=self._program_id(),
options=runtime_options,
inputs=primitive_inputs,
callback=combined.get("environment", {}).get("callback", None),
callback=options_dict.get("environment", {}).get("callback", None),
result_decoder=DEFAULT_DECODERS.get(self._program_id()),
)

Expand All @@ -178,15 +170,19 @@ def session(self) -> Optional[Session]:
"""
return self._session

def set_options(self, **fields: Any) -> None:
"""Set options values for the sampler.
Args:
**fields: The fields to update the options
"""
self.options = self._OPTIONS_CLASS( # pylint: disable=attribute-defined-outside-init
**merge_options(self.options, fields)
)
def _set_options(self, options: Optional[Union[Dict, BaseOptions]] = None) -> None:
"""Set options."""
if options is None:
self._options = self._options_class()
elif isinstance(options, dict):
default_options = self._options_class()
self.options = self._options_class(**merge_options(default_options, options))
elif isinstance(options, self._options_class):
self._options = replace(options)
else:
raise TypeError(
f"Invalid 'options' type. It can only be a dictionary of {self._options_class}"
)

@abstractmethod
def _validate_options(self, options: dict) -> None:
Expand Down
188 changes: 2 additions & 186 deletions qiskit_ibm_runtime/estimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,20 @@

from __future__ import annotations
import os
from typing import Optional, Dict, Sequence, Any, Union, Mapping
from typing import Optional, Dict, Sequence, Any, Union
import logging
import typing

import numpy as np
from numpy.typing import ArrayLike

from qiskit.circuit import QuantumCircuit
from qiskit.quantum_info.operators.base_operator import BaseOperator
from qiskit.primitives import BaseEstimator
from qiskit.quantum_info import SparsePauliOp, Pauli
from qiskit.primitives.utils import init_observable
from qiskit.circuit import Parameter
from qiskit.primitives.base.base_primitive import _isreal

from .runtime_job import RuntimeJob
from .ibm_backend import IBMBackend
from .options import Options
from .options.estimator_options import EstimatorOptions
from .base_primitive import BasePrimitiveV1, BasePrimitiveV2
from .utils.qctrl import validate as qctrl_validate
from .utils.deprecation import issue_deprecation_msg

# TODO: remove when we have real v2 base estimator
from .qiskit.primitives import BaseEstimatorV2
Expand All @@ -49,23 +41,6 @@
logger = logging.getLogger(__name__)


BasisObservableLike = Union[str, Pauli, SparsePauliOp, Mapping[Union[str, Pauli], complex]]
"""Types that can be natively used to construct a :const:`BasisObservable`."""

ObservablesArrayLike = Union[ArrayLike, Sequence[BasisObservableLike], BasisObservableLike]

ParameterMappingLike = Mapping[
Parameter, Union[float, np.ndarray, Sequence[float], Sequence[Sequence[float]]]
]
BindingsArrayLike = Union[
float,
np.ndarray,
ParameterMappingLike,
Sequence[Union[float, Sequence[float], np.ndarray, ParameterMappingLike]],
]
"""Parameter types that can be bound to a single circuit."""


class Estimator:
"""Base class for Qiskit Runtime Estimator."""

Expand Down Expand Up @@ -118,8 +93,7 @@ class EstimatorV2(BasePrimitiveV2, Estimator, BaseEstimatorV2):
print(psi1_H23.result())
"""

_ALLOWED_BASIS: str = "IXYZ01+-rl"
_OPTIONS_CLASS = EstimatorOptions
_options_class = EstimatorOptions

version = 2

Expand Down Expand Up @@ -149,101 +123,20 @@ def __init__(
Raises:
NotImplementedError: If "q-ctrl" channel strategy is used.
"""
self.options: EstimatorOptions
BaseEstimatorV2.__init__(self)
Estimator.__init__(self)
BasePrimitiveV2.__init__(self, backend=backend, session=session, options=options)

if self._service._channel_strategy == "q-ctrl":
raise NotImplementedError("EstimatorV2 is not supported with q-ctrl channel strategy.")

def run( # pylint: disable=arguments-differ
self,
circuits: QuantumCircuit | Sequence[QuantumCircuit],
observables: Sequence[ObservablesArrayLike]
| ObservablesArrayLike
| Sequence[BaseOperator]
| BaseOperator,
parameter_values: BindingsArrayLike | Sequence[BindingsArrayLike] | None = None,
**kwargs: Any,
) -> RuntimeJob:
"""Submit a request to the estimator primitive.
Args:
circuits: a (parameterized) :class:`~qiskit.circuit.QuantumCircuit` or
a list of (parameterized) :class:`~qiskit.circuit.QuantumCircuit`.
observables: Observable objects.
parameter_values: Concrete parameters to be bound.
**kwargs: Individual options to overwrite the default primitive options.
These include the runtime options in :class:`qiskit_ibm_runtime.RuntimeOptions`.
Returns:
Submitted job.
The result of the job is an instance of :class:`qiskit.primitives.EstimatorResult`.
Raises:
ValueError: Invalid arguments are given.
"""
# To bypass base class merging of options.
user_kwargs = {"_user_kwargs": kwargs}

return super().run(
circuits=circuits,
observables=observables,
parameter_values=parameter_values,
**user_kwargs,
)

def _run( # pylint: disable=arguments-differ
self,
circuits: Sequence[QuantumCircuit],
observables: Sequence[ObservablesArrayLike],
parameter_values: Sequence[Sequence[float]],
**kwargs: Any,
) -> RuntimeJob:
"""Submit a request to the estimator primitive.
Args:
circuits: a (parameterized) :class:`~qiskit.circuit.QuantumCircuit` or
a list of (parameterized) :class:`~qiskit.circuit.QuantumCircuit`.
observables: A list of observable objects.
parameter_values: An optional list of concrete parameters to be bound.
**kwargs: Individual options to overwrite the default primitive options.
These include the runtime options in :class:`~qiskit_ibm_runtime.RuntimeOptions`.
Returns:
Submitted job
"""
logger.debug(
"Running %s with new options %s",
self.__class__.__name__,
kwargs.get("_user_kwargs", {}),
)
inputs = {
"circuits": circuits,
"observables": observables,
"parameters": [circ.parameters for circ in circuits],
"parameter_values": parameter_values,
}
return self._run_primitive(
primitive_inputs=inputs, user_kwargs=kwargs.get("_user_kwargs", {})
)

def _validate_options(self, options: dict) -> None:
"""Validate that program inputs (options) are valid
Raises:
ValidationError: if validation fails.
ValueError: if validation fails.
"""
self._OPTIONS_CLASS(**options)

# TODO: Server should have different optimization/resilience levels for simulator

if (
Expand All @@ -257,83 +150,6 @@ def _validate_options(self, options: dict) -> None:
"a coupling map is required."
)

@staticmethod
def _validate_observables(
observables: Sequence[ObservablesArrayLike] | ObservablesArrayLike,
) -> Sequence[ObservablesArrayLike]:
def _check_and_init(obs: Any) -> Any:
if isinstance(obs, str):
if not all(basis in EstimatorV2._ALLOWED_BASIS for basis in obs):
raise ValueError(
f"Invalid character(s) found in observable string. "
f"Allowed basis are {EstimatorV2._ALLOWED_BASIS}."
)
elif isinstance(obs, Sequence):
return tuple(_check_and_init(obs_) for obs_ in obs)
elif not isinstance(obs, (Pauli, SparsePauliOp)) and isinstance(obs, BaseOperator):
issue_deprecation_msg(
msg="Only Pauli and SparsePauliOp operators can be used as observables",
version="0.13",
remedy="",
)
return init_observable(obs)
elif isinstance(obs, Mapping):
for key in obs.keys():
_check_and_init(key)

return obs

if isinstance(observables, str) or not isinstance(observables, Sequence):
observables = (observables,)

if len(observables) == 0:
raise ValueError("No observables were provided.")

return tuple(_check_and_init(obs_array) for obs_array in observables)

@staticmethod
def _validate_parameter_values(
parameter_values: BindingsArrayLike | Sequence[BindingsArrayLike] | None,
default: Sequence[Sequence[float]] | Sequence[float] | None = None,
) -> Sequence:

# Allow optional (if default)
if parameter_values is None:
if default is None:
raise ValueError("No default `parameter_values`, optional input disallowed.")
parameter_values = default

# Convert single input types to length-1 lists
if _isreal(parameter_values):
parameter_values = [[parameter_values]]
elif isinstance(parameter_values, Mapping):
parameter_values = [parameter_values]
elif isinstance(parameter_values, Sequence) and all(
_isreal(item) for item in parameter_values
):
parameter_values = [parameter_values]
return tuple(parameter_values) # type: ignore[arg-type]

@staticmethod
def _cross_validate_circuits_parameter_values(
circuits: tuple[QuantumCircuit, ...], parameter_values: tuple[tuple[float, ...], ...]
) -> None:
if len(circuits) != len(parameter_values):
raise ValueError(
f"The number of circuits ({len(circuits)}) does not match "
f"the number of parameter value sets ({len(parameter_values)})."
)

@staticmethod
def _cross_validate_circuits_observables(
circuits: tuple[QuantumCircuit, ...], observables: tuple[ObservablesArrayLike, ...]
) -> None:
if len(circuits) != len(observables):
raise ValueError(
f"The number of circuits ({len(circuits)}) does not match "
f"the number of observables ({len(observables)})."
)

@classmethod
def _program_id(cls) -> str:
"""Return the program ID."""
Expand Down
2 changes: 1 addition & 1 deletion qiskit_ibm_runtime/options/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@

from .environment_options import EnvironmentOptions
from .execution_options import ExecutionOptionsV1 as ExecutionOptions
from .options import Options, BaseOptions
from .options import Options
from .simulator_options import SimulatorOptions
from .transpilation_options import TranspilationOptions
from .resilience_options import ResilienceOptionsV1 as ResilienceOptions
Expand Down
Loading

0 comments on commit 73b3385

Please sign in to comment.