Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HEAT experiments #625

Open
wants to merge 54 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
7b2bfc1
cleanup old PR #460
nkanazawa1989 Jan 19, 2022
fccf94c
write release note
nkanazawa1989 Jan 19, 2022
6e64321
serialization unittest
nkanazawa1989 Jan 20, 2022
49a7845
fix projection angle of Z measure
nkanazawa1989 Jan 24, 2022
b766f56
Merge branch 'main' of github.com:Qiskit/qiskit-experiments into expe…
nkanazawa1989 Jan 24, 2022
d32444f
add unittest for running experiments and minor doc fix
nkanazawa1989 Jan 25, 2022
c0e0da5
Update qiskit_experiments/library/hamiltonian/__init__.py
nkanazawa1989 Jan 27, 2022
423dad4
Update qiskit_experiments/library/hamiltonian/__init__.py
nkanazawa1989 Jan 27, 2022
8adcca2
Update qiskit_experiments/library/hamiltonian/heat_analysis.py
nkanazawa1989 Jan 27, 2022
942e558
Update qiskit_experiments/library/hamiltonian/heat_analysis.py
nkanazawa1989 Jan 27, 2022
4f70f6e
Update qiskit_experiments/library/hamiltonian/heat_base.py
nkanazawa1989 Jan 27, 2022
9cc247f
Update qiskit_experiments/library/hamiltonian/heat_base.py
nkanazawa1989 Jan 27, 2022
e8a11f7
Update qiskit_experiments/library/hamiltonian/heat_base.py
nkanazawa1989 Jan 27, 2022
00a991a
Update qiskit_experiments/library/hamiltonian/heat_base.py
nkanazawa1989 Jan 27, 2022
7c49da1
Update qiskit_experiments/library/hamiltonian/heat_base.py
nkanazawa1989 Jan 27, 2022
4a3c645
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Jan 27, 2022
ca871ac
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Jan 27, 2022
8ced3c2
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Jan 27, 2022
52a1439
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Jan 27, 2022
42f0768
Update releasenotes/notes/add-heat-experiment-047a73818407e733.yaml
nkanazawa1989 Jan 27, 2022
0cec011
Merge branch 'main' into experiment/heat
nkanazawa1989 Jan 27, 2022
16fb9ea
document overhaul for ZXHeat class
nkanazawa1989 Jan 27, 2022
6175036
document overhaul for HeatElement class
nkanazawa1989 Jan 27, 2022
532f855
black
nkanazawa1989 Jan 27, 2022
e379b49
update test tolerance
nkanazawa1989 Jan 27, 2022
c7318b8
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Jan 31, 2022
9a59715
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Jan 31, 2022
ef8c56c
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Jan 31, 2022
30f9200
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Jan 31, 2022
c4333fb
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Jan 31, 2022
6524858
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Jan 31, 2022
cf47445
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Jan 31, 2022
077d217
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Jan 31, 2022
a773faa
Update qiskit_experiments/library/hamiltonian/heat_base.py
nkanazawa1989 Jan 31, 2022
9819c16
update test tolerance to be more precise
nkanazawa1989 Jan 31, 2022
678af55
Merge branch 'experiment/heat' of github.com:nkanazawa1989/qiskit-exp…
nkanazawa1989 Jan 31, 2022
1ceff09
Update heat_zx.py
nkanazawa1989 Jan 31, 2022
e540446
Merge branch 'main' of github.com:Qiskit/qiskit-experiments into expe…
nkanazawa1989 Feb 2, 2022
e103640
udpate analysis constructor and remove BatchHeatHelper
nkanazawa1989 Feb 2, 2022
d918470
Merge branch 'experiment/heat' of github.com:nkanazawa1989/qiskit-exp…
nkanazawa1989 Feb 2, 2022
280cae1
fix lint
nkanazawa1989 Feb 2, 2022
4f7cd81
Update qiskit_experiments/library/hamiltonian/heat_base.py
nkanazawa1989 Feb 8, 2022
5c40d7d
Update qiskit_experiments/library/hamiltonian/heat_base.py
nkanazawa1989 Feb 8, 2022
4882e9e
Update qiskit_experiments/library/hamiltonian/heat_base.py
nkanazawa1989 Feb 8, 2022
a62cc8f
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Feb 8, 2022
5d4945e
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Feb 8, 2022
c908105
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Feb 8, 2022
6c1a556
Merge branch 'main' of github.com:Qiskit/qiskit-experiments into expe…
nkanazawa1989 Feb 8, 2022
995a009
Update qiskit_experiments/library/hamiltonian/heat_zx.py
nkanazawa1989 Feb 9, 2022
caf945a
Merge branch 'main' of github.com:Qiskit/qiskit-experiments into expe…
nkanazawa1989 Feb 10, 2022
c400186
remove usage of fitval
nkanazawa1989 Feb 10, 2022
aba80ca
Merge branch 'experiment/heat' of github.com:nkanazawa1989/qiskit-exp…
nkanazawa1989 Feb 10, 2022
fec3997
lint
nkanazawa1989 Feb 10, 2022
1e21e36
fix bug due to #662
nkanazawa1989 Feb 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/apidocs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ Experiment Modules
mod_randomized_benchmarking
mod_tomography
mod_quantum_volume
mod_hamiltonian
6 changes: 6 additions & 0 deletions docs/apidocs/mod_hamiltonian.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. _qiskit-experiments-hamiltonian:

.. automodule:: qiskit_experiments.library.hamiltonian
:no-members:
:no-inherited-members:
:no-special-members:
2 changes: 2 additions & 0 deletions qiskit_experiments/framework/composite/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@
# Composite experiment classes
from .parallel_experiment import ParallelExperiment
from .batch_experiment import BatchExperiment

from .composite_experiment import sync_experiment_options, sync_transpile_options
75 changes: 74 additions & 1 deletion qiskit_experiments/framework/composite/composite_experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
Composite Experiment abstract base class.
"""

from typing import List, Sequence, Optional, Union
from typing import List, Sequence, Optional, Union, Type
from abc import abstractmethod
import functools
import warnings
from qiskit.providers.backend import Backend
from qiskit_experiments.framework import BaseExperiment, ExperimentData
Expand Down Expand Up @@ -131,3 +132,75 @@ def _postprocess_transpiled_circuits(self, circuits, **run_options):
for expr in self._experiments:
if not isinstance(expr, CompositeExperiment):
expr._postprocess_transpiled_circuits(circuits, **run_options)


def sync_transpile_options(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed in the first place? I wonder if this should be the default behavior of CompositeExperiment? Or why not have this as an extra function in the CompositeExperiment? I don't see why the decorator framework is needed when we only decorate a single method of a single class.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This aims at making a batch experiment to behave as if a single experiment (because user doesn't need to recognize its implementation to use). This SHOUD not be default behavior (unfortunately it is now) because we should be able to transpile batch (I believe also parallel) experiment with its own configuration.

composite_cls: Type[CompositeExperiment],
) -> Type[CompositeExperiment]:
"""A class decorator that overrides the transpile option setter method.

This method overrides the behavior of :meth:`set_transpile_options` method.
The option values set to the composite instance
will be propagated through all component experiments.

Args:
composite_cls: CompositeExperiment subclass to decorate.

Returns:
Composite experiment that implements option synchronization.

Raises:
TypeError: When class is not subclass of :class:`CompositeExperiment`
"""
if not issubclass(composite_cls, CompositeExperiment):
raise TypeError("Class is not composite experiment. Cannot override method.")

options_setter = getattr(composite_cls, "set_transpile_options")

@functools.wraps(options_setter)
def sync_opts(instance, **fields):
options_setter(instance, **fields)
# set the same options to component experiments
for comp in instance.component_experiment():
comp.set_transpile_options(**fields)

# override set method
setattr(composite_cls, "set_transpile_options", sync_opts)

return composite_cls


def sync_experiment_options(
composite_cls: Type[CompositeExperiment],
) -> Type[CompositeExperiment]:
Comment on lines +182 to +184
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above. Using decorators here only makes the code harder to follow.

"""A class decorator that overrides the experiment option setter method.

This method overrides the behavior of :meth:`set_experiment_options` method.
The option values set to the composite instance
will be propagated through all component experiments.

Args:
composite_cls: CompositeExperiment subclass to decorate.

Returns:
Composite experiment that implements option synchronization.

