Skip to the content.

QDK Chemistry integration

qpubench models the Microsoft QDK quantum chemistry pipeline in src/qpubench/schemas/mirrors/microsoft_qdk.py. The schemas cover the full pipeline from molecular structure through SCF, active-space selection, Hamiltonian construction, qubit encoding, state preparation, QPE/IQPE phase estimation, and Azure Quantum resource estimation.

Computing model: ComputingModel.GATE_BASED (QPE/IQPE is an algorithmic technique on top of gate-based circuits — see QPEMethod, not a separate paradigm)


Pipeline overview

MoleculeStructureSpec
  └─ SCFRunConfig → SCFResult
       └─ OrbitalLocalizationConfig → OrbitalLocalizationResult
            └─ ActiveSpaceSelectionConfig → ActiveSpaceSelectionResult
                 └─ SCIWavefunctionSpec   (optional MACIS/ASCI multi-configuration)
                      └─ FermionicHamiltonianSpec
                           └─ QubitHamiltonianSpec
                                └─ StatePrepConfig → StatePrepCircuitResult
                                     └─ QPEConfig → QPEResult
                                          └─ ResourceEstimatorConfig → ResourceEstimationResult

All stages are captured in QChemPipelineSpec stored in QuantumResult.qchem_pipeline.


Molecular structure and SCF

from qpubench.schemas.mirrors.microsoft_qdk import (
    AtomSpec, MoleculeStructureSpec, CoordinateUnit,
    SCFRunConfig, SCFResult, SCFMethod,
)

# H2 at equilibrium
mol = MoleculeStructureSpec(
    atoms=[
        AtomSpec(symbol="H", x=0.0, y=0.0, z=0.0),
        AtomSpec(symbol="H", x=0.0, y=0.0, z=0.7414),
    ],
    charge=0,
    spin_multiplicity=1,
    units=CoordinateUnit.ANGSTROM,
    name="H2",
)

scf_config = SCFRunConfig(
    method=SCFMethod.RHF,
    basis="sto-3g",
    convergence_threshold=1e-9,
    max_iterations=200,
)

scf_result = SCFResult(
    hf_energy=-1.1175,
    num_electrons=2,
    num_alpha=1,
    num_beta=1,
    num_orbitals=2,
    orbital_energies=[-0.5785, 0.6709],
    converged=True,
    num_iterations=8,
)

Orbital localization and active space

from qpubench.schemas.mirrors.microsoft_qdk import (
    OrbitalLocalizationConfig, OrbitalLocalizationResult, OrbitalLocalizerType,
    OrbitalEntanglementEntropies,
    ActiveSpaceSelectionConfig, ActiveSpaceSelectionResult, ActiveSpaceSelectorType,
)

loc_config = OrbitalLocalizationConfig(
    localizer_type=OrbitalLocalizerType.MP2_NO,
    num_orbitals=4,
)

entropies = OrbitalEntanglementEntropies(
    num_orbitals=4,
    s1_entropies=[0.01, 0.62, 0.61, 0.02],        # single-orbital entanglement
    mutual_information=[0.0, 0.0, 0.0, 0.0,        # flattened 4×4; I(i,j)
                        0.0, 0.0, 0.98, 0.0,
                        0.0, 0.98, 0.0, 0.0,
                        0.0, 0.0, 0.0, 0.0],
)

loc_result = OrbitalLocalizationResult(
    localizer_type=OrbitalLocalizerType.MP2_NO,
    entropies=entropies,
    selected_orbital_indices=[1, 2],
)

as_config = ActiveSpaceSelectionConfig(
    selector_type=ActiveSpaceSelectorType.MP2_NO,
    num_active_electrons=2,
    num_active_orbitals=2,
)

as_result = ActiveSpaceSelectionResult(
    selector_type=ActiveSpaceSelectorType.MP2_NO,
    active_electrons=2,
    active_orbitals=2,
    orbital_indices=[1, 2],
    frozen_core_energy=-1.1175,
)

Fermionic and qubit Hamiltonians

from qpubench.schemas.mirrors.microsoft_qdk import (
    FermionicHamiltonianSpec, QubitHamiltonianSpec,
    PauliStringTerm, QubitEncodingType,
)

h_fermionic = FermionicHamiltonianSpec(
    num_orbitals=2,
    num_electrons=2,
    core_energy=-1.1175,
    one_body_integrals=[-0.5785, 0.0, 0.0, 0.6709],   # flattened 2×2
    two_body_integrals=[0.674, 0.0, 0.0, 0.674,        # flattened 2×2×2×2
                        0.0, 0.181, 0.181, 0.0, ...],
    schatten_norm=1.432,                                 # ‖H‖₁ for QPE timing
)

h_qubit = QubitHamiltonianSpec(
    encoding=QubitEncodingType.JORDAN_WIGNER,
    num_qubits=4,
    num_pauli_terms=15,
    pauli_terms=[
        PauliStringTerm(pauli_string="IIII", coefficient=-0.0988),
        PauliStringTerm(pauli_string="IIIZ",  coefficient=-0.2159),
        # ...
    ],
)

QPE / IQPE

