"""QDK/Chemistry phase estimation builder abstractions."""
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See LICENSE.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
from abc import abstractmethod
from qdk_chemistry.algorithms.base import Algorithm, AlgorithmFactory
from qdk_chemistry.data import (
AlgorithmRef,
Circuit,
QubitOperator,
Settings,
)
__all__: list[str] = [
"IterativeQpeCircuitBuilder",
"QpeCircuitBuilder",
"QpeCircuitBuilderFactory",
"QpeCircuitBuilderSettings",
"StandardQpeCircuitBuilder",
]
[docs]
class QpeCircuitBuilderSettings(Settings):
"""Settings for the Phase Estimation Builder algorithm."""
[docs]
def __init__(self):
"""Initialize the settings for the Phase Estimation Builder.
Includes nested algorithm references for the evolution builder
and the circuit mapper used to construct phase estimation circuits.
"""
super().__init__()
self._set_default("num_bits", "int", -1, "The number of phase bits to estimate.")
self._set_default(
"unitary_builder",
"algorithm_ref",
AlgorithmRef("hamiltonian_unitary_builder", "trotter"),
)
self._set_default(
"controlled_circuit_mapper",
"algorithm_ref",
AlgorithmRef("controlled_circuit_mapper", "pauli_sequence"),
)
[docs]
class QpeCircuitBuilder(Algorithm):
"""Abstract base class for phase estimation circuit builders."""
[docs]
def __init__(
self,
num_bits: int = -1,
unitary_builder: AlgorithmRef | None = None,
controlled_circuit_mapper: AlgorithmRef | None = None,
):
"""Initialize the QpeCircuitBuilder with default settings.
Args:
num_bits: The number of phase bits to estimate. Default to -1; user needs to set a valid value.
unitary_builder: Optional algorithm reference for the unitary builder.
controlled_circuit_mapper: Optional algorithm reference for the controlled circuit mapper.
"""
super().__init__()
self._settings = QpeCircuitBuilderSettings()
self._settings.set("num_bits", num_bits)
if unitary_builder is not None:
self._settings.set("unitary_builder", unitary_builder)
if controlled_circuit_mapper is not None:
self._settings.set("controlled_circuit_mapper", controlled_circuit_mapper)
[docs]
def type_name(self) -> str:
"""Return the algorithm type name as qpe_circuit_builder."""
return "qpe_circuit_builder"
@abstractmethod
def _run_impl(
self,
state_preparation: Circuit,
qubit_hamiltonian: QubitOperator,
) -> list[Circuit]:
"""Build phase estimation circuits.
Args:
state_preparation: The circuit that prepares the initial state.
qubit_hamiltonian: The qubit Hamiltonian for which to build circuits.
Returns:
A list of quantum circuits for phase estimation.
"""
def _create_controlled_circuit(
self,
qubit_hamiltonian: QubitOperator,
power: int,
) -> tuple[Circuit, int]:
r"""Create the controlled circuit for the given Hamiltonian and power.
Sets the ``power`` on the unitary builder so it produces :math:`U^{\\text{power}}`
according to its ``power_strategy``, then maps the result to a controlled circuit.
Args:
qubit_hamiltonian: The qubit Hamiltonian to evolve under.
power: The power to which the unitary should be raised.
Returns:
A tuple of (circuit, num_ancilla_qubits) where circuit implements
controlled-:math:`U^{\\text{power}}` and num_ancilla_qubits is the number
of ancilla qubits used by the unitary beyond the system qubits.
"""
unitary_builder = self._create_nested("unitary_builder")
unitary_builder.settings().update("power", power)
unitary_rep = unitary_builder.run(qubit_hamiltonian)
num_ancilla_qubits = unitary_rep.get_num_qubits() - qubit_hamiltonian.num_qubits
circuit_mapper = self._create_nested("controlled_circuit_mapper")
circuit_mapper.settings().update("control_indices", [0])
circuit = circuit_mapper.run(unitary_rep)
return circuit, num_ancilla_qubits
[docs]
class QpeCircuitBuilderFactory(AlgorithmFactory):
"""Factory class for creating QpeCircuitBuilder instances."""
[docs]
def __init__(self):
"""Initialize the QpeCircuitBuilderFactory."""
super().__init__()
[docs]
def algorithm_type_name(self) -> str:
"""Return the algorithm type name as qpe_circuit_builder."""
return "qpe_circuit_builder"
[docs]
def default_algorithm_name(self) -> str:
"""Return qdk_iterative as default algorithm name."""
return "qdk_iterative"
[docs]
class IterativeQpeCircuitBuilder(QpeCircuitBuilder):
"""Abstract base class for iterative phase estimation circuit builders.
Serves as a type-checking abstraction for implementations of the iterative
(Kitaev-style) quantum phase estimation algorithm.
"""
[docs]
class StandardQpeCircuitBuilder(QpeCircuitBuilder):
"""Abstract base class for standard (QFT-based) phase estimation circuit builders.
Serves as a type-checking abstraction for implementations of the standard
(non-iterative) quantum phase estimation algorithm using QFT.
"""