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 \(\varphi \in [0, 1)\) that encodes an eigenvalue \(E\) of the target Hamiltonian. The relationship between the measured phase and energy depends on the type of unitary being phase-estimated.

QDK/Chemistry uses a unified factory method from_phase_fraction() that accepts a callable eigenvalue_from_phase mapping the measured phase to the Hamiltonian eigenvalue. Each unitary container provides this mapping as an instance method.

Time evolution

When QPE acts on \(U = e^{-iHt}\), the eigenvalues are \(e^{-iEt}\) and the energy is recovered via eigenvalue_from_phase():

\[E = \frac{2\pi\varphi'}{t}\]

where \(\varphi' \in (-1/2, 1/2]\) is the measured phase fraction wrapped from \([0, 1)\) into \((-1/2, 1/2]\).

Qubitization

When QPE acts on the qubitization walk operator \(W\), the eigenvalues are \(e^{\pm i \arccos(E/\lambda)}\) and the energy is recovered via eigenvalue_from_phase():

\[E = \lambda \cos(2\pi\varphi)\]

where \(\lambda = \sum_j |\alpha_j|\) is the 1-norm of the Hamiltonian coefficients.

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).

phase_fraction

float

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

phase_angle

float

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

canonical_phase_fraction

float

Alias-resolved phase fraction. Equals phase_fraction when no alias resolution is performed (e.g., qubitization).

canonical_phase_angle

float

Alias-resolved phase angle in radians.

raw_energy

float

Energy computed from the measured phase via the container’s eigenvalue_from_phase method.

branching

tuple[float, …]

Energy candidates. For the unified from_phase_fraction factory, this is a single-element tuple containing raw_energy.

resolved_energy

float | None

Reserved for alias resolution (currently None when using from_phase_fraction).

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

Alias resolution is relevant for time-evolution-based QPE (Trotter) where the phase is periodic. It is not needed for qubitization because the cosine mapping is injective over the measurable range.

Phase estimation measures a phase \(\varphi \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.

Note

The current from_phase_fraction factory does not perform alias resolution automatically. Alias resolution is the responsibility of the calling algorithm when needed.

Construction

QpeResult objects are typically created by the PhaseEstimation algorithm. They can also be constructed manually using from_phase_fraction(), passing container.eigenvalue_from_phase as the phase-to-energy mapping.

Time evolution example


from qdk_chemistry.algorithms import create
from qdk_chemistry.data import QpeResult, QubitOperator

# Time-evolution QPE: U = e^{-iHt}, eigenvalue_from_phase wraps the angle.
hamiltonian = QubitOperator(
    pauli_strings=["ZI", "IZ", "XX"], coefficients=[0.5, -0.3, 0.2]
)
evolution_time = 0.1

builder = create("hamiltonian_unitary_builder", "trotter", time=evolution_time)
unitary = builder.run(hamiltonian)
container = unitary.get_container()

result = QpeResult.from_phase_fraction(
    method="iterative",
    phase_fraction=0.423828125,
    eigenvalue_from_phase=container.eigenvalue_from_phase,
    bits_msb_first=(0, 1, 1, 0, 1, 1, 0, 0, 1, 0),
    bitstring_msb_first="0110110010",
)

Qubitization example


from qdk_chemistry.algorithms import create
from qdk_chemistry.data import QpeResult, QubitOperator

# Qubitization QPE: W = walk operator, E = lambda * cos(2*pi*phi).
hamiltonian = QubitOperator(
    pauli_strings=["ZI", "IZ", "XX"], coefficients=[0.5, -0.3, 0.2]
)

builder = create("hamiltonian_unitary_builder", "lcu", quantum_walk=True)
unitary = builder.run(hamiltonian)
walk_container = unitary.get_container()

result_qubitization = QpeResult.from_phase_fraction(
    method="qubitization_qpe",
    phase_fraction=0.25,
    eigenvalue_from_phase=walk_container.eigenvalue_from_phase,
    bits_msb_first=(0, 1, 0, 0),
    bitstring_msb_first="0100",
)

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"Measured bits: {result.bits_msb_first}")

# Full summary
print(result.get_summary())

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