diff --git a/qiskit_algorithms/state_fidelities/base_state_fidelity.py b/qiskit_algorithms/state_fidelities/base_state_fidelity.py index 1909e63f..2eac9aec 100644 --- a/qiskit_algorithms/state_fidelities/base_state_fidelity.py +++ b/qiskit_algorithms/state_fidelities/base_state_fidelity.py @@ -23,7 +23,6 @@ from qiskit.circuit import ParameterVector from ..algorithm_job import AlgorithmJob -from .state_fidelity_result import StateFidelityResult class BaseStateFidelity(ABC): @@ -246,7 +245,7 @@ def _run( values_1: Sequence[float] | Sequence[Sequence[float]] | None = None, values_2: Sequence[float] | Sequence[Sequence[float]] | None = None, **options, - ) -> StateFidelityResult: + ) -> AlgorithmJob: r""" Computes the state overlap (fidelity) calculation between two (parametrized) circuits (first and second) for a specific set of parameter @@ -263,7 +262,7 @@ def _run( Higher priority setting overrides lower priority setting. Returns: - The result of the fidelity calculation. + A newly constructed algorithm job instance to get the fidelity result. """ raise NotImplementedError @@ -293,15 +292,15 @@ def run( Returns: Primitive job for the fidelity calculation. - The job's result is an instance of ``StateFidelityResult``. + The job's result is an instance of :class:`.StateFidelityResult`. """ - - job = AlgorithmJob(self._run, circuits_1, circuits_2, values_1, values_2, **options) + job = self._run(circuits_1, circuits_2, values_1, values_2, **options) job.submit() return job - def _truncate_fidelities(self, fidelities: Sequence[float]) -> Sequence[float]: + @staticmethod + def _truncate_fidelities(fidelities: Sequence[float]) -> Sequence[float]: """ Ensures fidelity result in [0,1]. diff --git a/qiskit_algorithms/state_fidelities/compute_uncompute.py b/qiskit_algorithms/state_fidelities/compute_uncompute.py index 1b41346b..1512e04e 100644 --- a/qiskit_algorithms/state_fidelities/compute_uncompute.py +++ b/qiskit_algorithms/state_fidelities/compute_uncompute.py @@ -19,11 +19,13 @@ from qiskit import QuantumCircuit from qiskit.primitives import BaseSampler +from qiskit.primitives.primitive_job import PrimitiveJob from qiskit.providers import Options from ..exceptions import AlgorithmError from .base_state_fidelity import BaseStateFidelity from .state_fidelity_result import StateFidelityResult +from ..algorithm_job import AlgorithmJob class ComputeUncompute(BaseStateFidelity): @@ -118,7 +120,7 @@ def _run( values_1: Sequence[float] | Sequence[Sequence[float]] | None = None, values_2: Sequence[float] | Sequence[Sequence[float]] | None = None, **options, - ) -> StateFidelityResult: + ) -> AlgorithmJob: r""" Computes the state overlap (fidelity) calculation between two (parametrized) circuits (first and second) for a specific set of parameter @@ -135,7 +137,7 @@ def _run( Higher priority setting overrides lower priority setting. Returns: - The result of the fidelity calculation. + An AlgorithmJOb for the fidelity calculation. Raises: ValueError: At least one pair of circuits must be defined. @@ -155,29 +157,36 @@ def _run( opts = copy(self._default_options) opts.update_options(**options) - job = self._sampler.run(circuits=circuits, parameter_values=values, **opts.__dict__) + sampler_job = self._sampler.run(circuits=circuits, parameter_values=values, **opts.__dict__) + + local_opts = self._get_local_options(opts.__dict__) + return AlgorithmJob(ComputeUncompute._call, sampler_job, circuits, self._local, local_opts) + @staticmethod + def _call( + job: PrimitiveJob, circuits: Sequence[QuantumCircuit], local: bool, local_opts: Options + ) -> StateFidelityResult: try: result = job.result() except Exception as exc: raise AlgorithmError("Sampler job failed!") from exc - if self._local: + if local: raw_fidelities = [ - self._get_local_fidelity(prob_dist, circuit.num_qubits) + ComputeUncompute._get_local_fidelity(prob_dist, circuit.num_qubits) for prob_dist, circuit in zip(result.quasi_dists, circuits) ] else: raw_fidelities = [ - self._get_global_fidelity(prob_dist) for prob_dist in result.quasi_dists + ComputeUncompute._get_global_fidelity(prob_dist) for prob_dist in result.quasi_dists ] - fidelities = self._truncate_fidelities(raw_fidelities) + fidelities = ComputeUncompute._truncate_fidelities(raw_fidelities) return StateFidelityResult( fidelities=fidelities, raw_fidelities=raw_fidelities, metadata=result.metadata, - options=self._get_local_options(opts.__dict__), + options=local_opts, ) @property @@ -216,7 +225,8 @@ def _get_local_options(self, options: Options) -> Options: opts.update_options(**options) return opts - def _get_global_fidelity(self, probability_distribution: dict[int, float]) -> float: + @staticmethod + def _get_global_fidelity(probability_distribution: dict[int, float]) -> float: """Process the probability distribution of a measurement to determine the global fidelity. @@ -228,9 +238,8 @@ def _get_global_fidelity(self, probability_distribution: dict[int, float]) -> fl """ return probability_distribution.get(0, 0) - def _get_local_fidelity( - self, probability_distribution: dict[int, float], num_qubits: int - ) -> float: + @staticmethod + def _get_local_fidelity(probability_distribution: dict[int, float], num_qubits: int) -> float: """Process the probability distribution of a measurement to determine the local fidelity by averaging over single-qubit projectors.