Mitigating the energy landscape of a variational circuit with Mitiq

This tutorial shows an example in which the energy landscape for a two-qubit variational circuit is explored with and without error mitigation.

import matplotlib.pyplot as plt
import numpy as np
from cirq import Circuit, rx, CNOT, DensityMatrixSimulator, LineQubit, depolarize

from mitiq.zne import mitigate_executor
from mitiq.zne.inference import RichardsonFactory

SIMULATOR = DensityMatrixSimulator()

Defining the ideal variational circuit

We define a function which returns a simple two-qubit variational circuit depending on a single parameter \(\gamma\).

def variational_circuit(gamma: float) -> Circuit:
    """Returns a two-qubit circuit for a given variational parameter.

    Args:
        gamma: The variational parameter.

    Returns:
        The two-qubit circuit with a fixed gamma.
    """
        
    q0, q1 = LineQubit.range(2)
        
    return Circuit([rx(gamma)(q0), CNOT(q0, q1), rx(gamma)(q1), CNOT(q0, q1), rx(gamma)(q0)])
   

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

print(variational_circuit(gamma=np.pi))
0: ───Rx(π)───@───────────@───Rx(π)───
              │           │
1: ───────────X───Rx(π)───X───────────

Defining the executor functions with and without noise

To use error mitigation methods in Mitiq, we define an executor function which computes the expectation value of a simple Hamiltonian \(H=Z \otimes Z\), i.e., Pauli-\(Z\) on each qubit. To compare to the noiseless result, we define both a noiseless and a noisy executor below.

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

def noiseless_executor(circ: Circuit) -> float:
    """Simulates the execution of a circuit without noise.

    Args:
        circ: The input circuit.

    Returns:
        The expectation value of the ZZ observable.
    """
    # Get the final density matrix of the circuit
    SIMULATOR = DensityMatrixSimulator()
    rho = SIMULATOR.simulate(circ).final_density_matrix
    # Evaluate the ZZ expectation value
    expectation = np.real(np.trace(rho @ hamiltonian))
    return expectation

# Strength of noise channel
p = 0.04

def executor_with_noise(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
    noisy_circuit = circ.with_noise(depolarize(p))
    # Use the noiseless_executor function to return the expectation value of the ZZ observable for the noisy circuit
    return noiseless_executor(noisy_circuit)

Note

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

Computing the landscape without noise

We now compute the energy landscape \(\langle H \rangle(\gamma) =\langle Z \otimes Z \rangle(\gamma)\) on the noiseless simulator.

gammas = np.linspace(0, 2 * np.pi, 50)
noiseless_expectations = [noiseless_executor(variational_circuit(g)) for g in gammas]

The following code plots the values for visualization.

plt.figure(figsize=(8, 6))
plt.plot(gammas, noiseless_expectations, color="g", linewidth=3, label="Noiseless")
plt.title("Energy landscape", fontsize=16)
plt.xlabel(r"Ansatz angle $\gamma$", fontsize=16)
plt.ylabel(r"$\langle H \rangle(\gamma)$", fontsize=16)
plt.legend(fontsize=14)
plt.ylim(-1, 1);
plt.show()
---------------------------------------------------------------------------
ParseFatalException                       Traceback (most recent call last)
~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/_mathtext.py in parse(self, s, fonts_object, fontsize, dpi)
   2276         try:
-> 2277             result = self._expression.parseString(s)
   2278         except ParseBaseException as err:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/pyparsing/core.py in parse_string(self, instring, parse_all, parseAll)
   1106                 # catch and re-raise exception from here, clearing out pyparsing internal stack trace
-> 1107                 raise exc.with_traceback(None)
   1108         else:

ParseFatalException: Unknown symbol: \langle, found '\'  (at char 0), (line:1, col:1)

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/IPython/core/formatters.py in __call__(self, obj)
    339                 pass
    340             else:
--> 341                 return printer(obj)
    342             # Finally look for special method names
    343             method = get_real_method(obj, self.print_method)

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/IPython/core/pylabtools.py in <lambda>(fig)
    251 
    252     if 'png' in formats:
--> 253         png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
    254     if 'retina' in formats or 'png2x' in formats:
    255         png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/IPython/core/pylabtools.py in print_figure(fig, fmt, bbox_inches, **kwargs)
    135         FigureCanvasBase(fig)
    136 
--> 137     fig.canvas.print_figure(bytes_io, **kw)
    138     data = bytes_io.getvalue()
    139     if fmt == 'svg':

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2228                        else suppress())
   2229                 with ctx:
