Skip to the content.

Bring Your Own Hamiltonian

Plug external quantum chemistry packages into the library — the built-in chemistry stack ships with empirical integrals for small molecules (H₂, H₂O, LiH), but every solver accepts externally computed data. This page maps out where to plug in, depending on what your external tool produces.

The library deliberately has no dependency on any chemistry package. Instead it exposes typed seams at every level of the chemistry pipeline:

Molecule geometry ──► Integrals ──► Fermionic Hamiltonian ──► Qubit (Pauli) Hamiltonian ──► VQE / QPE / Trotter evolution
      ▲                  ▲                  ▲                        ▲
  providers,        IntegralProvider   FermionHamiltonian     PauliHamiltonian
  XYZ/PDB/SMILES    (PySCF, Psi4…)     (OpenFermion-style)    (already mapped)

Which entry point do I need?

You have… Plug in at API
Molecular integrals from PySCF / Psi4 / NWChem Integral level IntegralProvider in SolverConfig
An FCIDUMP file (standard interchange format) File level Molecule.fromFciDumpFileTask
Second-quantized fermionic operators Fermion level FermionMapping.FermionHamiltonian + Jordan-Wigner / Bravyi-Kitaev
Already-mapped Pauli terms (e.g. OpenFermion / Qiskit Nature output) Pauli level TrotterSuzuki.PauliHamiltonianAdaptVqe.run, QPE, Trotter evolution
Molecule structures in external databases / formats Data level IMoleculeDatasetProvider, IGeometryProvider, XYZ/MOL2/PDB/SMILES parsers

1. Integral providers (PySCF, Psi4, NWChem, …)

GroundStateEnergy.estimateEnergy and the quantumChemistry builder accept a custom integral provider — a plain function, no interface ceremony:

open FSharp.Azure.Quantum.QuantumChemistry

// Molecule -> Result<MolecularIntegrals, string>
let myProvider : IntegralProvider =
    fun molecule ->
        // call your external package (pythonnet, subprocess, REST, file...)
        Ok {
            NumOrbitals = 2
            NumElectrons = 2
            NuclearRepulsion = 0.7137
            OneElectron = { NumOrbitals = 2; Integrals = h_pq }     // float[,]
            TwoElectron = { NumOrbitals = 2; Integrals = g_pqrs }   // float[,,,]
            ReferenceEnergy = Some hartreeFockEnergy
        }

let config =
    { Method = GroundStateMethod.VQE
      Backend = None                        // None = LocalBackend
      MaxIterations = 100
      Tolerance = 1e-6
      InitialParameters = None
      ProgressReporter = None
      ErrorMitigation = None
      IntegralProvider = Some myProvider }  // <-- your external integrals

let! result = GroundStateEnergy.estimateEnergy molecule config

Requirements for the integrals (see the full preconditions block in Solvers/Quantum/QuantumChemistry.fs):

Working example: examples/DrugDiscovery/PySCFIntegration.fsx implements a complete PySCF-backed provider via pythonnet, including basis-set selection and validation against the Hartree-Fock reference energy.

2. FCIDUMP files

Most quantum chemistry packages (Molpro, PySCF, Q-Chem, …) export FCIDUMP — use it as a zero-code interchange path:

let! result = Molecule.fromFciDumpFileTask "h2.fcidump" ct   // Task<Result<Molecule, QuantumError>>

Note: FCIDUMP files carry orbital/electron information but usually no 3D geometry, so the resulting Molecule has placeholder atoms. Use this path for energy calculations, not for geometry-dependent workflows. The quantumChemistry computation expression also accepts an FCIDUMP path directly.

3. Fermionic Hamiltonians (second quantization)

If your external tool produces creation/annihilation operator terms (OpenFermion’s FermionOperator, for example), build a FermionHamiltonian and map it to qubits with your choice of transform:

open System.Numerics
open FSharp.Azure.Quantum.QuantumChemistry.FermionMapping

let fermionH : FermionHamiltonian = {
    NumOrbitals = 4
    Terms = [
        { Coefficient = Complex(-1.2524, 0.0)
          Operators = [ { OrbitalIndex = 0; OperatorType = Creation }
                        { OrbitalIndex = 0; OperatorType = Annihilation } ] }
        // ... one- and two-body terms from your package
    ]
}

// Jordan-Wigner: simple, locality-preserving for 1D
let qubitH = JordanWigner.transform fermionH

// or Bravyi-Kitaev: lower gate depth for larger systems
let qubitH' = BravyiKitaev.transform fermionH

// Feed VQE/QAOA infrastructure
let problemH = toQaoaHamiltonian qubitH

4. Pauli Hamiltonians (already mapped)

If the external stack already did the fermion-to-qubit mapping, hand the Pauli sum directly to the algorithm layer via TrotterSuzuki.PauliHamiltonian:

open System.Numerics
open FSharp.Azure.Quantum.Algorithms

let term (ops: char[]) (coeff: float) : TrotterSuzuki.PauliString =
    { Operators = ops; Coefficient = Complex(coeff, 0.0) }

// H = -1.05 II + 0.39 ZI + 0.39 IZ - 0.01 ZZ + 0.18 XX  (H2, STO-3G, mapped)
let hamiltonian : TrotterSuzuki.PauliHamiltonian =
    { NumQubits = 2
      Terms = [ term [| 'I'; 'I' |] -1.05
                term [| 'Z'; 'I' |]  0.39
                term [| 'I'; 'Z' |]  0.39
                term [| 'Z'; 'Z' |] -0.01
                term [| 'X'; 'X' |]  0.18 ] }

Everything downstream consumes this type:

For small dense matrices there is also TrotterSuzuki.decomposeMatrixToPauli (and decomposeDiagonalMatrixToPauli), which computes the Pauli decomposition for you.

5. Molecule data and geometry providers

To source molecular structures (rather than Hamiltonians) from external systems, implement the provider interfaces in Data/ChemistryDataProviders.fs:

let mol = Molecule.fromProvider myDatasetProvider "caffeine"   // your database
let mol' = Molecule.fromXyzFileTask "conformer42.xyz" ct       // your files

Scale honestly

The built-in VQE/QPE path is validated on small molecules (H₂, H₂O, LiH) and capped at 20 qubits on the local simulator. “Bring your own Hamiltonian” does not remove that ceiling — it removes the accuracy ceiling (empirical vs research-grade integrals) and lets your external package do what it is good at (integrals, active-space selection, orbital localization) while this library does what it is good at (typed circuit construction, backend routing, error mitigation, Azure Quantum execution). For molecules beyond the qubit budget, reduce to an active space externally before handing over.

See also