Path: blob/main/notebooks/summer-school/2021/resources/lab-notebooks/lab-2.ipynb
3855 views
Lab 2: Introduction to Variational Algorithms
In this Lab, you will learn about
variational quantum algorithms, in particular Variational Quantum Eigensolvers
how to create and work with parameterized circuits and quadratic programs in Qiskit
how to solve optimization problems using QAOA
1) Introduction
This section serves as an introduction to the topic of variational quantum algorithms and as a recap of the material covered in the previous lecture.
Variational quantum algorithms
In the most general sense, a variational quantum circuit is a circuit that depends on a set of parameters . Typically, a variational quantum algorithm queries a quantum computer to sample the output of this parameterized quantum circuit for some fixed parameters and evaluates a given cost function based on this output. A classical optimizer is then used to update the circuit parameters in order to maximize or minimize the objective function . These steps are repeated in a quantum-classical hybrid loop that eventually terminates when the classical optimization has found optimal parameters .
Variational Quantum Algorithms are often seen as a promising method of achieving quantum advantage on near term devices. In a lot of cases they do not require the execution of deep quantum circuits and systematic errors can partly be mitigated by outsourcing the optimization procedure to a classical optimizer. Nevertheless, VQAs also face a number of challenges, in particular the questions of whether they are efficiently trainable and produce solutions that are in fact superior to those obtained by classical algorithms. Despite these challenges, VQAs have been proposed for a variety of problem settings, amongst others the following.
Variational Quantum Eigensolvers: VQEs attempt to approximate the ground state and corresponding energy of a quantum system described by a Hamiltonian (i.e. the lowest eigenvalue and eigenvector of the corresponding hermitian matrix) (see below).
QAOA: An approximate optimization algorithm used for combinatorial optimization problems. QAOA can be seen as a VQE that solves optimization problems by encoding the cost function as a problem Hamiltonian (see Section 4).
Variational Classifiers: A variational classifier is a quantum circuit that is trained on a data set to classify unseen data samples, reminiscent of classical machine learning classifiers.
Variational Quantum Linear Solvers: VQLS solves systems of linear equations by leveraging the basic ideas behind VQEs.
In this lab, we will focus on QAOA as a special case of the Variational Quantum Eigensolver.
The Variational Method
Consider a Hermitian operator describing a quantum system with corresponding ground state and ground state energy . The variational method is a technique to approximate and . This is done by choosing a parameterized trial state , where denotes a set or vector of parameters. Recall that the energy of the system in the state is given by its expectation value with respect to Since the ground state of the system is the lowest energy eigenstate, by definition it holds that for any parameters . Thus, by minimizing the expectation value of the trial state , that is, finding parameters for which the expectation value becomes as small as possible, we obtain an upper bound on the ground state energy and an approximation of the ground state itself. Naturally, the choice of a good trial state is principal to the success of the variational method.
Variational Quantum Eigensolvers
Variational quantum eigensolvers use the variational method to approximate the ground state and minimal eigenvalue of a Hamiltonian . The trial state now corresponds to a quantum state prepared by a variational quantum circuit and the corresponding expectation value is measured by executing the circuit on a quantum computer. A classical optimizer is then used to tune the circuit parameters and minimize the measured expectation value.
Apart from being applicable to problems in chemistry or quantum mechanics itself, where we are directly interested in the ground state of a given Hamiltonian, one can also use the concept of variational quantum eigensolvers for optimization problems, by encoding the cost function that should be optimized as a Hamiltonian whose ground state corresponds to the optimal solution of the problem. This idea lies at the heart of QAOA.
Parameterized Quantum Circuits
In this section, we will learn how to construct parameterized circuits and assign values to circuit parameters in Qiskit, allowing us to build custom variational forms.
Constructing a parameterized circuit
Creating a quantum circuit with parameters in Qiskit is not much different from creating a standard quantum circuit. We simply initialize parameters using Qiskit's Parameter class and use them accordingly when appending gates to the constructed circuit. In the following example, we use parameters for the rotation angle of rotational quantum gates.
The same parameter can also be used multiple times within the same circuit. Consider the circuit form as above, but with the same parameter used repeatedly for different gates.
For convenience, there also exists a ParameterVector class in Qiskit which allows for the creation of multiple parameters at once. Consider the following example of a RealAmplitudes circuit, which consists of alternating layers of parameterized gates and entangling gates. The RealAmplitudes variational form is commonly used for classification in quantum machine learning and can also be found in the circuit library of Qiskit.
We can inspect the parameters that are part of a quantum circuit.
Assigning values to parameters
A parameterized circuit cannot be executed on a quantum backend until the parameters have been assigned fixed values. To do so, we can use the QuantumCircuit methods
bind_parameters assigns numeric values to the parameters of the circuit, always yielding a new circuit. With assign_parameters, one can assign numeric values or substitute parameters by other parameter expressions. Additionally, with assign_parameters it is possible to substitute parameters in place instead of yielding a new circuit. The values or parameter expressions that should be assigned to the circuit parameters can be provided either as a dictionary, where the dictionary keys correspond to the parameters in the circuit and the dictionary values are the values to bind, or as an iterable of values. In the latter case values are assigned to parameters in the same order as parameters were added to the circuit.
Consider also the following circuit, where we substitute a parameter from the original circuit by another parameter expression.
The bound version of the circuit can now be executed on a quantum device. Attempting to execute a parameterized quantum circuit with non-assigned parameters will throw an error.
Quadratic Programs
In this section, we will review the MaxCut problem and learn how to construct quadratic programs in Qiskit.
MaxCut
In the MaxCut problem, the input is a (possibly weighted) graph and one attempts to find a partition of the graph vertices into two disjoint sets, such that the cumulative weight of edges connecting vertices from different cuts is maximized.
Let be a (weighted) graph with vertices. By numbering the vertices , and assigning each vertex either the value 0 or 1, we can identify any cut of the graph with a vector . The weight of a cut is then determined by the cost function where determines the weight of the edge connecting vertices and , and if and are not connected by an edge. It is easy to see that each edge weight contributes exactly once to the sum if and only if .
The dictionary graphs defined below contains a number of different graph instances for you to explore. The name ending for each graph specifies the kinds of weights used.
Let us create one more graph instance using the networkx module and add it to the dictionary. You can use the widget below to explore cuts of different graph instances. The two groups of vertices are marked in light and dark blue, respectively, and edges that connect vertices from different groups (and therefore contribute to the cut weight) are marked in red.
Exercise 1: MaxCut
For the newly defined graph above, find the maximum cut and pass it as a list of bits '[]' to the grader. You can use the following function which displays a bar plot of the cost function values for all possible bitstrings, but you need to add the code that computes the maxcut cost function value for a particular bitstring . The numpy matrix weight_matrix refers to and you can access its elements via weight_matrix[i,j].
Quadratic Programs
A quadratically constrained quadratic program is an optimization problem with a quadratic objective function and linear and quadratic constraints on the optimization variables. In other words, it can be written in the following form where is a symmetric real-valued -matrix and is a real-valued vector specifying the quadratic and linear parts of the objective function. The optimization variables can be binary, integer- or real-valued, depending on the problem at hand.
In Qiskit, we can create quadratic programs with the QuadraticProgram class, located in the qiskit_optimization module. To generate a new model, simply call the initializer with the desired problem name.
We can add binary, integer or continuous optimization variables by calling the respective methods binary_var, integer_var and continuous_var. Any variable added to the quadratic program is specified by a name. We can also specify variable bounds for integer and continuous variables, using the lowerbound and upperbound arguments.
To set the objective function, use the methods minimize or maximize, depending on whether it is a minimization or maximization problem. The quadratic and linear terms can be specified by passing either a list, a matrix or a dictionary for the arguments linear and quadratic. It is also possible to specify a constant offset with the argument constant.
Finally, to print the quadratic program in a readable format, use the method export_as_lp_string.
Instead of creating quadratic programs from scratch, we can also convert an existing docplex model, explained in more detail in this tutorial on quadratic programs.
MaxCut as a Quadratic Program
We can formulate any MaxCut problem as a quadratic program. Consider again the cost function for a MaxCut problem with symmetric weight matrix This is clearly a quadratic cost function and we can reformulate it in the standard form for quadratic programs as written above. for and defined as follows Thus, we obtain an optimization instance with binary variables, a quadratic objective function and without any variable constraints. A quadratic program of that form is also called a quadratic unconstrained binary optimization instance, or QUBO for short. In the next section, we will learn how to use QAOA to optimize problems of that type.
Exercise 2: MaxCut to QUBO
The following function should construct a quadratic program from a MaxCut problem instance defined by a graph. Complete the code, using the methods explained in the previous section. You will have to add binary variables to the quadratic program which should be named 'x_0', 'x_1', ..., 'x_n'. We refer to the weight matrix as weight_matrix and to the qubo matrix as qubo_matrix.
QAOA
In this section, we will implement our own version of the QAOA variational form and solve the MaxCut problem defined in the sections above, using the Quantum Approximate Optimization Algorithm (QAOA) implemented in Qiskit.
QAOA Variational Form
Recall that the variational form for QAOA has the following layerized structure
where refers to a cost Hamiltonian that encodes the cost function of the optimization problem and is a mixer hamiltonian.
In the original version of QAOA, the initial prepared state is the equal superposition state and the mixer Hamiltonian is defined as the sum of single Pauli -operators on all qubits For a QUBO instance with corresponding matrix , we would like to encode the cost function as the cost Hamiltonian , that is we are trying to find an operator , such that for all computational basis states .
Using the fact that where denotes the unit operator and the Pauli-Z matrix for qubit , we can write as a sum of Pauli-Z operators, by carrying out the substitution in the cost function expression . This yields the following expression for Exponentiating both Hamiltonians, we obtain a variational from consisting of and gates in the cost layer and gates in the mixer layer As an example, consider the QAOA variational form for the QUBO of the MaxCut instance defined above (for ).
The gates in the circuit above have been decomposed as a combination of two gates and one single rotational gate. Note also that in QAOA circuits for MaxCut QUBO instances, the angle of the single rotational gates is always equal to 0.
Exercise 3: QAOA Variational Form
Write a function that takes as input a quadratic program and a parameter , and produces as output the corresponding QAOA circuit with layers. The basic construct of the function is provided below, but you will have to insert the parts where the cost and mixer layers are applied. You will need to calculate the angles of the rotational gates as described in the final equations above. In the code below, we refer to the qubo matrix as qubo_matrix, and to the vector as qubo_linearity. Make sure not to include any measurements in the circuit.
Once you have finished the exercises above, you can explore the QAOA circuits of different graph instances.
The QAOA and MinimumEigenOptimizer class
If you have managed to complete the previous exercises, congratulations! You have implemented your own version of QAOA that can solve general QUBO instances and in particular MaxCut problems by running on a quantum computer. Qiskit also provides its own implementation of QAOA which allows us to solve optimization problems with only a few lines of code.
The QAOA class in Qiskit is located in qiskit.algorithms and directly inherits from the Variational Quantum Eigensolver class VQE. The initializer for QAOA takes the following input parameters, amongst others
optimizer: This argument refers to the classical optimizer used for updating the circuit parameters. Qiskit offers a number of different optimizers and you can also define your own by subclassing Qiskit's nativeOptimizerclass. Some of the basic optimizers offered by Qiskit are the following:reps: The number of layers in the QAOA variational form, i.e. the depth of the algorithm. For higher values of , QAOA can theoretically obtain better results but the quantum circuit becomes deeper and there are more parameters to optimize.initial_point: Optional initial parameter values (values for and ) to start the optimization with.quantum_instance: The quantum instance to run the algorithm on. This can be a simulator or a real hardware device.callback: A callback function that can be used to monitor the optimization process.
Below, you will be able to test the effect of some of these arguments on the optimization procedure of QAOA.
The MinimumEigenOptimizer object provides a wrapper for the optimization process that handles the conversion from a quadratic program to a qubit operator as well as calling a given MinimumEigenSolver, such as QAOA to obtain the corresponding optimization result. The initializer takes as input the MinimumEigenSolver to use for the optimization, and the optimization is run by calling the optimize method with a quadratic program as input. Putting it all together, we can obtain a solution for the MaxCut problem defined above with only a couple of lines of code.
As you can see, the optimizer indeed manages to find the optimum within only a few optimization steps. We can also plot the optimized statevector to see which bitstrings are more likely to be sampled after optimization of the parameters has concluded.
Explore: The QAOA Optimization Process
The following widget shows a precomputed energy landscape for the MaxCut problem defined above and visualizes the QAOA optimization process at depth , showing how the statevector and average function value change with each parameter update. Try using different classical optimizers and initial points to see how it affects the optimization process. Note that the first value in initial_point sets the initial value for the parameter and the second value sets the initial value for the parameter.
Observe the periodicity in the cost function landscape plotted above. This is a direct consequence of the periodicity of the rotational gates used in the QAOA variational form. Since all rotational gates have a periodicity of and the MaxCut example we investigate here only has edges with integer weights, we observe a periodicity of in the parameter and a periodicity of in the parameter.
Higher values of
With higher values of , QAOA is theoretically able to reach a quantum state with a better energy value with respect to the cost Hamiltonian since increasing the number of layers strictly increases the space of quantum states, one is able to reach. That is, if denotes the maximal energy value reachable with a QAOA variational form of depth , it holds that In fact, using the adiabatic theorem, one can prove, that in the infinite limit, we are able to reach the maximal cost function value While the connection to adiabatic quantum computing serves as a justification of why we might expect QAOA to yield good optimization results, it only holds in the infinite limit, which in turn corresponds to an infinitely long quantum algorithm. One also needs to be mindful of the fact that the number of parameters increases with the number of layers, and finding the global optimum becomes increasingly harder when introducing more parameters.
The following plots show the evolution of the optimal QAOA state found for increasing values of and give some idea of how the circuit depth affects QAOA performance.
CVaR
One recently proposed adaptation to QAOA is the idea of calculating the Conditional Value at Risk (or CVaR). Here, instead of calculating the mean of all cut values obtained from the measurement outcomes of the circuit to compute the cost function , the algorithm only takes into account a fraction of the highest measured cut values. where the are ordered decreasing in size. Since we are only interested in obtaining a single good solution for the original optimization problem, looking only at a fraction of the best cuts can help to speed up the optimization process. Let us explore how adding CVaR can change the energy landscape of a QAOA instance. The following code creates and plots a QAOA energy landscape of a given MaxCut instance using your code from the previous exercises and returns the optimal parameters obtained during a grid search. Calculating the energy landscape might take a while.
Exercise 4: CVaR
Adapt the code above, so instead of taking the mean of all sampled cut values, the algorithm calculates the conditional value at risk and observe how different settings of the parameter change the QAOA energy landscape. What are the energy and optimal parameters we obtain by the grid search when setting the CVaR parameter to when using 1000 shots and setting the random seed of the qasm simulator to 42 (as is already done in the code above)?
Additional Resources
Tutorial on VQEs in Qiskit Textbook
Tutorial on combinatorial optimization with QAOA in Qiskit Textbook
E. Farhi, J. Goldstone, and S. Gutmann, A Quantum Approximate Optimization Algorithm (2014): The original QAOA paper
Qiskit Optimization Tutorials including
Talk by E. Farhi on recent results for QAOA at the Simons Institute for the Theory of Computing