Energy estimation
=================

The :class:`~qdk_chemistry.algorithms.ExpectationEstimator` algorithm in QDK/Chemistry estimates the energy of a quantum state by measuring expectation values of Pauli operators.
Following QDK/Chemistry's :doc:`algorithm design principles <../design/index>`, it takes an OpenQASM circuit (from :doc:`StatePreparation <state_preparation>`) and a :class:`~qdk_chemistry.data.QubitOperator` (from :doc:`QubitMapper <qubit_mapper>`) as input and returns energy expectation values with statistical uncertainty.

Overview
--------

The :class:`~qdk_chemistry.algorithms.ExpectationEstimator` evaluates the expectation value of a :class:`~qdk_chemistry.data.QubitOperator` with respect to a given quantum circuit that loads a wavefunction onto qubits.
It takes a Circuit object and a target qubit operator and automatically generates the corresponding measurement circuits.
These circuits are executed on a selected backend simulator with the user-specified number of shots, and the resulting bitstring statistics are used to calculate per-term expectation values and the total energy.

The algorithm supports:

Multiple simulator backends
  QDK's native Q# simulator or Qiskit's Aer simulator
Noise modeling
  Depolarizing noise, bit flip noise, Pauli noise, phase flip noise, and qubit loss simulation
Grouped measurements
  Efficient measurement of commuting Pauli terms in a single circuit execution

A typical workflow connects :doc:`StatePreparation <state_preparation>` (which loads the wavefunction onto qubits) with ExpectationEstimator (which measures the energy):

1. Prepare a :class:`~qdk_chemistry.data.Wavefunction` from a multi-configuration calculation
2. Generate an OpenQASM circuit using :doc:`StatePreparation <state_preparation>`
3. Map the Hamiltonian to qubit operators using :doc:`QubitMapper <qubit_mapper>`
4. Estimate the energy using ExpectationEstimator

Using the ExpectationEstimator
------------------------------

.. note::
   This algorithm is currently available only in the Python API.

This section demonstrates how to create, configure, and run an energy estimation.
The ``run`` method returns an energy expectation value with variance and the raw measurement data.

Input requirements
~~~~~~~~~~~~~~~~~~

The :class:`~qdk_chemistry.algorithms.ExpectationEstimator` requires the following inputs:

Circuit
   A quantum circuit that prepares the target quantum state. This is typically generated by the :doc:`StatePreparation <state_preparation>` algorithm from a :class:`~qdk_chemistry.data.Wavefunction`.

QubitOperator
   A :class:`~qdk_chemistry.data.QubitOperator` instance containing the Pauli-string representation of the electronic Hamiltonian. This is obtained from the :doc:`QubitMapper <qubit_mapper>` algorithm.

Circuit execution
   A backend to execute the measurement circuits. Supported backends include QDK's native Q# simulator and Qiskit's Aer simulator.

Number of shots
   The number of measurement repetitions to perform for statistical sampling.
   More shots reduce statistical uncertainty but increase computational cost.

.. note::

   The circuit and Hamiltonian must be compatible—they should use the same qubit encoding and be derived from the same underlying molecular system. The estimator automatically generates measurement circuits for each Pauli term in the Hamiltonian and performs the circuit sampling internally.

.. rubric:: Creating an estimator

.. tab:: Python API

   .. literalinclude:: ../../../_static/examples/python/expectation_estimator.py
      :language: python
      :start-after: # start-cell-create
      :end-before: # end-cell-create

.. rubric:: Configuring settings and running

Settings vary by implementation. The QDK backend supports noise models and qubit loss, while the Qiskit backend supports custom Aer noise models.

.. tab:: Python API (QDK Backend)

   .. literalinclude:: ../../../_static/examples/python/expectation_estimator.py
      :language: python
      :start-after: # start-cell-qdk
      :end-before: # end-cell-qdk

.. tab:: Python API (Qiskit Backend)

   .. literalinclude:: ../../../_static/examples/python/expectation_estimator.py
      :language: python
      :start-after: # start-cell-qiskit
      :end-before: # end-cell-qiskit

Available implementations
-------------------------

QDK/Chemistry's :class:`~qdk_chemistry.algorithms.ExpectationEstimator` provides a unified interface for quantum circuit simulation and energy measurement.
You can discover available implementations programmatically:

.. tab:: Python API

   .. literalinclude:: ../../../_static/examples/python/expectation_estimator.py
      :language: python
      :start-after: # start-cell-list-implementations
      :end-before: # end-cell-list-implementations

QDK expectation estimator
~~~~~~~~~~~~~~~~~~~~~~~~~

.. rubric:: Factory name: ``"qdk"``

Native QDK/Chemistry implementation of expectation estimator. Supports various simulator backends and noise models for realistic quantum hardware simulation.

.. rubric:: Run parameters

.. list-table::
   :header-rows: 1
   :widths: 25 25 50

   * - Parameter
     - Type
     - Description
   * - ``circuit``
     - Circuit
     - Quantum circuit that prepares the target quantum state
   * - ``qubit_hamiltonian``
     - QubitOperator
     - Qubit operator to measure
   * - ``circuit_executor``
     - CircuitExecutor
     - Backend to execute the measurement circuits
   * - ``total_shots``
     - int
     - Total number of measurement shots
   * - ``noise_model``
     - QuantumErrorProfile | None
     - Noise model to apply during circuit execution

Related classes
---------------

- :class:`~qdk_chemistry.data.QubitOperator`: Input qubit operator from QubitMapper
- :doc:`Wavefunction <../data/wavefunction>`: Source wavefunction for state preparation

Further reading
---------------

- The above examples can be downloaded as a complete `Python <../../../_static/examples/python/expectation_estimator.py>`_ script.
- :doc:`StatePreparation <state_preparation>`: Load wavefunctions onto qubits as quantum circuits
- :doc:`QubitMapper <qubit_mapper>`: Map fermionic Hamiltonians to qubit operators
- See the ``examples/state_prep_energy.ipynb`` notebook for an end-to-end workflow demonstration
- :doc:`Settings <settings>`: Configuration settings for algorithms
- :doc:`Factory Pattern <factory_pattern>`: Understanding algorithm creation
