Quantum Alternating Operator Ansatz/Quantum Approximate Optimization Algorithm (QAOA)
Project description
QAOA
This package is a flexible python implementation of the Quantum Approximate Optimization Algorithm /Quantum Alternating Operator ansatz (QAOA) aimed at researchers to readily test the performance of a new ansatz, a new classical optimizer, etc. By default it uses qiskit as a backend.
Install with pip install qaoa or pip install -e ..
Background
Given a cost function $$c: \lbrace 0, 1\rbrace^n \rightarrow \mathbb{R}$$ one defines a problem Hamiltonian $H_P$ through the action on computational basis states via
$$ H_P |x\rangle = c(x) |x\rangle,$$
which means that ground states minimize the cost function $c$. Given a parametrized ansatz $| \gamma, \beta \rangle$, a classical optimizer is used to minimize the energy
$$ \langle \gamma, \beta | H_P | \gamma, \beta \rangle.$$
QAOA of depth $p$ consist of the following ansatz:
$$ |\gamma, \beta \rangle = \prod_{l=1}^p \left( U_M(\beta_l) U_P(\gamma_l)\right) | s\rangle, $$
where
- $U_P$ is a family of phase-separating operators,
- $U_M$ is a family of mixing operators, and
- $|s\rangle$ is a "simple" initial state.
In plain vanilla QAOA these have the form $U_M(\beta_l)=e^{-i\beta_l X^{\otimes n}}$, $U_P(\gamma_l)=e^{-i\gamma_l H_P}$, and the uniform superposition $| s \rangle = |+\rangle^{\otimes n}$ as initial state.
Create a custom ansatz
In order to create a custom QAOA ansatz, one needs to specify a problem, a mixer, and an initial state. These base classes have an abstract method def create_circuit:which needs to be implemented. The problem base class additionally has an abstract method def cost:.
This library already contains several standard implementations.
- The following problem cases are already available:
- The following mixer cases are already available:
- X-mixer
- XY-mixer
- Grover-mixer
- Max k-CUT grover
- Max k-CUT LX
- X multi-angle mixer (one β per qubit)
- The following initial state cases are already available:
- Plus
- Statevector
- Dicke
- Dicke 1- and 2-states superposition
- Less than k
- Max k-CUT feasible
- Plus parameterized (|+⟩ with optimizable phase rotations)
It is very easy to extend this list by providing an implementation of a circuit/cost of the base classes mentioned above. Feel free to fork the repo and create a pull request :-)
To make an ansatz for the MaxCut problem, the X-mixer and the initial state $|+\rangle^{\otimes n}$ one can create an instance like this:
qaoa = QAOA(
problem=problems.MaxKCutBinaryPowerOfTwo(G="some networkx instance", k_cuts=2),
mixer=mixers.X(),
initialstate=initialstates.Plus()
)
(can be used for the standard MaxCut with argument k_cuts=2, or use problems.MaxCut(G) for convenience)
Run optimization at depth $p$
For depth $p=1$ the expectation value can be sampled on an $n\times m$ Cartesian grid over the domain $[0,\gamma_\text{max}]\times[0,\beta_\text{max}]$ with:
qaoa.sample_cost_landscape()
Sampling high-dimensional target functions quickly becomes intractable for depth $p>1$. We therefore iteratively increase the depth. At each depth a local optimization algorithm, e.g. COBYLA, is used to find a local minimum. As initial guess the following is used:
- At depth $p=1$ initial parameters $(\gamma, \beta)$ are given by the lowest value of the sampled cost landscape.
- At depth $p>1$ initial parameters $(\gamma, \beta)$ are based on an interpolation-based heuristic of the optimal values at the previous depth.
Running this iterative local optimization to depth $p$ can be done by the following call:
qaoa.optimize(depth=p)
The function will call sample_cost_landscape if not already done, before iteratively increasing the depth.
Further parameters
QAOA supports the following keywords:
qaoa = QAOA( ...,
backend= ,
noisemodel= ,
optimizer= ,
precision= ,
shots= ,
cvar=
)
backend: the backend to be used, defaults toAerSimulator()(fromqiskit_aer)noisemodel: the noise model to be used, default toNone,optimizer: a list of the optimizer to be used from qiskit-algorithms together with options, defaults to[COBYLA, {}],precision: sampel until a certain precision of the expectation value is reached based on $\text{error}=\frac{\text{variance}}{\sqrt{\text{shots}}}$, defaults toNone,shots: number of shots to be used, defaults to1024,cvar: the value for conditional value at risk (CVAR), defaults to1, which are the standard moments.
Extract results
Once qaoa.optimize(depth=p) is run, one can extract, the expectation value, variance, and parametres for each depth $1\leq i \leq p$ by respectively calling:
qaoa.get_Exp(depth=i)
qaoa.get_Var(depth=i)
qaoa.get_gamma(depth=i)
qaoa.get_beta(depth=i)
Additionally, for each depth every time the loss function is called, the angles, expectation value, variance, maximum cost, minimum cost, and number of shots are stored in
qaoa.optimization_results[i]
Multi-Angle QAOA
Multi-angle QAOA allows components to use multiple parameters per layer, increasing expressibility:
-
Multi-angle mixer (
XMultiAngle): Each qubit gets its own independent β parameter -
Parameterized initial state (
PlusParameterized): The initial state |+⟩ with optimizable per-qubit phase rotationsqaoa = QAOA( problem=problems.MaxKCutBinaryPowerOfTwo(G="some networkx instance", k_cuts=2), mixer=mixers.XMultiAngle(), # N_qubits beta parameters per layer initialstate=initialstates.Plus() )
The flat angle array format used by hist(), getParametersToBind(), and interp() is:
[init_0, ..., init_{n-1}, # initial state params (0 for Plus)
gamma_{0,0}, ..., beta_{0,n-1}, # layer 0 params
gamma_{1,0}, ..., beta_{1,n-1}, # layer 1 params
...]
For the standard single-parameter case, this reduces to [gamma_0, beta_0, gamma_1, beta_1, ...].
Implement get_num_parameters() in a custom component to enable multi-angle support. See examples/MultiAngle for a complete example.
Example use cases
See examples here.
Minimizing depth of phase separating operator
Assuming all-to-all connectivity of qubits, one can minimize the depth of the circuit of the phase separating operator by solving the problem of minimum edge colouring. This is implemtend in GraphHandler and gets automatically invoked. An example output is this
Tensorize mixers
To tensorize a mixer, i.e. decomposing the mixer into a tensor product of unitaries that is performed on each qubit, one can call the tensor class with the arguments of mixer and number of qubits in subpart.
For example, for the standard MaxCut problem above where the X mixer was used, one could find the tensor by writing:
tensorized_mixer = Tensor(mixer.X(), number_of_qubits_of_subpart)
Talk to an agent
In the code, there is also included an "agent" folder, which has implemented a specialized QAOA agent. It is possible to ask the agent for either code that implements, or explanations about, the QAOA package.
There are two ways to run the agents. Either one can run the agent in the terminal, or run an interface.
To run the agent directly from the terminal, one can simply open the agent folder and run the file planner.py. It is then possible to ask it questions as inputs from the terminal.
To run the interface, open the agent folder, and run streamlit by typing: streamlit run interface.py The following window will pop up:
It is then possible to ask questions in the text box. An example could be:
For the agent application the following dependencies are needed: langchain, langchain_community, langchain_chroma, langchain_openai and optionally streamlit (for the interface). Additionally, an API-KEY is needed.
Acknowledgement
We would like to thank for funding of the work by the Research Council of Norway through project number 33202.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file qaoa-1.2.2.tar.gz.
File metadata
- Download URL: qaoa-1.2.2.tar.gz
- Upload date:
- Size: 75.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a40ce42ceafc83c2b1ac289baee8271778137ce1b24bd16250339113db97f39
|
|
| MD5 |
9cb24ae48f479b8aacc5ff7cf783b89e
|
|
| BLAKE2b-256 |
542ba345b9b19fcbd97aaf16a3240f8ade024f17ec414d969d88c4287b9d30a5
|