.. _ansatzes_guide:

========
Ansatzes
========

Usage
=====

In the context of VQAs, an ansatz is a template for a parameterized quantum circuit. Given a cost function which depends on the output of the circuit, parameters can be tuned to create a circuit which minimizes the cost function.

Available Ansatzes
==================
`orquestra-vqa <https://github.com/zapatacomputing/orquestra-vqa>`_ provides several ansatzes. Here we give a list of ansatzes with a brief description of each.

1. :class:`QAOAFarhiAnsatz <orquestra.vqa.ansatz.qaoa_farhi.QAOAFarhiAnsatz>` - Vanilla QAOA Ansatz, alternates global cost Hamiltonians with local mixer Hamiltonians. See `the paper <https://arxiv.org/abs/1411.4028>`_ for details.
2. ``kbody ansatzes`` - ansatzes created to solve maxcut problems. Number of parameters increases exponentially with number of qubits, but these ansaztes avoid local minima. See `the paper <https://arxiv.org/abs/2105.01114>`_ for details.
    a. :class:`XAnsatz <orquestra.vqa.ansatz.kbody.XAnsatz>` - Couples qubits in the X direction. 
    b. :class:`XZAnsatz <orquestra.vqa.ansatz.kbody.XZAnsatz>` - Couples qubits in the X and Z directions. 
3. :class:`WarmStartQAOAAnsatz <orquestra.vqa.ansatz.qaoa_warm_start.WarmStartQAOAAnsatz>` - Uses existing solution to the optimization problem to improve performance of QAOA. See `the paper <https://arxiv.org/abs/2009.10095v3>`_ for details.
4. :class:`SingletUCCSDAnsatz <orquestra.vqa.ansatz.singlet_uccsd.SingletUCCSDAnsatz>` - Widely used in chemistry problems to estimate the ground state of a molecule's Hamiltonian. Parameters control the probability of single an double excitations in your simulated molecule. See `this paper <https://arxiv.org/abs/1701.02691>`_ for details.
5. :class:`HEAQuantumCompilingAnsatz <orquestra.vqa.ansatz.quantum_compiling.HEAQuantumCompilingAnsatz>` ``HEAQuantumCompilingAnsatz`` - Hardware-efficient ansatz using quantum compiling . See `the paper <https://arxiv.org/abs/2011.12245>`_ for details.
6. :class:`QCBMAnsatz <orquestra.vqa.ansatz.qcbm.QCBMAnsatz>` - Ansatz for learning distributions for Quantum Circuit Born Machine. See `this paper <https://arxiv.org/abs/1801.07686>`_ for details.


Creating Your Own Ansatz
========================

While the ansatzes listed above provide a good start, eventually you might need to implement your own ansatz. Below you can find an example of how to do this.

Let's construct a simple example where we only have a single layer of Z rotations in our ansatz. We start by creating a child of the :class:`Ansatz <orquestra.vqa.api.ansatz.Ansatz>` class.

.. literalinclude:: ../../examples/guides/mock_ansatz.py
    :language: python
    :start-at: from typing import Optional
    :end-at: number_of_qubits = ansatz_property("number_of_qubits")

As you can see, we have added the number of qubits as an ``ansatz_property``. This is used when a property would impact the circuit generated by the ``Ansatz``, and so when the property is changed we reset the parameterized circuit to ``None``. Next, let's define the ``__init__`` method where the ansatz is defined.

.. literalinclude:: ../../examples/guides/mock_ansatz.py
    :language: python
    :start-at: def __init__(
    :end-at: self._circuit += RZ(new_symbol)

Finally, we'll define the ``_generate_circuit`` function which substitutes parameters into the circuit. Note we must use the ``@overrides`` decorator to ensure that this critical function is implemented properly.

.. literalinclude:: ../../examples/guides/mock_ansatz.py
    :language: python
    :start-at: def _generate_circuit(
    :end-at: return self._circuit.bind(symbols_map)

And that's it! Once the ansatz is defined we can easily subtitute in into an ``EstimationTaskFactory``.


Another important concept to understand about our implementation of ansatzes is that it can support symbolic parameters. Conceptually, ansatzes yield themselves nicely be expressed using symbols rather. However, it might come at the price of performance, so we recommend implementing your ansatz using symbolic circuits in two cases:

- if generating circuit is time-consuming. For example in QAOA you need to perform time evolution of a Hamiltonian to build a circuit, which, depending on the Hamiltonian, can be pretty resource-intensive.
- if you value clarity and transparency over performance. 