-> 2230                     self.figure.draw(renderer)
   2231 
   2232             if bbox_inches:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     72     @wraps(draw)
     73     def draw_wrapper(artist, renderer, *args, **kwargs):
---> 74         result = draw(artist, renderer, *args, **kwargs)
     75         if renderer._rasterizing:
     76             renderer.stop_rasterizing()

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     49                 renderer.start_filter()
     50 
---> 51             return draw(artist, renderer, *args, **kwargs)
     52         finally:
     53             if artist.get_agg_filter() is not None:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/figure.py in draw(self, renderer)
   2789             self.patch.draw(renderer)
   2790             mimage._draw_list_compositing_images(
-> 2791                 renderer, self, artists, self.suppressComposite)
   2792 
   2793             for sfig in self.subfigs:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    130     if not_composite or not has_images:
    131         for a in artists:
--> 132             a.draw(renderer)
    133     else:
    134         # Composite any adjacent images together

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     49                 renderer.start_filter()
     50 
---> 51             return draw(artist, renderer, *args, **kwargs)
     52         finally:
     53             if artist.get_agg_filter() is not None:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/_api/deprecation.py in wrapper(*inner_args, **inner_kwargs)
    429                          else deprecation_addendum,
    430                 **kwargs)
--> 431         return func(*inner_args, **inner_kwargs)
    432 
    433     return wrapper

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe)
   2919             renderer.stop_rasterizing()
   2920 
-> 2921         mimage._draw_list_compositing_images(renderer, self, artists)
   2922 
   2923         renderer.close_group('axes')

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    130     if not_composite or not has_images:
    131         for a in artists:
--> 132             a.draw(renderer)
    133     else:
    134         # Composite any adjacent images together

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     49                 renderer.start_filter()
     50 
---> 51             return draw(artist, renderer, *args, **kwargs)
     52         finally:
     53             if artist.get_agg_filter() is not None:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/axis.py in draw(self, renderer, *args, **kwargs)
   1153         self._update_label_position(renderer)
   1154 
-> 1155         self.label.draw(renderer)
   1156 
   1157         self._update_offset_text_position(ticklabelBoxes, ticklabelBoxes2)

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     49                 renderer.start_filter()
     50 
---> 51             return draw(artist, renderer, *args, **kwargs)
     52         finally:
     53             if artist.get_agg_filter() is not None:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/text.py in draw(self, renderer)
    677 
    678         with _wrap_text(self) as textobj:
--> 679             bbox, info, descent = textobj._get_layout(renderer)
    680             trans = textobj.get_transform()
    681 

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/text.py in _get_layout(self, renderer)
    313             if clean_line:
    314                 w, h, d = renderer.get_text_width_height_descent(
--> 315                     clean_line, self._fontproperties, ismath=ismath)
    316             else:
    317                 w = h = d = 0

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/backends/backend_agg.py in get_text_width_height_descent(self, s, prop, ismath)
    233         if ismath:
    234             ox, oy, width, height, descent, fonts, used_characters = \
--> 235                 self.mathtext_parser.parse(s, self.dpi, prop)
    236             return width, height, descent
    237 

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/mathtext.py in parse(self, s, dpi, prop, _force_standard_ps_fonts)
    450         # mathtext.fontset rcParams also affect the parse (e.g. by affecting
    451         # the glyph metrics).
--> 452         return self._parse_cached(s, dpi, prop, _force_standard_ps_fonts)
    453 
    454     @functools.lru_cache(50)

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/mathtext.py in _parse_cached(self, s, dpi, prop, force_standard_ps_fonts)
    471             self.__class__._parser = _mathtext.Parser()
    472 
--> 473         box = self._parser.parse(s, font_output, fontsize, dpi)
    474         font_output.set_canvas_size(box.width, box.height, box.depth)
    475         return font_output.get_results(box)

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/_mathtext.py in parse(self, s, fonts_object, fontsize, dpi)
   2280                                         err.line,
   2281                                         " " * (err.column - 1) + "^",
-> 2282                                         str(err)])) from err
   2283         self._state_stack = None
   2284         self._em_width_cache = {}

ValueError: 
\langle H \rangle(\gamma)
^
Unknown symbol: \langle, found '\'  (at char 0), (line:1, col:1)
<Figure size 576x432 with 1 Axes>

Computing the unmitigated landscape

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

gammas = np.linspace(0, 2 * np.pi, 50)
expectations = [executor_with_noise(variational_circuit(g)) for g in gammas]

The following code plots these values for visualization along with the noiseless landscape.