from qpubench.schemas.mirrors.microsoft_qdk import (
    QPEConfig, QPEResult, QPEMethod,
    TimeEvolutionConfig, TimeEvolutionBuilderType,
    StatePrepConfig, StatePrepCircuitResult, StatePrepMethod,
)
import math

# State preparation
state_config = StatePrepConfig(
    method=StatePrepMethod.SPARSE_ISOMETRY_GF2X,
    num_determinants=4,
    target_fidelity=0.999,
)

state_result = StatePrepCircuitResult(
    method=StatePrepMethod.SPARSE_ISOMETRY_GF2X,
    circuit_qasm="OPENQASM 2.0; ...",
    num_cnots=12,
    circuit_depth=18,
    achieved_fidelity=0.9998,
)

# IQPE: 1 ancilla, sequential measurements
iqpe_config = QPEConfig(
    method=QPEMethod.ITERATIVE,
    evolution_time=math.pi / 1.432,   # T = π / ‖H‖₁
    num_bits=12,
    shots_per_bit=10,
    time_evolution=TimeEvolutionConfig(
        builder_type=TimeEvolutionBuilderType.SUZUKI_TROTTER,
        trotter_order=2,
        num_steps=6,
    ),
)

iqpe_result = QPEResult(
    raw_energy=-1.1373,
    bitstring_msb_first="110010011101",
    alias_branches=[-1.1373, -0.8821],
    error_mha=0.15,
    quantization_limit_mha=0.12,
    num_bits_used=12,
    evolution_time=math.pi / 1.432,
)

Resource estimation (Azure Quantum)

from qpubench.schemas.mirrors.microsoft_qdk import (
    ResourceEstimatorConfig, ResourceEstimationResult,
    ErrorBudgetPartition, QubitParamsType, QECScheme,
)

estimator_config = ResourceEstimatorConfig(
    qubit_params=QubitParamsType.GATE_NS_E4,
    qec_scheme=QECScheme.SURFACE_CODE,
    error_budget=ErrorBudgetPartition(
        logical_error=0.001,
        rotation_synthesis=0.0005,
        t_state_distillation=0.0005,
    ),
)

est_result = ResourceEstimationResult(
    num_physical_qubits=2847,
    runtime_s=0.043,
    t_gate_count=58_420,
    logical_qubits=38,
    code_distance=15,
    num_t_factories=4,
)

Model Hamiltonians

Use model Hamiltonians instead of a molecular structure for condensed-matter benchmarks:

from qpubench.schemas.mirrors.microsoft_qdk import (
    ModelHamiltonianSpec, ModelHamiltonianType,
    LatticeGraphSpec, LatticeTopology,
    IsingParams, HeisenbergParams, HubbardParams,
)

# Transverse-field Ising chain
ising = ModelHamiltonianSpec(
    hamiltonian_type=ModelHamiltonianType.ISING,
    lattice=LatticeGraphSpec(topology=LatticeTopology.CHAIN, num_sites=10),
    ising=IsingParams(J=1.0, h=0.5),
)

# Heisenberg XXX ring
heisenberg = ModelHamiltonianSpec(
    hamiltonian_type=ModelHamiltonianType.HEISENBERG,
    lattice=LatticeGraphSpec(topology=LatticeTopology.RING, num_sites=8),
    heisenberg=HeisenbergParams(Jx=1.0, Jy=1.0, Jz=1.0, h=0.0),
)

# Hubbard chain
hubbard = ModelHamiltonianSpec(
    hamiltonian_type=ModelHamiltonianType.HUBBARD,
    lattice=LatticeGraphSpec(topology=LatticeTopology.CHAIN, num_sites=6),
    hubbard=HubbardParams(t=1.0, U=4.0),
)

Only one parameter block (ising, heisenberg, hubbard, huckel, ppp) may be non-None; the validator enforces this.


Full pipeline record

from qpubench.schemas.mirrors.microsoft_qdk import QChemPipelineSpec
from qpubench.schemas.result import QuantumResult
from qpubench.schemas.primitives import ComputingModel

pipeline = QChemPipelineSpec(
    molecule=mol,
    scf_config=scf_config,
    scf_result=scf_result,
    active_space_result=as_result,
    fermionic_hamiltonian=h_fermionic,
    qubit_hamiltonian=h_qubit,
    state_prep_config=state_config,
    state_prep_result=state_result,
    qpe_config=iqpe_config,
    qpe_result=iqpe_result,
    resource_estimator_config=estimator_config,
    resource_estimation_result=est_result,
)

result = QuantumResult(
    computing_model=ComputingModel.GATE_BASED,
    qpe_result=iqpe_result,
    qchem_pipeline=pipeline,
)

Backends

from qpubench.schemas.backend import BackendSpec

BackendSpec.qdk_chemistry_simulator("qdk_sparse_state_simulator", num_qubits=20)
BackendSpec.azure_quantum("microsoft.estimator",
                          resource_id_ref="AZURE_RESOURCE_ID",
                          location_ref="AZURE_LOCATION")
BackendSpec.azure_quantum("quantinuum.hqs-lt-s1")   # Quantinuum H1 hardware