🧬 Variational Quantum Algorithms (VQE & QAOA)
Variational Quantum Algorithms (VQAs) are hybrid quantum-classical algorithms. They use a classical optimizer to update the parameters of a quantum circuit (ansatz) to minimize a cost function. QVM implements these algorithms in vqe.py, qaoa.py, observable.py, and gradient.py.
🧮 Hamiltonians & Observables
A Hamiltonian represents the energy of a physical system or a cost function to minimize. In QVM, it is represented as a linear combination of Pauli strings (tensor products of ):
PauliOp: Represents a single term .Hamiltonian: Tracks a list ofPauliOpobjects. Can construct the full matrix representation in the statevector space:pythonH_matrix = observable.to_matrix(circuit.num_qubits)
🔁 Hybrid Optimization Loop
Both VQE and QAOA operate in a closed feedback loop:
1. Variational Quantum Eigensolver (VQE)
VQE seeks to find the ground state energy (lowest eigenvalue) of a Hamiltonian:
- Ansatz Function: A parameterized circuit template:
python
def ansatz(params): qc = QuantumCircuit(2) qc.add_operation("ry", [0], params=[params[theta]]) qc.add_operation("cx", [0, 1]) return qc - Cost Function: Computes the exact expectation value:
- Optimizer: SciPy's
minimize(e.g.cobyla,powell,l-bfgs-b) updates the parameter array to minimize the expectation value.
2. Quantum Approximate Optimization Algorithm (QAOA)
QAOA is a specialized VQA designed for solving combinatorial optimization problems (e.g. MaxCut).
A. Circuit Structure
The ansatz alternates between a problem (cost) Hamiltonian layer and a mixer Hamiltonian layer:
- Initial Superposition: Apply Hadamard gates to all qubits to create state .
- Cost Unitary Layer: Apply . For terms in the Hamiltonian, this is unrolled into:
- Mixer Unitary Layer: Apply (implemented as on all qubits).
B. MaxCut Problem Hamiltonian
For a graph , the MaxCut Hamiltonian is: QAOA minimizes to find the configuration that maximizes the cut. The optimal bitstring is extracted by sampling the final optimized state.
📐 Gradient Calculations
To use gradient-based optimizers (like L-BFGS-B or SLSQP), QVM provides two ways to compute the gradient vector :
1. Analytical Gradients: The Parameter Shift Rule
For parameterized circuits with gates generated by single Pauli operators (like ), the exact derivative of the expectation value with respect to a parameter is: where is a shift parameter (usually ).
This allows QVM to compute exact analytic gradients using only two circuit evaluations per parameter, without numerical approximations:
# Forward shift
forward_values = dict(current_values)
forward_values[param] = current_values[param] + shift
e_forward = simulator.expectation_value(circuit.bind_parameters(forward_values), observable)
# Backward shift
backward_values = dict(current_values)
backward_values[param] = current_values[param] - shift
e_backward = simulator.expectation_value(circuit.bind_parameters(backward_values), observable)
gradient[i] = (e_forward - e_backward) / (2 * np.sin(shift))2. Numerical Gradients: Central Finite Difference
A standard numerical fallback: where is a small step size (default ). It is used when the parameter shift rule is not mathematically applicable.