plt.figure(figsize=(8, 6))
plt.plot(gammas, noiseless_expectations, color="g", linewidth=3, label="Noiseless")
plt.scatter(gammas, expectations, color="r", label="Unmitigated")
plt.title(rf"Energy landscape", fontsize=16)
plt.xlabel(r"Ansatz angle $\gamma$", fontsize=16)
plt.ylabel(r"$\langle H \rangle(\gamma)$", fontsize=16)
plt.legend(fontsize=14)
plt.ylim(-1, 1);
plt.show()
---------------------------------------------------------------------------
ParseFatalException                       Traceback (most recent call last)
~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/_mathtext.py in parse(self, s, fonts_object, fontsize, dpi)
   2276         try:
-> 2277             result = self._expression.parseString(s)
   2278         except ParseBaseException as err:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/pyparsing/core.py in parse_string(self, instring, parse_all, parseAll)
   1106                 # catch and re-raise exception from here, clearing out pyparsing internal stack trace
-> 1107                 raise exc.with_traceback(None)
   1108         else:

ParseFatalException: Unknown symbol: \langle, found '\'  (at char 0), (line:1, col:1)

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/IPython/core/formatters.py in __call__(self, obj)
    339                 pass
    340             else:
--> 341                 return printer(obj)
    342             # Finally look for special method names
    343             method = get_real_method(obj, self.print_method)

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/IPython/core/pylabtools.py in <lambda>(fig)
    251 
    252     if 'png' in formats:
--> 253         png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
    254     if 'retina' in formats or 'png2x' in formats:
    255         png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/IPython/core/pylabtools.py in print_figure(fig, fmt, bbox_inches, **kwargs)
    135         FigureCanvasBase(fig)
    136 
--> 137     fig.canvas.print_figure(bytes_io, **kw)
    138     data = bytes_io.getvalue()
    139     if fmt == 'svg':

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2228                        else suppress())
   2229                 with ctx:
-> 2230                     self.figure.draw(renderer)
   2231 
   2232             if bbox_inches:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     72     @wraps(draw)
     73     def draw_wrapper(artist, renderer, *args, **kwargs):
---> 74         result = draw(artist, renderer, *args, **kwargs)
     75         if renderer._rasterizing:
     76             renderer.stop_rasterizing()

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     49                 renderer.start_filter()
     50 
---> 51             return draw(artist, renderer, *args, **kwargs)
     52         finally:
     53             if artist.get_agg_filter() is not None:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/figure.py in draw(self, renderer)
   2789             self.patch.draw(renderer)
   2790             mimage._draw_list_compositing_images(
-> 2791                 renderer, self, artists, self.suppressComposite)
   2792 
   2793             for sfig in self.subfigs:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    130     if not_composite or not has_images:
    131         for a in artists:
--> 132             a.draw(renderer)
    133     else:
    134         # Composite any adjacent images together

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     49                 renderer.start_filter()
     50 
---> 51             return draw(artist, renderer, *args, **kwargs)
     52         finally:
     53             if artist.get_agg_filter() is not None:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/_api/deprecation.py in wrapper(*inner_args, **inner_kwargs)
    429                          else deprecation_addendum,
    430                 **kwargs)
--> 431         return func(*inner_args, **inner_kwargs)
    432 
    433     return wrapper

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe)
   2919             renderer.stop_rasterizing()
   2920 
-> 2921         mimage._draw_list_compositing_images(renderer, self, artists)
   2922 
   2923         renderer.close_group('axes')

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    130     if not_composite or not has_images:
    131         for a in artists:
--> 132             a.draw(renderer)
    133     else:
    134         # Composite any adjacent images together

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     49                 renderer.start_filter()
     50 
---> 51             return draw(artist, renderer, *args, **kwargs)
     52         finally:
     53             if artist.get_agg_filter() is not None:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/axis.py in draw(self, renderer, *args, **kwargs)
   1153         self._update_label_position(renderer)
   1154 
-> 1155         self.label.draw(renderer)
   1156 
   1157         self._update_offset_text_position(ticklabelBoxes, ticklabelBoxes2)

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     49                 renderer.start_filter()
     50 
---> 51             return draw(artist, renderer, *args, **kwargs)
     52         finally:
     53             if artist.get_agg_filter() is not None:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/text.py in draw(self, renderer)
    677 
    678         with _wrap_text(self) as textobj:
--> 679             bbox, info, descent = textobj._get_layout(renderer)
    680             trans = textobj.get_transform()
    681 

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/text.py in _get_layout(self, renderer)
    313             if clean_line:
    314                 w, h, d = renderer.get_text_width_height_descent(
--> 315                     clean_line, self._fontproperties, ismath=ismath)
    316             else:
    317                 w = h = d = 0

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/backends/backend_agg.py in get_text_width_height_descent(self, s, prop, ismath)
    233         if ismath:
    234             ox, oy, width, height, descent, fonts, used_characters = \