Raises:
TypeError: When class is not subclass of :class:`CompositeExperiment`
"""
if not issubclass(composite_cls, CompositeExperiment):
raise TypeError("Class is not composite experiment. Cannot override method.")

options_setter = getattr(composite_cls, "set_experiment_options")

@functools.wraps(options_setter)
def sync_opts(instance, **fields):
options_setter(instance, **fields)
# set the same options to component experiments
for comp in instance.component_experiment():
comp.set_experiment_options(**fields)

# override set method
setattr(composite_cls, "set_experiment_options", sync_opts)

return composite_cls
6 changes: 6 additions & 0 deletions qiskit_experiments/library/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@
~characterization.RamseyXY
~characterization.FineFrequency
~characterization.ReadoutAngle
~hamiltonian.ZXHeat
~hamiltonian.ZX90HeatXError
~hamiltonian.ZX90HeatYError
~hamiltonian.ZX90HeatZError


.. _calibration:
Expand Down Expand Up @@ -143,10 +147,12 @@ class instance to manage parameters and pulse schedules.
from .tomography import StateTomography, ProcessTomography
from .quantum_volume import QuantumVolume
from .mitigation import ReadoutMitigationExperiment
from .hamiltonian import ZXHeat, ZX90HeatXError, ZX90HeatYError, ZX90HeatZError

# Experiment Sub-modules
from . import calibration
from . import characterization
from . import randomized_benchmarking
from . import tomography
from . import quantum_volume
from . import hamiltonian
65 changes: 65 additions & 0 deletions qiskit_experiments/library/hamiltonian/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2022.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""
===============================================================================================
Hamiltonian Characterization Experiments (:mod:`qiskit_experiments.library.hamiltonian`)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a fairly broad title. Should the contents in cr_hamiltonian.py be moved under qiskit_experiments.library.hamiltonian as well? Also, I put a comment by the reno as well -- I feel like experiments are characterizing a particular schedule more than the underlying Hamiltonian. One could tweak the pulse shape or cancellation tone to adjust observed errors from the target ZX90 operation.

Copy link
Collaborator Author

@nkanazawa1989 nkanazawa1989 Jan 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably entangler and Entangler characterization? But this could kick out JAZZ experiment from here. I think having static ZZ in the module improves accessibility.

(edit)
Probably we may want to add sizzle too.

===============================================================================================

.. currentmodule:: qiskit_experiments.library.hamiltonian

This module provides a set of experiments to characterize qubit Hamiltonians.

HEAT Experiments
================

HEAT stands for `Hamiltonian Error Amplifying Tomography` which amplifies the
dynamics of an entangling gate along a specified axis of the target qubit. Here,
errors are typically amplified by repeating a sequence of gates which results in
a ping-pong pattern when measuring the qubit population.

HEAT for ZX Hamiltonian
-----------------------
eggerdj marked this conversation as resolved.
Show resolved Hide resolved

.. autosummary::
:toctree: ../stubs/
:template: autosummary/experiment.rst

ZXHeat
ZX90HeatXError
ZX90HeatYError
ZX90HeatZError

HEAT Analysis
-------------

.. autosummary::
:toctree: ../stubs/
:template: autosummary/analysis.rst

HeatElementAnalysis
HeatAnalysis

HEAT Base Classes
-----------------

.. autosummary::
:toctree: ../stubs/
:template: autosummary/experiment.rst

HeatElement


"""

from .heat_base import HeatElement
from .heat_zx import ZXHeat, ZX90HeatXError, ZX90HeatYError, ZX90HeatZError
from .heat_analysis import HeatElementAnalysis, HeatAnalysis
157 changes: 157 additions & 0 deletions qiskit_experiments/library/hamiltonian/heat_analysis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2021.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""
Analysis for HEAT experiments.
"""

from typing import Tuple

import numpy as np

from qiskit_experiments.curve_analysis import ErrorAmplificationAnalysis, ParameterRepr
from qiskit_experiments.exceptions import AnalysisError
from qiskit_experiments.framework import (
CompositeAnalysis,
ExperimentData,
AnalysisResultData,
Options,
FitVal,
)


class HeatElementAnalysis(ErrorAmplificationAnalysis):
"""An analysis class for HEAT experiment to define the fixed parameters.

# section: overview

This is standard error amplification analysis.

# section: see_also
qiskit_experiments.curve_analysis.ErrorAmplificationAnalysis
"""

__fixed_parameters__ = ["angle_per_gate", "phase_offset", "amp"]

@classmethod
def _default_options(cls) -> Options:
"""Default analysis options."""
options = super()._default_options()
options.angle_per_gate = np.pi
options.phase_offset = np.pi / 2
options.amp = 1.0

return options


class HeatAnalysis(CompositeAnalysis):
r"""A composite error amplification analysis to get unitary error coefficients.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this docstring would be benefit from writting down the Hamiltonian so that we can better see how the terms A_{I\beta} and A_{Z\beta} fit in the model.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The model is written in the ZXHeat class rather than here since this is not restricted to specific Hamiltonian and it might be hard to write general model.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not write an example model and make it clear that this has a broader use.

