Skip to content

Commit

Permalink
Bugfix: missing extra in mitigated tomography analysis (#1344)
Browse files Browse the repository at this point in the history
### Summary

#1133 introduce a bug in `MitigatedTomographyAnalysis` that accidentally
drops extra analysis metadata. This PR fixes the bug.

### Details and comments

In the new data storage implementation with dataframe,
`ExperimentData.analysis_results` returns a copy of the protected
dataframe and mutating the returned object doesn't update the source.
This PR introduces new option to `TomographyAnalysis` to inject extra
metadata.

<img width="993" alt="screenshot"
src="https://github.com/Qiskit-Extensions/qiskit-experiments/assets/39517270/d8674af1-78ad-4870-bfea-d441f9dfd1e8">

(edit) note that reno is not necessary because 1133 is not released yet.
  • Loading branch information
nkanazawa1989 authored Jan 10, 2024
1 parent a6c9e53 commit 2571675
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 13 deletions.
3 changes: 2 additions & 1 deletion qiskit_experiments/framework/experiment_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -1557,7 +1557,8 @@ def analysis_results(
dataframe: Set to ``True`` to return analysis results in the dataframe format.
Returns:
Analysis results for this experiment.
A copy of analysis results data. Updating the returned object doesn't
mutate the original dataset.
Raises:
ExperimentEntryNotFound: If the entry cannot be found.
Expand Down
26 changes: 14 additions & 12 deletions qiskit_experiments/library/tomography/mit_tomography_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,24 +101,26 @@ def _run_analysis(self, experiment_data):
# Construct noisy measurement basis
mitigator = roerror_data.analysis_results(0).value

# Construct noisy measurement basis
measurement_basis = PauliMeasurementBasis(mitigator=mitigator)
tomo_analysis.set_options(measurement_basis=measurement_basis)

# Run mitigated tomography analysis
tomo_analysis.run(tomo_data, replace_results=True).block_for_results()
for res in tomo_data.analysis_results(block=False):
res.extra["mitigated"] = True
# Run mitigated tomography analysis with noisy mitigated basis
# Tomo analysis instance is internally copied by setting option with run.
tomo_analysis.run(
tomo_data,
replace_results=True,
measurement_basis=PauliMeasurementBasis(mitigator=mitigator),
extra={"mitigated": True},
).block_for_results()

# Combine results so that tomography results are ordered first
combined_data = [tomo_data, roerror_data]

# Run unmitigated tomography analysis
if self.options.unmitigated_fit:
tomo_analysis.set_options(measurement_basis=PauliMeasurementBasis())
nomit_data = tomo_analysis.run(tomo_data, replace_results=False).block_for_results()
for res in nomit_data.analysis_results(block=False):
res.extra["mitigated"] = False
nomit_data = tomo_analysis.run(
tomo_data,
replace_results=False,
measurement_basis=PauliMeasurementBasis(),
extra={"mitigated": False},
).block_for_results()
combined_data.append(nomit_data)

if self._flatten_results:
Expand Down
5 changes: 5 additions & 0 deletions qiskit_experiments/library/tomography/tomography_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ def _default_options(cls) -> Options:
the remaining tomographic bases conditional on the basis index. The
conditional preparation basis index is stored in state analysis result
extra fields `"conditional_preparation_index"`.
extra (Dict[str, Any]): Extra metadata dictionary attached to analysis results.
"""
options = super()._default_options()

Expand All @@ -132,6 +133,7 @@ def _default_options(cls) -> Options:
options.conditional_circuit_clbits = None
options.conditional_measurement_indices = None
options.conditional_preparation_indices = None
options.extra = {}
return options

@classmethod
Expand Down Expand Up @@ -232,6 +234,9 @@ def _run_analysis(self, experiment_data):

analysis_results = state_results + other_results

if self.options.extra:
for res in analysis_results:
res.extra.update(self.options.extra)
return analysis_results, []

def _fit_state_results(
Expand Down
2 changes: 2 additions & 0 deletions test/library/tomography/test_process_tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,8 @@ def test_mitigated_full_qpt_random_unitary(self, qubits):
f_threshold,
msg=f"{fitter} fit fidelity is low for qubits {qubits}",
)
self.assertTrue(mitfid.extra["mitigated"])
self.assertFalse(nomitfid.extra["mitigated"])

@ddt.data([0], [1], [0, 1], [1, 0])
def test_qpt_conditional_circuit(self, circuit_clbits):
Expand Down
2 changes: 2 additions & 0 deletions test/library/tomography/test_state_tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,8 @@ def test_mitigated_full_qst(self, qubits):
f_threshold,
msg=f"{fitter} fit fidelity is low for qubits {qubits}",
)
self.assertTrue(mitfid.extra["mitigated"])
self.assertFalse(nomitfid.extra["mitigated"])

@ddt.data([None, 1], [True, 4], [[0], 2], [[1], 2], [[0, 1], 4])
@ddt.unpack
Expand Down

0 comments on commit 2571675

Please sign in to comment.