# Mitigating a MaxCut Landscape with QAOA¶

This tutorial shows an example of mitigating the energy landscape for a two-qubit instance of MaxCut using the quantum alternating operator ansatz (QAOA). We first import the libraries we will use.

import matplotlib.pyplot as plt
import numpy as np

from cirq import Circuit, CNOT, DensityMatrixSimulator, H, LineQubit, depolarize, rz
from mitiq.zne import mitigate_executor

SIMULATOR = DensityMatrixSimulator()


We will use the density matrix simulator to compute the final density matrix of our noisy circuit, from which we then compute expectation values to mitigate.

## Defining the noiseless circuit¶

We define a function below which returns a two-qubit QAOA circuit at a specified driver angle $$\gamma$$. The mixer angle $$\beta$$ is set to $$\pi / 8$$ and we will sweep over $$\gamma$$ to compute an energy landscape.

def maxcut_qaoa_circuit(gamma: float) -> Circuit:
"""Returns two-qubit MaxCut QAOA circuit with beta = pi/8 and with the provided gamma.

Args:
gamma: One of the two variational parameters (the other is fixed).

Returns:
A two-qubit MaxCut QAOA circuit with fixed beta and gamma.
"""
q0, q1 = LineQubit.range(2)

return Circuit(
H.on_each(q0, q1),
CNOT.on(q0, q1),
rz(2 * gamma).on(q1),
CNOT.on(q0, q1),
H.on_each(q0, q1),
rz(np.pi / 4).on_each(q0, q1),
H.on_each(q0, q1)
)


We can visualize the circuit for a particular $$\gamma$$ as follows.

>>> circ = maxcut_qaoa_circuit(gamma=np.pi)
>>> print(circ)
0: ───H───@────────────@───H───Rz(0.25π)───H───
│            │
1: ───H───X───Rz(2π)───X───H───Rz(0.25π)───H───


## Defining the executor¶

To interface with mitiq, we now define an executor function which adds noise to the circuit and computes the expectation value of the usual QAOA observable $$Z \otimes Z$$, i.e., Pauli-$$Z$$ on each qubit. The code block below first creates this observable, then sets a noise value, then defines the executor.

# Observable to measure
z = np.diag([1, -1])
zz = np.kron(z, z)

# Strength of noise channel
p = 0.05

def executor(circ: Circuit) -> float:
"""
Simulates the execution of a circuit with depolarizing noise.

Args:
circ: The input circuit.

Returns:
The expectation value of the ZZ observable.
"""
# Add depolarizing noise to the circuit
circuit = circ.with_noise(depolarize(p))

# Get the final density matrix of the circuit
rho = SIMULATOR.simulate(circuit).final_density_matrix

# Evaluate the ZZ expectation value
expectation = np.real(np.trace(rho @ zz))
return expectation


Note

The above code block uses depolarizing noise, but any channel in Cirq can be substituted in.

## Computing the unmitigated landscape¶

We now compute the unmitigated energy landscape $$\langle Z \otimes Z \rangle(\gamma)$$ in the following code block.

gammas = np.linspace(-np.pi, np.pi, 50)
expectations = []

for gamma in gammas:
circ = maxcut_qaoa_circuit(gamma)
expectation = executor(circ)
expectations.append(expectation)


The following code plots these values for visualization.

plt.figure(figsize=(8, 6))
plt.scatter(gammas, expectations, color="r", label="Unmitigated")
plt.title(rf"Max-Cut QAOA: $\langle ZZ \rangle (\gamma)$ with $\beta = \pi/8$", fontsize=16)
plt.xlabel(r"Ansatz Angle $\gamma$", fontsize=16)
plt.ylabel(r"Expectation Value $\langle ZZ \rangle$", fontsize=16)
plt.legend(fontsize=14)
plt.ylim(-1, 1);


The plot is shown below.

## Computing the mitigated landscape¶

We now do the same task but use mitiq to mitigate the energy landscape.

We do so by first getting a mitigated executor as follows.

mitigated_executor = mitigate_executor(executor)


We then run the same code above to compute the energy landscape, but this time use the mitigated_exectuor instead of just the executor.

mitigated_expectations = []

for gamma in gammas:
circ = maxcut_qaoa_circuit(gamma)
mitigated_expectation = mitigated_executor(circ)
mitigated_expectations.append(mitigated_expectation)


We can visualize the mitigated landscape alongside the unmitigated landscape with the following code for plotting.

plt.figure(figsize=(8, 6))
plt.scatter(gammas, expectations, color="r", label="Unmitigated")
plt.scatter(gammas, mitigated_expectations, color="b", label="Mitigated")
plt.title(rf"Max-Cut QAOA: $\langle ZZ \rangle (\gamma)$ with $\beta = \pi/8$", fontsize=16)
plt.xlabel(r"Ansatz Angle $\gamma$", fontsize=16)
plt.ylabel(r"Expectation Value $\langle ZZ \rangle$", fontsize=16)
plt.legend(fontsize=14)
plt.ylim(-1, 1);


This cell produces a plot which looks like the following.

As we can see, the mitigated landscape is significantly closer to the noiseless landscape than the unmitigated curve.

### Acknowledgements¶

The code for this documentation was written by Peter Karalekas.