# How to use InQuanto¶

InQuanto is a modular Python library with components that fit together to allow bespoke quantum computational chemistry calculations. Whilst InQuanto can be used in a reasonably black-box manner, the user is recommended to have some familiarity with modern computational chemistry and quantum computational chemistry.

In the figure below we show how the key components in InQuanto can be brought together. More in-depth guides on each of these components can be found in this user guide.

## Chemistry Workflows¶

In InQuanto, `algorithms`

solve quantum computational problems representing
chemical systems and quantities of interest. The classes in this module, such as
`AlgorithmVQE`

, include quantum and hybrid quantum-classical methods
which we may apply to evaluate
meaningful chemical quantities, such as ground and excited states. The choice of algorithm may be determined
by the problem of interest. See Algorithms.

Algorithms use `computables`

. Computables are expressions representing
physical or chemical quantities that one may want to compute with a quantum circuit. A basic example of a computable is the
`ExpectationValue`

of a quantum state, such as the total energy of the system
as reported by the Hamiltonian. Computables are symbolic, contain the ingredients needed to give the quantity of interest,
and their evaluation is performed using `protocols`

. Protocols build and contain the quantum circuits required to evaluate
a computable, as well as instructions for measuring and interpreting quantum measurements.
See Computables and Protocols for more details.

These algorithms also use pytket backends to drive the quantum computation, and may also need classical functions or data, such as minimizers or a set of initial parameters to aid solution.

Note

InQuanto’s main focus is solving the electronic structure problem of molecules within the Born-Oppenheimer (frozen nuclei) approximation. This is often described using second quantization, such that the Hamiltonian is:

where \(a^{\dagger}\) and \(a\) are the Fermionic creation and annihilation operators and \(h_{ij}\) and \(h_{ijkl}\) are the one- and two- body electronic integrals respectively. The integrals are obtained from mean-field calculations, such as Hartree-Fock. For more details see e.g. [4, 5]

In order to build a computable, one must InQuantize the chemical system.
This refers to how InQuanto takes a chemical system defined by the
atomic coordinates or some model and constructs its set of qubit states
and operators. Broadly, this can be considered to split into two steps, *i*) preparing mean-field quantities, and
*ii*) selecting and representing the electronic system.

Doing so will allow us to construct and run computables and algorithms.

## Preparing Mean-Field Systems¶

One must first process the molecule/material from a specification of molecular geometry or an atomic structure file (e.g. mol.xyz). Then, drivers run mean-field calculations with a small classical computational overhead, such as Hartree-Fock.

Geometry takes the structure and loads it into InQuanto. Symmetry contains a set of tools for reducing the computational complexity of chemical systems at the structural, electronic, and qubit levels. Embeddings (e.g. DMET) allow one to focus computational effort on a part of the system, reducing the overall cost. Drivers are used to run classical computational chemistry calculations to construct components and are generally provided by InQuanto Extensions but there are also model Hamiltonians and data in Express.

## Spaces, Operators, States and Mappings¶

When the mean-field system is defined and the classical components calculated, one can specify the Spaces, Operators, and States of the system and perform Qubit Mappings.

For example, systems of correlated electrons are modelled using some electronic Hamiltonian operator which acts on a Fermionic Hilbert space, with the state often being defined by a set of occupation numbers. In InQuanto we can construct these spaces, operators, and states and then convert them to qubit spaces, qubit operators, and qubit states.

Many quantum algorithms for quantum chemistry require the preparation of an ansatz state, which may be parameterized. These ansatzes are educated guesses for the state of the chemical system. InQuanto represents the generation of quantum circuits necessary for a variety of ansatzes using the ansatz classes.

## Running Computables and Algorithms¶

When the qubit based ansatz and operators have been prepared, they are fed into Computables and we are ready to focus on exactly how the computable is evaluated. This is done using Protocols. Specifically, Protocols add instructions for how to measure the necessary state and operators for the computable of interest. They are also where noise mitigation capabilities may be provided.

Computables and Protocols are fed into the algorithm along with some complementary initial parameters. The initial parameters for the qubit states vary between algorithms. Similarly, the form of the ‘solver’ also varies between algorithms. If performing a variational algorithm then the preference is for an efficient Minimizers, whilst time-evolution algorithms require Integrators.

The last component we need to `build`

an `algorithms`

or `computables`

class is quantum computational
hardware and simulators accessed via pytket-extensions. Pytket
optimizes the underlying circuit for performance, can deliver the circuit to the hardware or simulator (when
provided credentials), and will collect the processed circuit results to
pass to InQuanto.

Having provided the `algorithms`

with the necessary input, all that
remains is to `run`

the circuit(s). This will automatically pass the
information from the built `algorithms`

to the backend, queue then run
the experiment, and return results. The `algorithms`

object can then be
inquired for results, for example `algorithm.final_values`

, which
correspond to the computable and gives the chemical quantity of
interest.

## Expert use of InQuanto¶

For expert quantum computational chemistry users there are a couple of useful tips.

There are a number of fully customizable classes which allow users to construct objects from scratch or modify
prebuilt objects. For example, `QubitMapping`

can be used
to build your own mapping, or `operators`

classes have many tools for adding, removing, or manipulating terms.

Expert users can also manipulate circuits using the pytket stack. Ultimately, InQuanto constructs,
runs, and interprets pytket circuits. Thus,
one can obtain the circuit objects from InQuanto using functions such as
`get_circuit()`

to change the underlying circuit e.g. by manually
appending gates. It is also possible to inject pytket
native objects into InQuanto, such as passing a custom built
compiler pass objects to protocols. Due to
its modular nature, these modifications can be made and become part of an InQuanto workflow.