Source code for kaleidoscope.qiskit.backends.interactive.gate_map

# -*- 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.

# This code is part of Qiskit.
#
# (C) Copyright IBM 2017, 2019.
#
# 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.

"""Interactive gate map for IBM Quantum Experience devices."""

import plotly.graph_objects as go
from qiskit.providers.ibmq.ibmqbackend import IBMQBackend
from qiskit.test.mock.fake_backend import FakeBackend
from qiskit.providers.models.backendproperties import BackendProperties
from kaleidoscope.errors import KaleidoscopeError
from kaleidoscope.qiskit.services._simulators import DeviceSimulator
from kaleidoscope.qiskit.backends.pseudobackend import properties_to_pseudobackend
from kaleidoscope.interactive.plotly_wrapper import PlotlyWidget, PlotlyFigure
from kaleidoscope.qiskit.backends.device_layouts import LAYOUTS


[docs]def system_gate_map( backend, figsize=(None, None), label_qubits=True, qubit_size=None, line_width=None, font_size=None, qubit_colors="#2f4b7c", qubit_labels=None, line_colors="#2f4b7c", font_color="white", background_color='white', as_widget=False): """Plots an interactive gate map of a device. Args: backend (IBMQBackend or FakeBackend or DeviceSimulator or Properties): Plot the error map for a backend. figsize (tuple): Output figure size (wxh) in pixels. label_qubits (bool): Labels for the qubits. qubit_size (float): Size of qubit marker. line_width (float): Width of lines. font_size (float): Font size of qubit labels. qubit_colors (str or list): A list of colors for the qubits. If a single color is given, it's used for all qubits. qubit_labels (list): A list of qubit labels line_colors (str or list): A list of colors for each line from the coupling map. If a single color is given, it's used for all lines. font_color (str): The font color for the qubit labels. background_color (str): The background color, either 'white' or 'black'. as_widget (bool): Return the figure as a widget. Returns: PlotlyFigure or PlotlyWidget: Returned figure instance. Raises: KaleidoscopeError: Invalid input object. Example: .. jupyter-execute:: from qiskit import * from kaleidoscope.qiskit.backends import system_gate_map pro = IBMQ.load_account() backend = pro.backends.ibmq_vigo system_gate_map(backend) """ if not isinstance(backend, (IBMQBackend, DeviceSimulator, FakeBackend, BackendProperties)): raise KaleidoscopeError('Input is not a valid backend or properties object.') if isinstance(backend, BackendProperties): backend = properties_to_pseudobackend(backend) config = backend.configuration() n_qubits = config.n_qubits cmap = config.coupling_map # set coloring if isinstance(qubit_colors, str): qubit_colors = [qubit_colors] * n_qubits if isinstance(line_colors, str): line_colors = [line_colors] * len(cmap) if cmap else [] if str(n_qubits) in LAYOUTS['layouts'].keys(): kind = 'generic' if backend.name() in LAYOUTS['special_names']: if LAYOUTS['special_names'][backend.name()] in LAYOUTS['layouts'][str(n_qubits)]: kind = LAYOUTS['special_names'][backend.name()] grid_data = LAYOUTS['layouts'][str(n_qubits)][kind] else: fig = go.Figure() fig.update_layout(showlegend=False, plot_bgcolor=background_color, paper_bgcolor=background_color, width=figsize[0], height=figsize[1], margin=dict(t=30, l=0, r=0, b=0)) if as_widget: return PlotlyWidget(fig) return PlotlyFigure(fig) offset = 0 if cmap: if n_qubits in [14, 15, 16]: offset = 1 if qubit_size is None: qubit_size = 24 if font_size is None: font_size = 10 if line_width is None: line_width = 4 if figsize == (None, None): figsize = (400, 200) elif n_qubits == 27: if qubit_size is None: qubit_size = 24 if font_size is None: font_size = 10 if line_width is None: line_width = 4 if figsize == (None, None): figsize = (400, 300) else: if qubit_size is None: qubit_size = 32 if font_size is None: font_size = 14 if line_width is None: line_width = 6 if figsize == (None, None): figsize = (300, 300) else: if figsize == (None, None): figsize = (300, 300) if qubit_size is None: qubit_size = 30 fig = go.Figure() # Add lines for couplings if cmap: for ind, edge in enumerate(cmap): is_symmetric = False if edge[::-1] in cmap: is_symmetric = True y_start = grid_data[edge[0]][0] + offset x_start = grid_data[edge[0]][1] y_end = grid_data[edge[1]][0] + offset x_end = grid_data[edge[1]][1] if is_symmetric: if y_start == y_end: x_end = (x_end - x_start) / 2 + x_start x_mid = x_end y_mid = y_start elif x_start == x_end: y_end = (y_end - y_start) / 2 + y_start x_mid = x_start y_mid = y_end else: x_end = (x_end - x_start) / 2 + x_start y_end = (y_end - y_start) / 2 + y_start x_mid = x_end y_mid = y_end else: if y_start == y_end: x_mid = (x_end - x_start) / 2 + x_start y_mid = y_end elif x_start == x_end: x_mid = x_end y_mid = (y_end - y_start) / 2 + y_start else: x_mid = (x_end - x_start) / 2 + x_start y_mid = (y_end - y_start) / 2 + y_start fig.add_trace( go.Scatter(x=[x_start, x_mid, x_end], y=[-y_start, -y_mid, -y_end], mode="lines", hoverinfo='none', line=dict(width=line_width, color=line_colors[ind]))) # Add the qubits themselves qubit_text = [] qubit_str = "<b>Qubit {}" for num in range(n_qubits): qubit_text.append(qubit_str.format(qubit_labels[num] if qubit_labels else num)) if qubit_labels is None: qubit_labels = [str(ii) for ii in range(n_qubits)] if n_qubits > 50: if qubit_size is None: qubit_size = 20 if font_size is None: font_size = 9 fig.add_trace(go.Scatter( x=[d[1] for d in grid_data], y=[-d[0]-offset for d in grid_data], mode="markers+text", marker=go.scatter.Marker(size=qubit_size, color=qubit_colors, opacity=1), text=qubit_labels if label_qubits else '', textposition="middle center", textfont=dict(size=font_size, color=font_color), hoverinfo="text" if label_qubits else 'none', hovertext=qubit_text)) fig.update_xaxes(visible=False) _range = None if offset: _range = [-3.5, 0.5] fig.update_yaxes(visible=False, range=_range) fig.update_layout(showlegend=False, plot_bgcolor=background_color, paper_bgcolor=background_color, width=figsize[0], height=figsize[1], margin=dict(t=30, l=0, r=0, b=0)) if as_widget: return PlotlyWidget(fig) return PlotlyFigure(fig)