Skip to content

Commit

Permalink
Adds target kwarg to tomography init (qiskit-community#1025)
Browse files Browse the repository at this point in the history
This allows specifying a custom target for analysis when initializing the experiments. If set to None automatic target calculation is disabled.

Co-authored-by: Will Shanks <wshaos@posteo.net>
  • Loading branch information
chriseclectic and wshanks committed Jan 26, 2023
1 parent bfe717f commit 64e6049
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 8 deletions.
9 changes: 8 additions & 1 deletion qiskit_experiments/library/tomography/qpt_experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def __init__(
basis_indices: Optional[Sequence[Tuple[List[int], List[int]]]] = None,
qubits: Optional[Sequence[int]] = None,
analysis: Union[BaseAnalysis, None, str] = "default",
target: Union[Statevector, DensityMatrix, None, str] = "default",
):
"""Initialize a quantum process tomography experiment.
Expand Down Expand Up @@ -94,6 +95,10 @@ def __init__(
analysis: Optional, a custom analysis instance to use. If ``"default"``
:class:`~.ProcessTomographyAnalysis` will be used. If None no analysis
instance will be set.
target: Optional, a custom quantum state target for computing the
state fidelity of the fitted density matrix during analysis.
If "default" the state will be inferred from the input circuit
if it contains no classical instructions.
"""
if analysis == "default":
analysis = ProcessTomographyAnalysis()
Expand All @@ -115,7 +120,9 @@ def __init__(

# Set target quantum channel
if isinstance(self.analysis, TomographyAnalysis):
self.analysis.set_options(target=self._target_quantum_channel())
if target == "default":
target = self._target_quantum_channel()
self.analysis.set_options(target=target)

def _target_quantum_channel(self) -> Union[Choi, Operator]:
"""Return the process tomography target"""
Expand Down
9 changes: 8 additions & 1 deletion qiskit_experiments/library/tomography/qst_experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def __init__(
basis_indices: Optional[Sequence[List[int]]] = None,
qubits: Optional[Sequence[int]] = None,
analysis: Union[BaseAnalysis, None, str] = "default",
target: Union[Statevector, DensityMatrix, None, str] = "default",
):
"""Initialize a quantum process tomography experiment.
Expand All @@ -82,6 +83,10 @@ def __init__(
analysis: Optional, a custom analysis instance to use. If ``"default"``
:class:`~.StateTomographyAnalysis` will be used. If None no analysis
instance will be set.
target: Optional, a custom quantum state target for computing the
state fidelity of the fitted density matrix during analysis.
If "default" the state will be inferred from the input circuit
if it contains no classical instructions.
"""
if isinstance(circuit, Statevector):
# Convert to circuit using initialize instruction
Expand Down Expand Up @@ -110,7 +115,9 @@ def __init__(

# Set target quantum state
if isinstance(self.analysis, TomographyAnalysis):
self.analysis.set_options(target=self._target_quantum_state())
if target == "default":
target = self._target_quantum_state()
self.analysis.set_options(target=target)

def _target_quantum_state(self) -> Union[Statevector, DensityMatrix]:
"""Return the state tomography target"""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
---
features:
- |
Adds ``backend`` and ``analysis`` init kwargs to :class:`~.StateTomography`
and :class:`~.ProcessTomography` experiments to match the base
:class:`~.TomographyExperiment` init kwargs. This allows specifying the
intented backend, or a custom analysis class when initializing the
experiments.
Adds ``backend``, ``analysis``, and ``target`` init kwargs to the
:class:`~.StateTomography` and :class:`~.ProcessTomography` experiments.
These allow specifying intended backend, a custom analysis class, or a
custom target for fidelity calculations, when initializing the experiments.
upgrade:
- |
Renames the ``qubits``, ``measurement_qubits``, and ``preparation_qubits``
Expand Down
19 changes: 19 additions & 0 deletions test/library/tomography/test_process_tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from qiskit_aer.noise import NoiseModel
from qiskit_experiments.library import ProcessTomography, MitigatedProcessTomography
from qiskit_experiments.library.tomography import ProcessTomographyAnalysis, basis
from qiskit_experiments.database_service import ExperimentEntryNotFound
from .tomo_utils import (
FITTERS,
filter_results,
Expand Down Expand Up @@ -477,3 +478,21 @@ def test_mitigated_full_qpt_random_unitary(self, qubits):
f_threshold,
msg=f"{fitter} fit fidelity is low for qubits {qubits}",
)

def test_target_none(self):
"""Test setting target=None disables fidelity calculation."""
seed = 4343
backend = AerSimulator(seed_simulator=seed)
target = qi.random_unitary(2, seed=seed)
exp = ProcessTomography(target, backend=backend, target=None)
expdata = exp.run()
self.assertExperimentDone(expdata)
state = expdata.analysis_results("state").value
self.assertTrue(
isinstance(state, qi.Choi),
msg="Fitted state is not Choi matrix",
)
with self.assertRaises(
ExperimentEntryNotFound, msg="process_fidelity should not exist when target=None"
):
expdata.analysis_results("process_fidelity")
21 changes: 20 additions & 1 deletion test/library/tomography/test_state_tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

from qiskit_experiments.library import StateTomography, MitigatedStateTomography
from qiskit_experiments.library.tomography import StateTomographyAnalysis, basis
from qiskit_experiments.database_service import ExperimentEntryNotFound
from .tomo_utils import (
FITTERS,
filter_results,
Expand Down Expand Up @@ -252,7 +253,7 @@ def test_experiment_config(self):
self.assertTrue(self.json_equiv(exp, loaded_exp))

def test_analysis_config(self):
""" "Test converting analysis to and from config works"""
"""Test converting analysis to and from config works"""
analysis = StateTomographyAnalysis()
loaded = StateTomographyAnalysis.from_config(analysis.config())
self.assertNotEqual(analysis, loaded)
Expand Down Expand Up @@ -375,3 +376,21 @@ def test_mitigated_full_qst(self, qubits):
f_threshold,
msg=f"{fitter} fit fidelity is low for qubits {qubits}",
)

def test_target_none(self):
"""Test setting target=None disables fidelity calculation."""
seed = 4343
backend = AerSimulator(seed_simulator=seed)
target = qi.random_statevector(2, seed=seed)
exp = StateTomography(target, backend=backend, target=None)
expdata = exp.run()
self.assertExperimentDone(expdata)
state = expdata.analysis_results("state").value
self.assertTrue(
isinstance(state, qi.DensityMatrix),
msg="Fitted state is not density matrix",
)
with self.assertRaises(
ExperimentEntryNotFound, msg="state_fidelity should not exist when target=None"
):
expdata.analysis_results("state_fidelity")

0 comments on commit 64e6049

Please sign in to comment.