--> 235                 self.mathtext_parser.parse(s, self.dpi, prop)
    236             return width, height, descent
    237 

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/mathtext.py in parse(self, s, dpi, prop, _force_standard_ps_fonts)
    450         # mathtext.fontset rcParams also affect the parse (e.g. by affecting
    451         # the glyph metrics).
--> 452         return self._parse_cached(s, dpi, prop, _force_standard_ps_fonts)
    453 
    454     @functools.lru_cache(50)

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/mathtext.py in _parse_cached(self, s, dpi, prop, force_standard_ps_fonts)
    471             self.__class__._parser = _mathtext.Parser()
    472 
--> 473         box = self._parser.parse(s, font_output, fontsize, dpi)
    474         font_output.set_canvas_size(box.width, box.height, box.depth)
    475         return font_output.get_results(box)

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/_mathtext.py in parse(self, s, fonts_object, fontsize, dpi)
   2280                                         err.line,
   2281                                         " " * (err.column - 1) + "^",
-> 2282                                         str(err)])) from err
   2283         self._state_stack = None
   2284         self._em_width_cache = {}

ValueError: 
\langle H \rangle(\gamma)
^
Unknown symbol: \langle, found '\'  (at char 0), (line:1, col:1)
<Figure size 576x432 with 1 Axes>

Computing the mitigated landscape

We now repeat the same task but use Mitiq to mitigate errors. We initialize a RichardsonFactory with scale factors [1, 3, 5] and we get a mitigated executor as follows.

fac = RichardsonFactory(scale_factors=[1, 3, 5])
mitigated_executor = mitigate_executor(executor_with_noise, factory=fac)

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

mitigated_expectations = [mitigated_executor(variational_circuit(g)) for g in gammas]

Let us visualize the mitigated landscape alongside the unmitigated and noiseless landscapes.

plt.figure(figsize=(8, 6))
plt.plot(gammas, noiseless_expectations, color="g", linewidth=3, label="Noiseless")
plt.scatter(gammas, expectations, color="r", label="Unmitigated")
plt.scatter(gammas, mitigated_expectations, color="b", label="Mitigated")
plt.title(rf"Energy landscape", fontsize=16)
plt.xlabel(r"Variational angle $\gamma$", fontsize=16)
plt.ylabel(r"$\langle H \rangle(\gamma)$", fontsize=16)
plt.legend(fontsize=14)
plt.ylim(-1.5, 1.5);
plt.show()
---------------------------------------------------------------------------
ParseFatalException                       Traceback (most recent call last)
~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/_mathtext.py in parse(self, s, fonts_object, fontsize, dpi)
   2276         try:
-> 2277             result = self._expression.parseString(s)
   2278         except ParseBaseException as err:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/pyparsing/core.py in parse_string(self, instring, parse_all, parseAll)
   1106                 # catch and re-raise exception from here, clearing out pyparsing internal stack trace
-> 1107                 raise exc.with_traceback(None)
   1108         else:

ParseFatalException: Unknown symbol: \langle, found '\'  (at char 0), (line:1, col:1)

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/IPython/core/formatters.py in __call__(self, obj)
    339                 pass
    340             else:
--> 341                 return printer(obj)
    342             # Finally look for special method names
    343             method = get_real_method(obj, self.print_method)

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/IPython/core/pylabtools.py in <lambda>(fig)
    251 
    252     if 'png' in formats:
--> 253         png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
    254     if 'retina' in formats or 'png2x' in formats:
    255         png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/IPython/core/pylabtools.py in print_figure(fig, fmt, bbox_inches, **kwargs)
    135         FigureCanvasBase(fig)
    136 
--> 137     fig.canvas.print_figure(bytes_io, **kw)
    138     data = bytes_io.getvalue()
    139     if fmt == 'svg':

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2228                        else suppress())
   2229                 with ctx:
-> 2230                     self.figure.draw(renderer)
   2231 
   2232             if bbox_inches:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     72     @wraps(draw)
     73     def draw_wrapper(artist, renderer, *args, **kwargs):
---> 74         result = draw(artist, renderer, *args, **kwargs)
     75         if renderer._rasterizing:
     76             renderer.stop_rasterizing()

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     49                 renderer.start_filter()
     50 
