"""Regular isometry module for quantum state preparation."""
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See LICENSE.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
from qiskit import QuantumCircuit, qasm3
from qiskit.circuit.library import StatePreparation as QiskitStatePreparation
from qiskit.compiler import transpile
from qiskit.quantum_info import Statevector
from qiskit.transpiler import PassManager
from qdk_chemistry.algorithms.state_preparation import StatePreparation
from qdk_chemistry.data import Circuit, Settings, Wavefunction
from qdk_chemistry.plugins.qiskit._interop.transpiler import (
MergeZBasisRotations,
RemoveZBasisOnZeroState,
SubstituteCliffordRz,
)
from qdk_chemistry.plugins.qiskit.conversion import create_statevector_from_wavefunction
from qdk_chemistry.utils import Logger
__all__ = ["RegularIsometryStatePreparation", "RegularIsometryStatePreparationSettings"]
[docs]
class RegularIsometryStatePreparationSettings(Settings):
"""Settings for RegularIsometryStatePreparation."""
[docs]
def __init__(self):
"""Initialize the RegularIsometryStatePreparationSettings."""
super().__init__()
self._set_default("basis_gates", "vector<string>", ["x", "y", "z", "cx", "cz", "id", "h", "s", "sdg", "rz"])
self._set_default("transpile", "bool", True)
self._set_default("transpile_optimization_level", "int", 0)
[docs]
class RegularIsometryStatePreparation(StatePreparation):
"""State preparation using a regular isometry approach.
This class implements the isometry-based state preparation proposed by
Matthias Christandl in arXiv:1501.06911 :cite:`Christandl2016`.
"""
[docs]
def __init__(self):
"""Initialize the RegularIsometryStatePreparation."""
Logger.trace_entering()
super().__init__()
self._settings = RegularIsometryStatePreparationSettings()
def _run_impl(self, wavefunction: Wavefunction) -> Circuit:
"""Create a quantum circuit that prepares the state using regular isometry.
Args:
wavefunction: Wavefunction to prepare state from
Returns:
A Circuit object containing a QASM string representation of the quantum circuit.
"""
Logger.trace_entering()
num_dets = wavefunction.size()
Logger.debug(f"Using {num_dets} determinants for state preparation")
# Create statevector from wavefunction
statevector_data = create_statevector_from_wavefunction(wavefunction, normalize=True)
n_qubits = int(statevector_data.shape[0]).bit_length() - 1
# Create the circuit
circuit = QuantumCircuit(n_qubits, name=f"regular_isometry_{num_dets}_det")
# Use the StatePreparation class which implements efficient decomposition
state_prep = QiskitStatePreparation(Statevector(statevector_data), normalize=True)
circuit.append(state_prep, range(n_qubits))
# Transpile the circuit if needed
basis_gates = self._settings.get("basis_gates")
do_transpile = self._settings.get("transpile")
if do_transpile and basis_gates:
opt_level = self._settings.get("transpile_optimization_level")
circuit = transpile(circuit, basis_gates=basis_gates, optimization_level=opt_level)
pass_manager = PassManager(
[
MergeZBasisRotations(),
RemoveZBasisOnZeroState(),
SubstituteCliffordRz(),
]
)
circuit = pass_manager.run(circuit)
return Circuit(qasm=qasm3.dumps(circuit), encoding="jordan-wigner")
[docs]
def name(self) -> str:
"""Return the name of the state preparation method."""
Logger.trace_entering()
return "qiskit_regular_isometry"