Source code for kaleidoscope.qiskit.backends.mpl.cnot_err

# -*- coding: utf-8 -*-

# This file is part of Kaleidoscope.
#
# (C) Copyright IBM 2020.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
# pylint: disable=invalid-unary-operand-type

"""CNOT error density plot"""

import numpy as np
from scipy.stats import gaussian_kde
import matplotlib as mpl
import matplotlib.pyplot as plt
from qiskit.providers.models.backendproperties import BackendProperties
from kaleidoscope.colors import COLORS1, COLORS2, COLORS3, COLORS4, COLORS5, COLORS14
from kaleidoscope.errors import KaleidoscopeError
from kaleidoscope.qiskit.backends.pseudobackend import properties_to_pseudobackend


[docs]def cnot_error_density(backends, figsize=None, colors=None, offset=None, scale='log', covariance_factor=0.1, xlim=None, text_xval=None, xticks=None): """Plot CNOT error distribution for one or more IBMQ backends. Parameters: backends (list or IBMQBackend or BackendProperties): A single or ist of IBMQBackend instances or properties. figsize (tuple): Optional figure size in inches. colors (list): A list of Matplotlib compatible colors to plot with. offset (float): Positive offset for spacing out the backends. scale (str): 'linear' or 'log' scaling of x-axis. covariance_factor (float): Sets the width of the gaussian for each point. xlim (list or tuple): Optional lower and upper limits of cnot error values. text_xval (float): Optional xaxis value at which to start the backend text. xticks (list): Optional list of xaxis ticks to plot. Returns: Figure: A matplotlib Figure instance. Raises: KaleidoscopeError: A backend with < 2 qubits was passed. KaleidoscopeError: Number of colors did not match number of backends. Example: .. jupyter-execute:: from qiskit import * from kaleidoscope.qiskit.backends import cnot_error_density provider = IBMQ.load_account() backends = [] backends.append(provider.backends.ibmq_vigo) backends.append(provider.backends.ibmq_ourense) backends.append(provider.backends.ibmq_valencia) backends.append(provider.backends.ibmq_santiago) cnot_error_density(backends) """ if not isinstance(backends, list): backends = [backends] for idx, back in enumerate(backends): if isinstance(back, BackendProperties): backends[idx] = properties_to_pseudobackend(back) for back in backends: if back.configuration().n_qubits < 2: raise KaleidoscopeError('Number of backend qubits must be > 1') if scale not in ['linear', 'log']: raise KaleidoscopeError("scale must be 'linear' or 'log'.") # Attempt to autosize if figsize=None if figsize is None: if len(backends) > 1: fig = plt.figure(figsize=(12, len(backends)*1.5)) else: fig = plt.figure(figsize=(12, 2)) else: fig = plt.figure(figsize=figsize) text_color = 'k' if offset is None: offset = 100 if len(backends) > 3 else 200 offset = -offset if colors is None: if len(backends) == 1: colors = COLORS1 elif len(backends) == 2: colors = COLORS2 elif len(backends) == 3: colors = COLORS3 elif len(backends) == 4: colors = COLORS4 elif len(backends) == 5: colors = COLORS5 else: colors = [COLORS14[kk % 14] for kk in range(len(backends))] else: if len(colors) != len(backends): raise KaleidoscopeError('Number of colors does not match number of backends.') cx_errors = [] for idx, back in enumerate(backends): back_props = back.properties().to_dict() cx_errs = [] meas_errs = [] for gate in back_props['gates']: if len(gate['qubits']) == 2: # Ignore cx gates with values of 1.0 if gate['parameters'][0]['value'] != 1.0: cx_errs.append(gate['parameters'][0]['value']) for qubit in back_props['qubits']: for item in qubit: if item['name'] == 'readout_error': meas_errs.append(item['value']) cx_errors.append(100*np.asarray(cx_errs)) max_cx_err = max([cerr.max() for cerr in cx_errors]) min_cx_err = min([cerr.min() for cerr in cx_errors]) if xlim is None: if scale == 'linear': xlim = [0, 1.5*max_cx_err] else: xlim = [10**np.floor(np.log10(min_cx_err)), 10**np.ceil(np.log10(max_cx_err))] if text_xval is None: if scale == 'linear': text_xval = 0.8*xlim[1] else: text_xval = 0.6*xlim[1] for idx, back in enumerate(backends): cx_density = gaussian_kde(cx_errors[idx]) xs = np.linspace(xlim[0], xlim[1], 2500) cx_density.covariance_factor = lambda: covariance_factor cx_density._compute_covariance() if scale == 'linear': plt.plot(xs, 100*cx_density(xs)+offset*idx, zorder=idx, color=colors[idx]) else: plt.semilogx(xs, 100*cx_density(xs)+offset*idx, zorder=idx, color=colors[idx]) plt.fill_between(xs, offset*idx, 100*cx_density(xs)+offset*idx, zorder=idx, color=colors[idx]) qv_val = back.configuration().quantum_volume if qv_val: qv = "(QV"+str(qv_val)+")" else: qv = '' bname = back.name().split('_')[-1].title()+" {}".format(qv) plt.text(text_xval, offset*idx+0.2*(-offset), bname, fontsize=20, color=colors[idx]) fig.axes[0].get_yaxis().set_visible(False) # get rid of the frame for spine in plt.gca().spines.values(): spine.set_visible(False) if xticks is None: if scale == 'linear': xticks = np.round(np.linspace(xlim[0], xlim[1], 4), 2) else: xticks = np.asarray(xticks) if xticks is not None: plt.xticks(np.floor(xticks), labels=np.floor(xticks), color=text_color) plt.xticks(fontsize=18) plt.xlim(xlim) plt.tick_params(axis='x', colors=text_color) plt.xlabel('Gate Error', fontsize=18, color=text_color) plt.title('CNOT Error Distributions', fontsize=18, color=text_color) fig.tight_layout() if mpl.get_backend() in ['module://ipykernel.pylab.backend_inline', 'nbAgg']: plt.close(fig) return fig