---> 51             return draw(artist, renderer, *args, **kwargs)
     52         finally:
     53             if artist.get_agg_filter() is not None:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/figure.py in draw(self, renderer)
   2789             self.patch.draw(renderer)
   2790             mimage._draw_list_compositing_images(
-> 2791                 renderer, self, artists, self.suppressComposite)
   2792 
   2793             for sfig in self.subfigs:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    130     if not_composite or not has_images:
    131         for a in artists:
--> 132             a.draw(renderer)
    133     else:
    134         # Composite any adjacent images together

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     49                 renderer.start_filter()
     50 
---> 51             return draw(artist, renderer, *args, **kwargs)
     52         finally:
     53             if artist.get_agg_filter() is not None:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/_api/deprecation.py in wrapper(*inner_args, **inner_kwargs)
    429                          else deprecation_addendum,
    430                 **kwargs)
--> 431         return func(*inner_args, **inner_kwargs)
    432 
    433     return wrapper

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe)
   2919             renderer.stop_rasterizing()
   2920 
-> 2921         mimage._draw_list_compositing_images(renderer, self, artists)
   2922 
   2923         renderer.close_group('axes')

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    130     if not_composite or not has_images:
    131         for a in artists:
--> 132             a.draw(renderer)
    133     else:
    134         # Composite any adjacent images together

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     49                 renderer.start_filter()
     50 
---> 51             return draw(artist, renderer, *args, **kwargs)
     52         finally:
     53             if artist.get_agg_filter() is not None:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/axis.py in draw(self, renderer, *args, **kwargs)
   1153         self._update_label_position(renderer)
   1154 
-> 1155         self.label.draw(renderer)
   1156 
   1157         self._update_offset_text_position(ticklabelBoxes, ticklabelBoxes2)

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     49                 renderer.start_filter()
     50 
---> 51             return draw(artist, renderer, *args, **kwargs)
     52         finally:
     53             if artist.get_agg_filter() is not None:

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/text.py in draw(self, renderer)
    677 
    678         with _wrap_text(self) as textobj:
--> 679             bbox, info, descent = textobj._get_layout(renderer)
    680             trans = textobj.get_transform()
    681 

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/text.py in _get_layout(self, renderer)
    313             if clean_line:
    314                 w, h, d = renderer.get_text_width_height_descent(
--> 315                     clean_line, self._fontproperties, ismath=ismath)
    316             else:
    317                 w = h = d = 0

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/backends/backend_agg.py in get_text_width_height_descent(self, s, prop, ismath)
    233         if ismath:
    234             ox, oy, width, height, descent, fonts, used_characters = \
--> 235                 self.mathtext_parser.parse(s, self.dpi, prop)
    236             return width, height, descent
    237 

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/mathtext.py in parse(self, s, dpi, prop, _force_standard_ps_fonts)
    450         # mathtext.fontset rcParams also affect the parse (e.g. by affecting
    451         # the glyph metrics).
--> 452         return self._parse_cached(s, dpi, prop, _force_standard_ps_fonts)
    453 
    454     @functools.lru_cache(50)

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/mathtext.py in _parse_cached(self, s, dpi, prop, force_standard_ps_fonts)
    471             self.__class__._parser = _mathtext.Parser()
    472 
--> 473         box = self._parser.parse(s, font_output, fontsize, dpi)
    474         font_output.set_canvas_size(box.width, box.height, box.depth)
    475         return font_output.get_results(box)

~/checkouts/readthedocs.org/user_builds/mitiq/envs/stable/lib/python3.7/site-packages/matplotlib/_mathtext.py in parse(self, s, fonts_object, fontsize, dpi)
   2280                                         err.line,
   2281                                         " " * (err.column - 1) + "^",
-> 2282                                         str(err)])) from err
   2283         self._state_stack = None
   2284         self._em_width_cache = {}

ValueError: 
\langle H \rangle(\gamma)
^
Unknown symbol: \langle, found '\'  (at char 0), (line:1, col:1)
<Figure size 576x432 with 1 Axes>

Noise usually tends to flatten expectation values towards a constant. Therefore error mitigation can be used to increase the visibility the landscape and this fact can simplify the energy minimization which is required in most variational algorithms such as VQE or QAOA.

We also observe that the minimum of mitigated energy approximates well the theoretical ground state which is equal to \(-1\). Indeed:

print(f"Minimum of the noisy landscape: {round(min(expectations), 3)}")
print(f"Minimum of the mitigated landscape: {round(min(mitigated_expectations), 3)}")
print(f"Theoretical groud state energy: {min(np.linalg.eigvals(hamiltonian))}")
Minimum of the noisy landscape: -0.639
Minimum of the mitigated landscape: -0.907
Theoretical groud state energy: -1.0