Controlled evolution circuit mapper
The ControlledEvolutionCircuitMapper algorithm in QDK/Chemistry converts a TimeEvolutionUnitary into a controlled quantum circuit.
Following QDK/Chemistry’s algorithm design principles, it takes a ControlledTimeEvolutionUnitary as input and produces a Circuit as output.
Overview
Controlled unitaries — operations of the form \(C\text{-}U\) that apply \(U\) to a target register conditioned on the state of a control qubit — are a building block in many quantum algorithms. Mathematically, for a single control qubit the controlled unitary acts as:
That is, the target register is left unchanged when the control is \(|0\rangle\) and \(U\) is applied when the control is \(|1\rangle\).
The ControlledEvolutionCircuitMapper synthesises these controlled operations from the abstract TimeEvolutionUnitary representation produced by a TimeEvolutionBuilder.
This is a core component of algorithms such as PhaseEstimation, which requires repeated controlled applications \(C\text{-}U^{2^k}\).
The mapper takes two inputs:
A
ControlledTimeEvolutionUnitary— which pairs aTimeEvolutionUnitarywith the control qubit indicesAn optional power parameter that controls how many times the unitary is repeated (\(U^{\text{power}}\))
The resulting Circuit implements the controlled unitary and can be executed by a CircuitExecutor.
Using the ControlledEvolutionCircuitMapper
Note
This algorithm is currently available only in the Python API.
This section demonstrates how to create, configure, and run the circuit mapper.
Input requirements
The ControlledEvolutionCircuitMapper requires:
- ControlledTimeEvolutionUnitary
A
ControlledTimeEvolutionUnitarywrapping aTimeEvolutionUnitaryand specifying which qubits serve as controls.
Creating a mapper
from qdk_chemistry.algorithms import create
# Create the default mapper (pauli_sequence)
mapper = create("controlled_evolution_circuit_mapper")
Configuring settings
# Configure the power of the controlled unitary
mapper = create("controlled_evolution_circuit_mapper", "pauli_sequence")
mapper.settings().set("power", 4)
Running the mapper
import numpy as np
from qdk_chemistry.algorithms import create
from qdk_chemistry.data import Structure
# 1. Setup molecule
coords = np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 1.4]])
symbols = ["H", "H"]
structure = Structure(coords, symbols=symbols)
# 2. SCF
scf_solver = create("scf_solver")
E_scf, wfn_scf = scf_solver.run(
structure, charge=0, spin_multiplicity=1, basis_or_guess="sto-3g"
)
# 3. Hamiltonian and qubit mapping
hamiltonian_constructor = create("hamiltonian_constructor")
hamiltonian = hamiltonian_constructor.run(wfn_scf.get_orbitals())
qubit_mapper = create("qubit_mapper", encoding="jordan-wigner")
qubit_ham = qubit_mapper.run(hamiltonian)
# 4. Build time evolution unitary
trotter = create("time_evolution_builder", "trotter", order=2)
evolution = trotter.run(qubit_ham, time=0.1)
# 5. Create a controlled version and map to a circuit
from qdk_chemistry.data import ControlledTimeEvolutionUnitary
controlled = ControlledTimeEvolutionUnitary(evolution, control_indices=[0])
mapper = create("controlled_evolution_circuit_mapper", "pauli_sequence")
circuit = mapper.run(controlled)
print("Controlled evolution circuit generated")
Available implementations
You can discover available implementations programmatically:
from qdk_chemistry.algorithms import registry
# List all registered controlled evolution circuit mapper implementations
implementations = registry.available("controlled_evolution_circuit_mapper")
print(implementations) # e.g. ['pauli_sequence']
Pauli sequence mapper
Factory name: "pauli_sequence" (default)
Given a time-evolution unitary expressed as a PauliProductFormulaContainer — a sequence of exponentiated Pauli terms \(e^{-i\theta_j P_j}\) — this mapper constructs a controlled version by:
Rotating each Pauli operator \(P_j\) into the Z basis
Entangling the target qubits with a CNOT ladder
Applying a controlled \(R_z(2\theta_j)\) rotation from the control qubit
Uncomputing the basis rotations and entangling operations
Note
The current implementation supports a single control qubit.
Settings
Setting |
Type |
Description |
|---|---|---|
|
int |
Number of times the unitary is repeated (\(U^{\text{power}}\)). Default is 1. |
Further reading
The above examples can be downloaded as a complete Python script.
PhaseEstimation: Uses the circuit mapper to build controlled-\(U\) operations
TimeEvolutionBuilder: Constructs the input unitaries
Settings: Configuration settings for algorithms
Factory Pattern: Understanding algorithm creation