.. _release-v2.1.0: ========================== What's New in Version 2.1 ========================== Version 2.1 adds geometry optimization as a first-class algorithm type, isolates the vendored Q# utilities in a dedicated context so that importing QDK/Chemistry no longer mutates global interpreter state, and corrects the phase-to-energy convention used when phase estimation runs on a time-evolution unitary. There are no breaking API changes relative to :ref:`2.0 `, but the phase-convention fix changes the *numerical* results of time-evolution :term:`QPE`; see :ref:`Time-evolution phase convention `. .. contents:: On this page :local: :depth: 1 Highlights ========== - **Geometry optimization.** A new ``geometry_optimizer`` algorithm type relaxes molecular structures on top of the nuclear derivative calculators introduced in 2.0, with a geomeTRIC-backed implementation shipped as an optional plugin. - **Isolated Q# context.** The vendored Q# utilities load into a private ``qdk.Context`` instead of the global ``qsharp`` interpreter, and four helpers in :mod:`qdk_chemistry.utils.qsharp` expose that context for user-defined Q# operations. - **Corrected time-evolution phase convention.** Energies recovered from :math:`U = e^{-iHt}` now use :math:`E = -\theta / t`, and the ``bits_msb_first`` field of :class:`~qdk_chemistry.data.QpeResult` from iterative :term:`QPE` is genuinely most-significant-bit first. - **Python 3.14 Qiskit support.** The ``qiskit-extras`` extra now installs on Python 3.14. Geometry Optimization ===================== Version 2.0 added nuclear gradients and finite-difference Hessians, but left the optimization loop to the caller. Version 2.1 closes that gap with a ``geometry_optimizer`` :doc:`algorithm type <../user/comprehensive/algorithms/index>` that drives a nuclear derivative calculator to a stationary point. Optimizers follow the usual factory and settings conventions and are created by name: .. literalinclude:: ../_static/examples/python/release_notes_v2_1.py :language: python :start-after: # start-cell-geometry-optimizer :end-before: # end-cell-geometry-optimizer The energy and gradient engine is itself an algorithm reference, so any registered nuclear derivative calculator can drive the optimization: .. literalinclude:: ../_static/examples/python/release_notes_v2_1.py :language: python :start-after: # start-cell-geometry-derivative :end-before: # end-cell-geometry-derivative Shared settings on ``GeometryOptimizerSettings`` are ``derivative_calculator``, ``max_iterations`` (default 300), and ``compute_hessian`` (default ``False``; when ``True``, a Hessian is evaluated at the converged geometry and returned). .. literalinclude:: ../_static/examples/python/release_notes_v2_1.py :language: python :start-after: # start-cell-geometry-run :end-before: # end-cell-geometry-run ``run()`` takes an initial :class:`~qdk_chemistry.data.Structure`, the charge and spin multiplicity, and an ``input`` that is either a basis-set name, a :class:`~qdk_chemistry.data.BasisSet`, an :class:`~qdk_chemistry.data.Orbitals`, or a :class:`~qdk_chemistry.data.Wavefunction`. It returns the converged energy, the optimized structure, an optional :class:`~qdk_chemistry.data.NuclearHessian`, and the optional converged wavefunction. The optional trailing ``n_inactive_orbitals`` argument excludes doubly occupied orbitals from the active space used by the derivative calculator. .. rubric:: geomeTRIC plugin The bundled ``"geometric"`` implementation wraps `geomeTRIC `_ and is enabled automatically when the package is installed: .. code-block:: bash pip install 'qdk-chemistry[plugins]' It adds transition-state search (``transition_state``), a choice of coordinate system (``optimizer``, one of ``tric``, ``tric-p``, ``dlc``, ``hdlc``, ``prim``, ``cart``), the five geomeTRIC convergence thresholds (``convergence_energy``, ``convergence_rms_gradient``, ``convergence_max_gradient``, ``convergence_rms_displacement``, ``convergence_max_displacement``), and ``print_level``. As with geomeTRIC itself, all five convergence criteria must be satisfied together. Q# Context Management ===================== Previously, importing ``qdk_chemistry`` initialized the process-global Q# interpreter and forced its target profile to ``Base``, which silently invalidated Q# code the caller had already imported. The vendored utilities now load into a dedicated ``qdk.Context`` owned by the library, and importing ``qdk_chemistry`` leaves the caller's global ``qsharp`` state untouched. QDK requires that composed Q# callables belong to the same context, so :mod:`qdk_chemistry.utils.qsharp` exposes that context directly: - :func:`~qdk_chemistry.utils.qsharp.get_qsharp_context` returns the shared context; define your own Q# operations against it so they compose with the chemistry circuit builders. - :func:`~qdk_chemistry.utils.qsharp.create_qsharp_context` builds a fresh context preloaded with the chemistry utilities, forwarding ``target_profile`` and other ``qdk.Context`` options. - :func:`~qdk_chemistry.utils.qsharp.set_qsharp_context` installs a caller-supplied context process-wide (pass ``None`` to restore the default). - :func:`~qdk_chemistry.utils.qsharp.use_qsharp_context` is a context manager that overrides the active context on the current thread only. See :ref:`shared-qsharp-context` for worked examples of bringing your own Q# operation or your own context. Bug Fixes ========= .. _v2-1-phase-convention: Time-evolution phase convention ------------------------------- For :math:`U(t) = e^{-iHt}` an eigenstate of energy :math:`E` accumulates phase :math:`e^{-iEt}`, so phase estimation measures :math:`\varphi = (-Et / 2\pi) \bmod 1`. ``PauliProductFormulaContainer.eigenvalue_from_phase`` previously inverted this as :math:`E = \theta / t`, dropping the sign. It now returns :math:`E = -\theta / t`. This affects any phase estimation run — standard or iterative — whose unitary comes from a product-formula builder; qubitization-based runs, which recover :math:`E = \lambda\cos(\theta)`, are unchanged. Energies previously reported for time-evolution :term:`QPE` have the wrong sign and should be recomputed. Two related iterative :term:`QPE` defects are fixed alongside it: - The feedback phase applied to each iteration circuit is now negated to match the same convention. - The ``bits_msb_first`` field of :class:`~qdk_chemistry.data.QpeResult` is now reversed before being stored. Kitaev's iteration extracts bits least-significant first, so the field previously held them in the opposite order to its name. Other fixes ----------- - ``QpeResult`` files are now understood by ``python -m qdk_chemistry.migrate``, which drops the obsolete evolution-time field while preserving the result. The ``qpe_result`` type tag participates in the ``name.type.ext`` filename convention. See :doc:`../user/migrating-data-files`. - The migration converter rejects v1 ``TimeEvolutionUnitary`` files explicitly: they do not carry the scale required by the current :class:`~qdk_chemistry.data.UnitaryRepresentation` schema and must be regenerated. - The geomeTRIC plugin restores the host application's root logging handlers and level after geomeTRIC reconfigures logging. - Fixed a flaky cube-file generation test. Infrastructure and Packaging ============================= - **Python 3.14 Qiskit support.** ``qiskit-extras`` now installs on Python 3.14. ``qiskit-aer`` is omitted on Linux ARM64 (aarch64) for that version only, because no cp314 manylinux aarch64 wheel is published yet; all other platforms install the full set. - **New** ``plugins`` **dependency.** ``geometric>=1.0`` joins PySCF in the ``plugins`` extra.