QpeResult

The QpeResult class in QDK/Chemistry represents the outcome of a quantum phase estimation calculation. It encapsulates the measured phase, reconstructed energy, alias candidates, and measurement metadata, providing a complete record of a QPE experiment.

Overview

Quantum phase estimation measures a phase fraction \(\phi \in [0, 1)\) that encodes an eigenvalue \(E\) of the target Hamiltonian. The relationship between phase and energy depends on the evolution time \(t\):

\[E = \frac{2\pi\phi}{t}\]

However, because the phase is periodic, the measured \(\phi\) is only unique modulo \(2\pi / t\). This means multiple energy values — called aliases — can produce the same measured phase. The QpeResult class handles this ambiguity automatically by computing all alias candidates and optionally resolving to the physically correct energy using a reference value.

QpeResult is the output of the PhaseEstimation algorithm and supports full serialization to JSON and HDF5 formats. For details on how different QPE implementations (IQPE, standard QFT-based) populate this result, see the PhaseEstimation algorithm documentation.

Properties

The QpeResult stores the following information:

Property

Type

Description

method

str

Algorithm identifier (e.g., "iterative" for IQPE or "qiskit_standard" for standard QPE).

evolution_time

float

Time parameter \(t\) used in the evolution \(U = e^{-iHt}\).

phase_fraction

float

Raw measured phase \(\phi \in [0, 1)\).

phase_angle

float

Raw phase angle in radians: \(2\pi\phi\).

canonical_phase_fraction

float

Alias-resolved phase fraction. Equals phase_fraction when no alias resolution is performed.

canonical_phase_angle

float

Alias-resolved phase angle in radians.

raw_energy

float

Energy computed directly from the raw phase: \(E = 2\pi\phi / t\).

branching

tuple[float, …]

All alias energy candidates \(E + k \cdot 2\pi/t\) for a range of integer shifts \(k\).

resolved_energy

float | None

The alias candidate closest to the reference energy, or None if no reference was provided.

bits_msb_first

tuple[int, …] | None

Measured phase bits ordered from most significant to least significant. Available for IQPE; may be None for other methods.

bitstring_msb_first

str | None

Binary string representation of the measured phase (e.g., "0110110010").

metadata

dict | None

Caller-defined metadata for provenance tracking (e.g., molecule name, basis set, reference energy).

Alias resolution

Phase estimation measures a phase \(\phi \in [0, 1)\), but the underlying energy eigenvalue can be negative, positive, or arbitrarily large. Different energy values that differ by integer multiples of \(2\pi / t\) all map to the same phase.

The alias resolution algorithm works as follows:

  1. Compute the raw energy: \(E_{\text{raw}} = 2\pi\phi / t\) where the angle is mapped to \((-\pi, \pi]\)

  2. Enumerate alias candidates: \(E_k = E_{\text{raw}} + k \cdot 2\pi/t\) for each \(k\) in the branch shift range (default: \(k \in \{-2, -1, 0, 1, 2\}\))

  3. Include negative reflections: \(-E_k\) for symmetry

  4. If a reference energy is provided, select the candidate closest to the reference as resolved_energy

The branch shift range can be customized via the branch_shifts parameter in from_phase_fraction().

Tip

A good choice for reference_energy is the energy from a classical multi-configuration calculation (e.g., CASCI), which is typically close to the true eigenvalue.

Construction

QpeResult objects are typically created by the PhaseEstimation algorithm. They can also be constructed manually from a measured phase fraction using the from_phase_fraction() class method:

from qdk_chemistry.data import QpeResult

# Construct a QpeResult from a measured phase fraction
result = QpeResult.from_phase_fraction(
    method="iterative",
    phase_fraction=0.423828125,
    evolution_time=0.1,
    bits_msb_first=(0, 1, 1, 0, 1, 1, 0, 0, 1, 0),
    bitstring_msb_first="0110110010",
    reference_energy=-1.137,
)

Inspecting results

# Inspect the result
print(f"Method: {result.method}")
print(f"Phase fraction: {result.phase_fraction:.6f}")
print(f"Phase angle: {result.phase_angle:.6f} rad")
print(f"Raw energy: {result.raw_energy:.8f} Ha")
print(f"Alias candidates: {result.branching}")
print(f"Resolved energy: {result.resolved_energy:.8f} Ha")
print(f"Measured bits: {result.bits_msb_first}")

# Full summary
print(result.get_summary())

Working with aliases

# Construct without a reference energy — no alias resolution
result_no_ref = QpeResult.from_phase_fraction(
    method="iterative",
    phase_fraction=0.423828125,
    evolution_time=0.1,
)

# All alias candidates are available in the branching tuple
for i, energy in enumerate(result_no_ref.branching):
    print(f"  Candidate {i}: {energy:.6f} Ha")

# Resolve later using a reference energy
from qdk_chemistry.utils.phase import resolve_energy_aliases

resolved = resolve_energy_aliases(
    result_no_ref.raw_energy,
    evolution_time=0.1,
    reference_energy=-1.137,
)
print(f"Resolved energy: {resolved:.8f} Ha")

Serialization

QpeResult supports the same serialization formats as other QDK/Chemistry data classes:

import os
import tempfile

tmpdir = tempfile.mkdtemp()

# Save to JSON
result.to_json_file(os.path.join(tmpdir, "result.qpe_result.json"))

# Load from JSON
loaded = QpeResult.from_json_file(os.path.join(tmpdir, "result.qpe_result.json"))

# Save to HDF5
result.to_hdf5_file(os.path.join(tmpdir, "result.qpe_result.h5"))

# Load from HDF5
loaded_h5 = QpeResult.from_hdf5_file(os.path.join(tmpdir, "result.qpe_result.h5"))

Further reading

  • The above examples can be downloaded as a complete Python script.

  • PhaseEstimation: Phase estimation algorithms

  • TimeEvolutionBuilder: Hamiltonian simulation methods

  • Serialization: Data persistence formats

  • See the examples/qpe_stretched_n2.ipynb notebook for an end-to-end QPE workflow