What’s New in Version 2.2
Version 2.2 changes several numerical and packaging behaviors; see Behavior Changes.
Command-Line and MCP Interfaces
The base package installs the qc command-line interface. Its command groups
run algorithms, inspect data files, manage projects, perform unit conversions,
and query the algorithm registry. Algorithm commands accept --cache,
--remote, and --remote-config. --dry-run displays the supplied
parameters without executing the command.
The mcp extra installs the dependencies required by qcmcp:
pip install 'qdk-chemistry[mcp]'
The MCP server exposes the same project and algorithm operations as structured
tools. It uses stdio by default and also supports streamable HTTP. File-producing
tools report whether output was created, already existed, or failed. MCP Apps
visualization tools are registered when qsharp_widgets is installed.
The repository contains a Copilot plugin with skills and MCP configuration:
qc plugin install qdk-chemistry@qdk-chemistry --target-dir .
The command deploys the plugin into the current workspace. See Working with AI Assistants.
Remote Execution and Caching
Algorithms returned by create() accept
remote and cache arguments on run(). Serializable arguments,
settings, and results are transferred through a registered remote backend.
Supported values include QDK/Chemistry data classes,
AlgorithmRef, NumPy arrays, scalar values, and
lists or tuples of those values. Unsupported values raise TypeError before
submission.
The built-in "local" backend runs the serialized request in a subprocess on
the same machine:
structure = Structure([[0.0, 0.0, 0.0], [0.0, 0.0, 1.4]], [1, 1])
energy, wavefunction = create("scf_solver").run(
structure,
charge=0,
spin_multiplicity=1,
basis_or_guess="sto-3g",
remote="local",
cache="./cache",
)
Passing a path as cache creates a
FolderCache. Completed entries are
returned without resubmission, and an in-flight remote entry resumes polling
instead of starting a duplicate job. force_rerun=True bypasses the lookup.
A cache shared with the compute node must be configured with is_shared=True.
Run hashes do not include the QDK/Chemistry version. Do not reuse cache entries across releases when algorithm behavior has changed. In particular, clear pre-2.2 entries for calculations that use effective core potentials.
Remote and cache backends can be registered by plugins through
PluginRegistrar. See
Implementing a remote backend for an SSH
example.
Microsoft Discovery
The discovery extra installs the Microsoft Discovery backend:
pip install 'qdk-chemistry[discovery]'
The backend submits a containerized tool invocation and transfers files through
Azure Blob Storage or a shared cache. Workspace, project, tool, node-pool,
container, storage, and authentication settings can be supplied directly or
through QDK_DISCOVERY_* environment variables.
Algorithm Components
Unary-iteration phase estimation
phase_estimation / qdk_unary builds an arbitrary-length chain of
qubitized-walk queries. The phase register uses a cosine window, and
num_queries need not be a power of two.
The walk spectrum contains conjugate branches
\(e^{\pm i\arccos(E/\lambda)}\). The result stores both energy candidates
in branching; resolve_positive_branch selects resolved_energy. The
default selects the non-positive branch used for ground-state calculations.
This implementation requires a quantum_walk unitary builder. For execution,
it also requires Q# state preparation and the qdk_sparse_state_simulator
executor because its recursive Q# operation does not lower to QIR. The circuit
retains a Q# representation and can still be passed to
estimate().
Binary encoding for sparse isometry
Sparse-isometry state preparation now has a binary_encoding setting. The
standard path reduces the determinant-support matrix over
\(\mathrm{GF}(2)\) and loads amplitudes on the remaining rows. When
\(\lceil\log_2 d\rceil\) is smaller than that width, binary encoding maps
the \(d\) determinants one-to-one into the basis states of the smaller
register.
The lookup circuit adds CCZ operations and may allocate ancilla qubits, so a
smaller amplitude-loading register does not imply a smaller complete circuit.
measurement_based_uncompute replaces Toffoli-based uncomputation with
mid-circuit measurement and feedforward and therefore requires an adaptive
target profile. See State preparation.
Controlled-SWAP circuit mapping
controlled_circuit_mapper / cswap_pauli_sequence implements controlled
time evolution without controlling every gate in the product formula. For an
\(n\)-qubit system it uses an additional \(n\)-qubit vacuum register
and two layers of \(n\) controlled-SWAP gates.
The mapper applies to particle-conserving Hamiltonians. The vacuum must remain
an eigenstate of the grouped evolution; the mapper computes and cancels the vacuum’s
phase. term_grouper / vacuum_annihilating keeps the Pauli cancellation
partners from each fermionic term contiguous. The mapper rejects an ordering
that leaks amplitude from the vacuum.
Amplitude amplification
amplitude_amplification / qdk_base applies a configurable number of
amplification rounds to a state-preparation circuit and a marking oracle. Each
round reflects about the marked subspace and the prepared state.
The registered amplitude_amplification_oracle / qdk_qpe_subspace oracle
marks phase-estimation bins whose energy is at least energy_lower_bound.
It is an exact reflection only when the relevant eigenphases lie on
phase-register bins.
Effective Hamiltonian interface
The new effective_hamiltonian_constructor algorithm type defines the
interface for downfolding a Hamiltonian onto target orbitals. It accepts a
reference Wavefunction, a full-window
Hamiltonian, and target indices. No implementation
ships in this release.
Orbitals, Analysis, and Cube Generation
orbital_localizer / qdk_gauge_fixing fixes the rotational freedom
within occupation-degenerate natural-orbital blocks. It first anchors each
block to the atomic-orbital basis, then performs capped coordinate-descent
sweeps that reduce
\(\lambda = \sum_\ell |h_\ell|\) from the anchored gauge. Anchoring can
raise \(\lambda\) relative to the input orientation, so the final value is
not guaranteed to be below the input value.
The norm excludes the separate core-energy constant and is evaluated before
post-mapping tapering. It is invariant across linear fermion-to-qubit encodings,
where each Majorana monomial maps to one Pauli word up to phase. Each objective
evaluation performs an integral transformation and a qubit mapping. Run
qdk_natural_orbitals before gauge fixing.
orbital_localizer / qdk_active_space_qio performs gradient-free Jacobi
sweeps that reduce the sum of single-orbital entropies within a fixed active
space. It rotates the input density matrices but does not reoptimize the
correlated wavefunction.
Both new localizers return transformed orbitals and rotated active-space 1-RDM data; the QIO result does not carry a rotated 2-RDM. See Orbital localization.
The new population_analyzer type provides Mulliken electron populations
per atom, or site occupations for model orbitals, through native "qdk" and
"pyscf" implementations.
compute_s_squared() evaluates
\(\langle\hat{S}^2\rangle\).
generate_cubefiles_from_orbitals() evaluates
orbitals in process, supporting spherical and Cartesian basis sets without a
third-party quantum chemistry package. The "pyscf" backend remains
available for comparison.
Molecular QPE Tutorial
Ground-state molecular energies with quantum phase estimation follows stretched N2 from molecular input through active-space selection, qubit mapping, trial-state preparation, and iterative phase estimation. It includes executable scripts and three notebooks and does not require PySCF.
The propagator and Hamiltonian-simulation interfaces introduced in 2.0 are also documented in Propagator and Hamiltonian simulation.
Platforms and Packaging
Wheels are built for Linux x86-64 and Arm64, macOS Arm64, Windows x86-64, and Windows Arm64. Windows x86-64 supports Python 3.10 and later; Windows Arm64 supports Python 3.11 and later.
Native Windows has the following restrictions:
PySCF is unavailable because it publishes no Windows wheels.
On Windows Arm64,
mcpis omitted fromallandtestbecausecryptographypublishes no native wheel. An explicitmcpinstallation may require an Arm64 Rust toolchain, MSVC C/C++ build tools, and Arm64 OpenSSL development libraries.Qiskit, PennyLane, RDKit, and the Microsoft Discovery backend are unavailable on Windows Arm64 through the standard extras.
QDK/Chemistry OpenMP regions are disabled on Windows. Vendor libraries may still use their own threading.
Other packaging and build changes:
jupyterno longer includesplugins.Source builds and CI use Libint2 2.13.1.
A BLIS/libFLAME symbol collision in Linux wheel builds is fixed.
See the installation instructions for the complete extras and platform matrix.
Behavior Changes
Sparse-isometry name
The state_prep implementation "sparse_isometry_gf2x" is renamed
"sparse_isometry". The old name remains available and emits a
DeprecationWarning.
ECP handling
Effective nuclear charges now determine SCF electron counts, nuclear repulsion energies, and Hamiltonian core energies for systems with effective core potentials. ECP assignments are keyed by atom rather than element. Recompute affected results and clear pre-2.2 cache entries before doing so.
Orbital occupations
When a stored one-particle RDM does not match its determinant,
StateVectorContainer reports natural occupation
numbers obtained by diagonalizing the RDM rather than integer determinant
occupations. For a non-natural orbital basis these eigenvalues are not diagonal
populations of the stored orbitals.
Cube generation
Orbital cube generation defaults to backend="native" instead of
"pyscf". Default labels are zero-based: orbital 0 now writes
orbital_0000.cube instead of orbital_0001.cube.
Registration
Duplicate algorithm, algorithm-type, data-class, remote-backend, and
cache-backend registrations now raise
DuplicateRegistrationError and preserve the
existing registration.
Custom DataClass subclasses must declare their wire
identifier with a static data_type_name() method. Replace the former
_data_type_name class attribute before registering the class through a
plugin.
Nested BLAS threading
For linked BLAS libraries with runtime thread control, QDK/Chemistry restricts the library to one thread inside GauXC-backed SCF, gradient, and response operations. Nested BLAS threading could previously cause oversubscription or wrong results for some backends. Other BLAS libraries emit guidance for setting thread limits externally. Recompute pre-2.2 results if they showed thread-dependent numerical behavior.
Bug Fixes
Importing
qdk_chemistryno longer emits theMP2NaturalOrbitalLocalizerdeprecation message. Explicitly requestingqdk_mp2_natural_orbitalsstill warns.JSON deserialization preserves derived orbital types.
Cache plugin discovery failures are logged instead of discarded.
The controlled-IQPE tutorial diagram renders unitary powers as superscripts.