Skip to content

Commit

Permalink
add unittest for running experiments and minor doc fix
Browse files Browse the repository at this point in the history
  • Loading branch information
nkanazawa1989 committed Jan 25, 2022
1 parent b766f56 commit d32444f
Show file tree
Hide file tree
Showing 6 changed files with 267 additions and 52 deletions.
13 changes: 6 additions & 7 deletions qiskit_experiments/library/hamiltonian/heat_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,11 @@ def __init__(self, fit_params: List[str], out_params: List[str]):
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.
"""
super(HeatAnalysis, self).__init__()
super().__init__()

if len(fit_params) != 2:
raise AnalysisError(
Expand All @@ -113,9 +116,7 @@ def _run_analysis(self, experiment_data: ExperimentData):
# 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)
)
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)
Expand All @@ -125,9 +126,7 @@ def _run_analysis(self, experiment_data: ExperimentData):
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
)
sigma = np.sqrt(fit_results[0].value.stderr ** 2 + fit_results[1].value.stderr ** 2)

estimate_ib = AnalysisResultData(
name=self.out_params[0],
Expand Down
8 changes: 3 additions & 5 deletions qiskit_experiments/library/hamiltonian/heat_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def __init__(
meas_circ: QuantumCircuit,
backend: Optional[Backend] = None,
parameter_name: Optional[str] = "d_theta",
**kwargs
**kwargs,
):
"""Create new HEAT sub experiment.
Expand All @@ -100,9 +100,7 @@ def __init__(
See :meth:`experiment_options` for details.
"""
analysis = HeatElementAnalysis()
analysis.set_options(
result_parameters=[ParameterRepr("d_theta", parameter_name, "rad")]
)
analysis.set_options(result_parameters=[ParameterRepr("d_theta", parameter_name, "rad")])

super().__init__(qubits=qubits, backend=backend, analysis=analysis)
self.set_experiment_options(**kwargs)
Expand Down Expand Up @@ -135,7 +133,7 @@ def _default_transpile_options(cls) -> Options:

return options

def circuits(self, backend: Optional[Backend] = None) -> List[QuantumCircuit]:
def circuits(self) -> List[QuantumCircuit]:
opt = self.experiment_options

circs = list()
Expand Down
68 changes: 36 additions & 32 deletions qiskit_experiments/library/hamiltonian/heat_zx.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,21 @@ class ZXHeat(BatchHeatHelper):
ZX-type generator, a typical Hamiltonian implemented
by a cross resonance drive, which is a foundation of the CNOT gate.
The preparation circuit locks target qubit state along X-axis,
in which the state is insensitive to the controlled X rotation
imposed by the drive with the ZX-type generator.
The echo circuit refocuses ZX rotation to identity (II) then applies
a pi-pulse along the interrogated error axis. X error and Y error are
amplified outward the X-Y plane to draw a ping-pong pattern with the
amplified outward the X-Y plane to draw a ping-pong pattern with
state flip by the pi-pulse echo, while Z error is amplified outward
the X-Z plane in the same manner.
Measurement is projected onto Y-axis in this case.
Because the echoing axis are anti-commute with other Pauli terms,
errors in other axes are cancelled out to reduce rotation
in the interrogated axis.
Measurement is projected onto Y-axis in this setup.
Because the echoed axis are anti-commute with other Pauli terms,
errors in other axes are cancelled out to reduce rotation in the interrogated axis.
This enables to selectively amplify the Hamiltonian dynamics in the specific axis.
Note that we have always nonzero X rotation imparted by the significant ZX term,
the error along Y and Z axis are skewed by the nonzero commutator term.
This yields slight mismatch in the estimated coefficients with the generator Hamiltonian,
however this matters less when the expected magnitude of the error is small.
On the other hand, the error in the X axis is straightforward
because this is commute with the ZX term of the generator.
.. parsed-literal::
(xN)
Expand Down Expand Up @@ -80,7 +81,7 @@ class ZXHeat(BatchHeatHelper):
ZX(angle) evolution otherwise selective amplification doesn't work properly.
# section: see_also
HeatElement
qiskit_experiments.library.hamiltonian.HeatElement
# section: analysis_ref
:py:class:`HeatAnalysis`
Expand All @@ -94,7 +95,7 @@ def __init__(
qubits: Tuple[int, int],
error_axis: str,
backend: Optional[Backend] = None,
angle: Optional[float] = np.pi/2,
angle: Optional[float] = np.pi / 2,
):
"""Create new HEAT experiment for the entangler of ZX generator.
Expand All @@ -104,6 +105,9 @@ def __init__(
either one of "x", "y", "z".
backend: Optional, the backend to run the experiment on.
angle: Angle of controlled rotation, which defaults to pi/2.
Raises:
ValueError: When ``error_axis`` is not one of "x", "y", "z".
"""

amplification_exps = []
Expand All @@ -119,15 +123,15 @@ def __init__(
echo.rx(-angle, 1)

if error_axis == "x":
prep.rx(np.pi/2, 1)
prep.rx(np.pi / 2, 1)
echo.rx(np.pi, 1)
elif error_axis == "y":
prep.ry(np.pi/2, 1)
prep.ry(np.pi / 2, 1)
echo.ry(np.pi, 1)
elif error_axis == "z":
prep.ry(np.pi/2, 1)
prep.ry(np.pi / 2, 1)
echo.rz(np.pi, 1)
meas.rx(-np.pi/2, 1)
meas.rx(-np.pi / 2, 1)
else:
raise ValueError(f"Invalid error term {error_axis}.")

Expand All @@ -146,7 +150,7 @@ def __init__(
out_params=[f"A_I{error_axis.upper()}", f"A_Z{error_axis.upper()}"],
)

super(ZXHeat, self).__init__(
super().__init__(
heat_experiments=amplification_exps,
heat_analysis=analysis,
backend=backend,
Expand All @@ -157,16 +161,16 @@ class ZX90HeatXError(ZXHeat):
"""HEAT experiment for X error amplification for ZX(pi/2) Hamiltonian.
# section: see_also
ZXHeat
qiskit_experiments.library.hamiltonian.ZXHeat
"""

def __init__(self, qubits: [int, int], backend: Optional[Backend] = None):
def __init__(self, qubits: Tuple[int, int], backend: Optional[Backend] = None):
"""Create new experiment.
qubits: Index of control and target qubit, respectively.
backend: Optional, the backend to run the experiment on.
qubits: Index of control and target qubit, respectively.
backend: Optional, the backend to run the experiment on.
"""
super(ZX90HeatXError, self).__init__(
super().__init__(
qubits=qubits,
error_axis="x",
backend=backend,
Expand All @@ -178,37 +182,37 @@ class ZX90HeatYError(ZXHeat):
"""HEAT experiment for Y error amplification for ZX(pi/2) Hamiltonian.
# section: see_also
ZXHeat
qiskit_experiments.library.hamiltonian.ZXHeat
"""

def __init__(self, qubits: [int, int], backend: Optional[Backend] = None):
def __init__(self, qubits: Tuple[int, int], backend: Optional[Backend] = None):
"""Create new experiment.
qubits: Index of control and target qubit, respectively.
backend: Optional, the backend to run the experiment on.
qubits: Index of control and target qubit, respectively.
backend: Optional, the backend to run the experiment on.
"""
super(ZX90HeatYError, self).__init__(
super().__init__(
qubits=qubits,
error_axis="y",
backend=backend,
angle=np.pi/2,
angle=np.pi / 2,
)


class ZX90HeatZError(ZXHeat):
"""HEAT experiment for Z error amplification for ZX(pi/2) Hamiltonian.
# section: see_also
ZXHeat
qiskit_experiments.library.hamiltonian.ZXHeat
"""

def __init__(self, qubits: [int, int], backend: Optional[Backend] = None):
def __init__(self, qubits: Tuple[int, int], backend: Optional[Backend] = None):
"""Create new experiment.
qubits: Index of control and target qubit, respectively.
backend: Optional, the backend to run the experiment on.
qubits: Index of control and target qubit, respectively.
backend: Optional, the backend to run the experiment on.
"""
super(ZX90HeatZError, self).__init__(
super().__init__(
qubits=qubits,
error_axis="z",
backend=backend,
Expand Down
6 changes: 4 additions & 2 deletions releasenotes/notes/add-heat-experiment-047a73818407e733.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
features:
- |
New experiment module :mod:`qiskit_experiments.library.hamiltonian`
is added. This module contains experiments to characterize low level
has been added. This module collects experiments to characterize low level
system properties, such as device Hamiltonian.
- |
The `Hamiltonian Error Amplifying Tomography` (HEAT) experiment has been
added. This experiment consists of the base class
:class:`~qiskit_experiments.library.hamiltonian.BatchHeatHelper`
and :class:`~qiskit_experiments.library.hamiltonian.HeatElement`
for the experiment developers to implement HEAT experiment
for the experiment developers to implement own HEAT experiment
for arbitrary generator and for specific interrogated error axis.
This can be realized by designing proper initialization circuit,
echo sequence, and measurement axis against the interrogated error axis.
The HEAT experiment specific to the ZX-type generator
:class:`~qiskit_experiments.library.hamiltonian.ZXHeat` is also added
Expand Down
2 changes: 1 addition & 1 deletion test/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2022.
# (C) Copyright IBM 2021, 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
Expand Down
Loading

0 comments on commit d32444f

Please sign in to comment.