Evolution circuit builder

The EvolutionCircuitBuilder is an abstract base class that defines the interface for constructing time-evolution circuits. It serves as the central component that orchestrates circuit synthesis by composing a HamiltonianUnitaryBuilder (to construct the time-evolution unitary) with a CircuitMapper (to compile the unitary into a quantum circuit).

The EvolutionCircuitBuilder mirrors the role of QpeCircuitBuilder for phase estimation: it produces a Circuit suitable for resource estimation or further analysis without requiring a simulator backend.

Overview

Evolution circuit builders are responsible for:

  1. Composing circuits from state preparation and time-evolution unitaries

  2. Generating strategy-specific circuits (e.g., Euler stepping with configurable propagators and unitary builders)

The EvolutionCircuitBuilder abstract class provides the common interface, while concrete implementations handle variant-specific details (e.g., Euler stepping with Magnus propagation).

Use EvolutionCircuitBuilder

Note

This algorithm is currently available only in the Python API.

This section demonstrates how to create, configure, and run an evolution circuit builder. The run method returns a Circuit containing the constructed state-prep + evolution circuit.

Input requirements

The EvolutionCircuitBuilder requires the following inputs:

TimeDependentQubitHamiltonian

A TimeDependentQubitHamiltonian specifying the time-evolution schedule. For static Hamiltonians, use DrivenQubitHamiltonian with a constant drive lambda t: 1.0.

State preparation circuit

A Circuit that prepares the initial state. Use identity_state_prep() for the trivial \(|0\rangle^{\otimes n}\) initial state.

The EvolutionCircuitBuilderSettings class defines the general configuration parameters shared by all evolution circuit builders.

Setting

Type

Description

evolution_builder

AlgorithmRef

Reference to the algorithm that constructs the time-evolution unitary. Default: "hamiltonian_unitary_builder" with method "trotter".

circuit_mapper

AlgorithmRef

Reference to the algorithm that compiles the unitary to a quantum circuit. Default: "circuit_mapper" with method "pauli_sequence".

propagator

AlgorithmRef

Reference to the propagator that evaluates the effective Hamiltonian over each time step. Default: "propagator" with method "magnus".

total_time

float

Total evolution time \(T\). Default: 1.0.

dt

float

Time step for evolution discretization. Each step is passed to the propagator. Default: 0.0 (invalid; user must set).

Once configured, the builder can be executed:


# 1. Define the Ising model on a small lattice with a sinusoidal drive
import numpy as np
from qdk_chemistry.algorithms import create
from qdk_chemistry.algorithms.state_preparation import identity_state_prep
from qdk_chemistry.data import AlgorithmRef, DrivenQubitHamiltonian, LatticeGraph
from qdk_chemistry.utils.model_hamiltonians import create_ising_hamiltonian

lattice = LatticeGraph.chain(4)
h0 = create_ising_hamiltonian(lattice, j=1.0, h=0.0)  # ZZ coupling
h1 = create_ising_hamiltonian(lattice, j=0.0, h=0.5)  # Transverse X field

# Sinusoidal drive → time-dependent Hamiltonian: H(t) = H0 + sin(2πt)·H1
td_hamiltonian = DrivenQubitHamiltonian(h0, h1, drive=lambda t: np.sin(2 * np.pi * t))

# 2. Configure the builder
evolution_builder = AlgorithmRef(
    "hamiltonian_unitary_builder", "trotter", order=4, num_divisions=2
)
propagator = AlgorithmRef("propagator", "magnus", order=1)

circuit_builder = create(
    "evolution_circuit_builder",
    "euler",
    evolution_builder=evolution_builder,
    propagator=propagator,
    total_time=1.0,
    dt=0.1,
)

# 3. Build the circuit (state-prep + evolution) without executing
state_prep = identity_state_prep(num_qubits=td_hamiltonian.num_qubits)
circuit = circuit_builder.run(td_hamiltonian, state_prep)

print(f"Circuit has QIR: {circuit.get_qir() is not None}")

# 4. Use for quantum resource estimation
app = circuit.get_qre_application()
print(f"QRE application created: {app is not None}")

Available Implementations

Euler Evolution Circuit Builder

Class: EulerEvolutionCircuitBuilder

Factory name: "euler"

Divides \([0, T]\) into Euler steps of size dt. At each step, the configured propagator (default: Magnus order-1) evaluates the effective Hamiltonian and the evolution builder constructs the time-evolution unitary.

The default propagator (magnus) computes the Magnus-expanded Hamiltonian over each interval, giving second-order global accuracy for smooth drives. Other propagators can be substituted via the propagator setting.

Usage example:

from qdk_chemistry.algorithms import create
from qdk_chemistry.data import AlgorithmRef

# Create an Euler evolution circuit builder.
# The propagator evaluates the effective Hamiltonian over each dt interval,
# and the evolution builder constructs the unitary with `num_divisions`
# subdivisions within that interval.
evolution_builder = AlgorithmRef(
    "hamiltonian_unitary_builder", "trotter", order=4, num_divisions=2
)
propagator = AlgorithmRef("propagator", "magnus", order=1)

circuit_builder = create(
    "evolution_circuit_builder",
    "euler",
    evolution_builder=evolution_builder,
    propagator=propagator,
    total_time=1.0,
    dt=1.0,  # single Euler step = full time
)

Circuit Composition Details

The evolution circuit is built by composing:

  1. State Preparation — Prepares the initial quantum state on the system register

  2. time-evolution Unitaries — Applies the time-evolution unitary for each step obtained from the evolution builder

To accomplish this, the EvolutionCircuitBuilder maintains three key nested algorithm references:

Nested Algorithm 1: Propagator

Reference setting: "propagator"

Default: AlgorithmRef to "propagator" with method "magnus"

The propagator evaluates the effective Hamiltonian over each time interval \([t, t+\mathrm{d}t]\). The default Magnus propagator computes \(H_\text{eff} = H_0 + \bar{f}\,H_1\) where \(\bar{f}\) is the time-averaged drive.

Nested Algorithm 2: Evolution Builder

Reference setting: "evolution_builder"

Default: AlgorithmRef to "hamiltonian_unitary_builder" with method "trotter"

The evolution builder (typically HamiltonianUnitaryBuilder) produces a UnitaryRepresentation of the time-evolution operator from a QubitOperator.

Nested Algorithm 3: Circuit Mapper

Reference setting: "circuit_mapper"

Default: AlgorithmRef to "circuit_mapper" with method "pauli_sequence"

The circuit mapper (see CircuitMapper) converts the UnitaryRepresentation into an executable Circuit.

Further Reading