Copy link
Collaborator Author

@nkanazawa1989 nkanazawa1989 Feb 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any example of the model? (without assuming specific amplification sequence) I can write a model specific to for example ZX Hamiltonian but this may mislead user so that usecase is limited.


# section: fit_model

Heat experiment amplifies the dynamics of the entangling gate along the
experiment-specific error axis on the target qubit Bloch sphere.
This analysis takes two error amplification experiment results performed with
different states of the control qubit to distinguish the contribution
of local term (such as IX) from non-local term (such as ZX).

This analysis takes a set of `d_theta` parameters from child error amplification results
which might be represented by a unique name in the child experiment data.
With these fit parameters, two Hamiltonian coefficients will be computed as

.. math::

A_{I\beta} = \frac{1}{2}\left( d\theta_{\beta 0} + d\theta_{\beta 1} \right) \\

A_{Z\beta} = \frac{1}{2}\left( d\theta_{\beta 0} - d\theta_{\beta 1} \right)

where, :math:`\beta \in [X, Y, Z]` is a single-qubit Pauli term, and
:math:`d\theta_{\beta k}` is an angle error ``d_theta`` extracted from the HEAT experiment
with the control qubit in state :math:`|k\rangle \in [|0\rangle, |1\rangle]`.

# section: see_also
qiskit_experiments.library.hamiltonian.HeatElementAnalysis
nkanazawa1989 marked this conversation as resolved.
Show resolved Hide resolved
qiskit_experiments.curve_analysis.ErrorAmplificationAnalysis

"""

def __init__(
self,
fit_params: Tuple[str, str],
out_params: Tuple[str, str],
):
"""Create new HEAT analysis.

Args:
fit_params: Name of error parameters for each amplification sequence.
out_params: Name of Hamiltonian coefficients.

Raises:
AnalysisError: When size of ``fit_params`` or ``out_params`` are not 2.
nkanazawa1989 marked this conversation as resolved.
Show resolved Hide resolved
"""
if len(fit_params) != 2:
raise AnalysisError(
f"{self.__class__.__name__} assumes two fit parameters extracted from "
"a set of experiments with different control qubit state input. "
f"{len(fit_params)} input parameter names are specified."
)

if len(out_params) != 2:
raise AnalysisError(
f"{self.__class__.__name__} assumes two output parameters computed with "
"a set of experiment results with different control qubit state input. "
f"{len(out_params)} output parameter names are specified."
)

analyses = []
for fit_parm in fit_params:
sub_analysis = HeatElementAnalysis()
sub_analysis.set_options(result_parameters=[ParameterRepr("d_theta", fit_parm, "rad")])
analyses.append(sub_analysis)

super().__init__(analyses=analyses)

self._fit_params = fit_params
self._out_params = out_params

def _run_analysis(self, experiment_data: ExperimentData):

# wait for child experiments to complete
super()._run_analysis(experiment_data)
eggerdj marked this conversation as resolved.
Show resolved Hide resolved

# extract d_theta parameters
fit_results = []
for i, pname in enumerate(self._fit_params):
fit_results.append(experiment_data.child_data(i).analysis_results(pname))

# Check data quality
is_good_quality = all(r.quality == "good" for r in fit_results)

# Compute unitary terms
ib = (fit_results[0].value.value + fit_results[1].value.value) / 2
zb = (fit_results[0].value.value - fit_results[1].value.value) / 2

# Compute new variance
sigma = np.sqrt(fit_results[0].value.stderr ** 2 + fit_results[1].value.stderr ** 2)
nkanazawa1989 marked this conversation as resolved.
Show resolved Hide resolved

estimate_ib = AnalysisResultData(
name=self._out_params[0],
value=FitVal(value=ib, stderr=sigma, unit="rad"),
quality="good" if is_good_quality else "bad",
)

estimate_zb = AnalysisResultData(
name=self._out_params[1],
value=FitVal(value=zb, stderr=sigma, unit="rad"),
quality="good" if is_good_quality else "bad",
)

return [estimate_ib, estimate_zb], []
Loading