Beispiel #1
0
    def __init__(self,
                 qregs,
                 cregs,
                 ops,
                 scale=1.0,
                 style=None,
                 plot_barriers=True,
                 reverse_bits=False):

        if not HAS_MATPLOTLIB:
            raise ImportError('The class MatplotlibDrawer needs matplotlib. '
                              'Run "pip install matplotlib" before.')

        self._ast = None
        self._scale = DEFAULT_SCALE * scale
        self._creg = []
        self._qreg = []
        self._registers(cregs, qregs)
        self._ops = ops

        self._qreg_dict = collections.OrderedDict()
        self._creg_dict = collections.OrderedDict()
        self._cond = {
            'n_lines': 0,
            'xmax': 0,
            'ymax': 0,
        }
        config = user_config.get_config()
        if config and (style is None):
            config_style = config.get('circuit_mpl_style', 'default')
            if config_style == 'default':
                self._style = DefaultStyle()
            elif config_style == 'bw':
                self._style = BWStyle()
        elif style is False:
            self._style = BWStyle()
        else:
            self._style = DefaultStyle()

        self.plot_barriers = plot_barriers
        self.reverse_bits = reverse_bits
        if style:
            if isinstance(style, dict):
                self._style.set_style(style)
            elif isinstance(style, str):
                with open(style, 'r') as infile:
                    dic = json.load(infile)
                self._style.set_style(dic)

        self.figure = plt.figure()
        self.figure.patch.set_facecolor(color=self._style.bg)
        self.ax = self.figure.add_subplot(111)
        self.ax.axis('off')
        self.ax.set_aspect('equal')
        self.ax.tick_params(labelbottom=False,
                            labeltop=False,
                            labelleft=False,
                            labelright=False)

        self.x_offset = 0
Beispiel #2
0
    def _tgt_qubit(self, xy, fc=None, ec=None, ac=None,
                   add_width=None):
        if self._style.gc != DefaultStyle().gc:
            fc = self._style.gc
            ec = self._style.gc
        if fc is None:
            fc = self._style.dispcol['target']
        if ec is None:
            ec = self._style.lc
        if ac is None:
            ac = self._style.lc
        if add_width is None:
            add_width = 0.35

        linewidth = 2

        if self._style.dispcol['target'] == '#ffffff':
            add_width = self._style.colored_add_width

        xpos, ypos = xy

        box = patches.Circle(xy=(xpos, ypos), radius=HIG * 0.35,
                             fc=fc, ec=ec, linewidth=linewidth,
                             zorder=PORDER_GATE)
        self.ax.add_patch(box)
        # add '+' symbol
        self.ax.plot([xpos, xpos], [ypos - add_width * HIG,
                                    ypos + add_width * HIG],
                     color=ac, linewidth=linewidth, zorder=PORDER_GATE+1)

        self.ax.plot([xpos - add_width * HIG, xpos + add_width * HIG],
                     [ypos, ypos], color=ac, linewidth=linewidth,
                     zorder=PORDER_GATE+1)
Beispiel #3
0
    def _gate(self, xy, fc=None, wide=False, text=None, subtext=None):
        xpos, ypos = xy

        if wide:
            if subtext:
                boxes_wide = round(max(len(subtext), len(text)) / 10, 1) or 1
                wid = WID * 1.5 * boxes_wide
            else:
                boxes_wide = round(len(text) / 10) or 1
                wid = WID * 2.2 * boxes_wide
        else:
            wid = WID
        if fc:
            _fc = fc
        elif self._style.gc != DefaultStyle().gc:
            _fc = self._style.gc
        elif text and text in self._style.dispcol:
            _fc = self._style.dispcol[text]
        else:
            _fc = self._style.gc

        box = patches.Rectangle(
            xy=(xpos - 0.5 * wid, ypos - 0.5 * HIG), width=wid, height=HIG,
            fc=_fc, ec=self._style.edge_color, linewidth=1.5, zorder=PORDER_GATE)
        self.ax.add_patch(box)

        if text:
            font_size = self._style.fs
            sub_font_size = self._style.sfs
            # check if gate is not unitary
            if text in ['reset']:
                disp_color = self._style.not_gate_lc
                sub_color = self._style.not_gate_lc
                font_size = self._style.math_fs

            else:
                disp_color = self._style.gt
                sub_color = self._style.sc

            if text in self._style.dispcol:
                disp_text = "${}$".format(self._style.disptex[text])
            else:
                disp_text = text

            if subtext:
                self.ax.text(xpos, ypos + 0.15 * HIG, disp_text, ha='center',
                             va='center', fontsize=font_size,
                             color=disp_color, clip_on=True,
                             zorder=PORDER_TEXT)
                self.ax.text(xpos, ypos - 0.3 * HIG, subtext, ha='center',
                             va='center', fontsize=sub_font_size,
                             color=sub_color, clip_on=True,
                             zorder=PORDER_TEXT)
            else:
                self.ax.text(xpos, ypos, disp_text, ha='center', va='center',
                             fontsize=font_size,
                             color=disp_color,
                             clip_on=True,
                             zorder=PORDER_TEXT)
Beispiel #4
0
 def _ctrl_qubit(self, xy, fc=None, ec=None):
     if self._style.gc != DefaultStyle().gc:
         fc = self._style.gc
         ec = self._style.gc
     if fc is None:
         fc = self._style.lc
     if ec is None:
         ec = self._style.lc
     xpos, ypos = xy
     box = patches.Circle(xy=(xpos, ypos), radius=WID * 0.15,
                          fc=fc, ec=ec,
                          linewidth=1.5, zorder=PORDER_GATE)
     self.ax.add_patch(box)
Beispiel #5
0
    def __init__(
        self,
        qubits,
        clbits,
        ops,
        scale,
        reverse_bits=False,
        plot_barriers=True,
        layout=None,
        initial_state=False,
        cregbundle=False,
        global_phase=None,
        qregs=None,
        cregs=None,
    ):
        """QCircuitImage initializer.

        Args:
            qubits (list[Qubit]): list of qubits
            clbits (list[Clbit]): list of clbits
            ops (list[list[DAGNode]]): list of circuit instructions, grouped by layer
            scale (float): image scaling
            reverse_bits (bool): when True, reverse the bit ordering of the registers
            plot_barriers (bool): Enable/disable drawing barriers in the output
               circuit. Defaults to True.
            layout (Layout or None): If present, the layout information will be
               included.
            initial_state (bool): Optional. Adds |0> in the beginning of the line. Default: `False`.
            cregbundle (bool): Optional. If set True bundle classical registers. Default: `False`.
            global_phase (float): Optional, the global phase for the circuit.
            qregs (list): List qregs present in the circuit.
            cregs (list): List of cregs present in the circuit.
        Raises:
            ImportError: If pylatexenc is not installed
        """
        # list of lists corresponding to layers of the circuit
        self.ops = ops

        # image scaling
        self.scale = 0.7 if scale is None else scale

        # Map of qregs to sizes
        self.qregs = {}

        # Map of cregs to sizes
        self.cregs = {}

        # List of qubits and cbits in order of appearance in code and image
        # May also include ClassicalRegisters if cregbundle=True
        self.ordered_bits = []

        # Map from registers to the list they appear in the image
        self.img_regs = {}

        # Array to hold the \\LaTeX commands to generate a circuit image.
        self._latex = []

        # Variable to hold image depth (width)
        self.img_depth = 0

        # Variable to hold image width (height)
        self.img_width = 0

        # Variable to hold total circuit depth
        self.sum_column_widths = 0

        # Variable to hold total circuit width
        self.sum_wire_heights = 0

        # em points of separation between circuit columns
        self.column_separation = 1

        # em points of separation between circuit wire
        self.wire_separation = 0

        # presence of "box" or "target" determines wire spacing
        self.has_box = False
        self.has_target = False
        self.layout = layout
        self.initial_state = initial_state
        self.reverse_bits = reverse_bits
        self.plot_barriers = plot_barriers

        #################################
        self.qubit_list = qubits
        self.ordered_bits = qubits + clbits
        self.cregs = {reg: reg.size for reg in cregs}

        self.bit_locations = {
            bit: {
                "register": register,
                "index": index
            }
            for register in cregs + qregs for index, bit in enumerate(register)
        }
        for index, bit in list(enumerate(qubits)) + list(enumerate(clbits)):
            if bit not in self.bit_locations:
                self.bit_locations[bit] = {"register": None, "index": index}

        self.cregbundle = cregbundle
        # If there is any custom instruction that uses clasiscal bits
        # then cregbundle is forced to be False.
        for layer in self.ops:
            for op in layer:
                if op.name not in {"measure"} and op.cargs:
                    self.cregbundle = False

        self.cregs_bits = [
            self.bit_locations[bit]["register"] for bit in clbits
        ]
        self.img_regs = {bit: ind for ind, bit in enumerate(self.ordered_bits)}

        if self.cregbundle:
            self.img_width = len(qubits) + len(self.cregs)
        else:
            self.img_width = len(self.img_regs)
        self.global_phase = global_phase

        self._style = DefaultStyle().style
Beispiel #6
0
    def _custom_multiqubit_gate(self, xy, cxy=None, fc=None, wide=True, text=None,
                                subtext=None):
        xpos = min([x[0] for x in xy])
        ypos = min([y[1] for y in xy])
        ypos_max = max([y[1] for y in xy])

        if cxy:
            ypos = min([y[1] for y in cxy])
        if wide:
            if subtext:
                boxes_length = round(max([len(text), len(subtext)]) / 6) or 1
            else:
                boxes_length = math.ceil(len(text) / 6) or 1
            wid = WID * 2.5 * boxes_length
        else:
            wid = WID

        if fc:
            _fc = fc
        else:
            if self._style.name != 'bw':
                if self._style.gc != DefaultStyle().gc:
                    _fc = self._style.gc
                else:
                    _fc = self._style.dispcol['multi']
                _ec = self._style.dispcol['multi']
            else:
                _fc = self._style.gc

        qubit_span = abs(ypos) - abs(ypos_max) + 1
        height = HIG + (qubit_span - 1)
        box = patches.Rectangle(
            xy=(xpos - 0.5 * wid, ypos - .5 * HIG),
            width=wid, height=height,
            fc=_fc,
            ec=self._style.dispcol['multi'],
            linewidth=1.5, zorder=PORDER_GATE)
        self.ax.add_patch(box)
        # Annotate inputs
        for bit, y in enumerate([x[1] for x in xy]):
            self.ax.text(xpos - 0.45 * wid, y, str(bit), ha='left', va='center',
                         fontsize=self._style.fs, color=self._style.gt,
                         clip_on=True, zorder=PORDER_TEXT)

        if text:

            disp_text = text
            if subtext:
                self.ax.text(xpos, ypos + 0.5 * height, disp_text, ha='center',
                             va='center', fontsize=self._style.fs,
                             color=self._style.gt, clip_on=True,
                             zorder=PORDER_TEXT)
                self.ax.text(xpos, ypos + 0.3 * height, subtext, ha='center',
                             va='center', fontsize=self._style.sfs,
                             color=self._style.sc, clip_on=True,
                             zorder=PORDER_TEXT)
            else:
                self.ax.text(xpos, ypos + .5 * (qubit_span - 1), disp_text,
                             ha='center',
                             va='center',
                             fontsize=self._style.fs,
                             color=self._style.gt,
                             clip_on=True,
                             zorder=PORDER_TEXT,
                             wrap=True)
Beispiel #7
0
    def _load_style(self, style):
        current_style = DefaultStyle().style
        style_name = 'default'
        def_font_ratio = current_style['fs'] / current_style['sfs']

        config = user_config.get_config()
        if style is not None:
            if style is False:
                style_name = 'bw'
            elif isinstance(style, dict) and 'name' in style:
                style_name = style['name']
            elif isinstance(style, str):
                style_name = style
            elif config:
                style_name = config.get('circuit_mpl_style', 'default')
            elif not isinstance(style, (str, dict)):
                warn("style parameter '{}' must be a str or a dictionary."
                     " Will use default style.".format(style), UserWarning, 2)
        if style_name.endswith('.json'):
            style_name = style_name[:-5]

        # Search for file in 'styles' dir, then config_path, and finally 'cwd'
        style_path = []
        if style_name != 'default':
            style_name = style_name + '.json'
            spath = os.path.dirname(os.path.abspath(__file__))
            style_path.append(os.path.join(spath, 'styles', style_name))
            if config:
                config_path = config.get('circuit_mpl_style_path', '')
                if config_path:
                    for path in config_path:
                        style_path.append(os.path.normpath(os.path.join(path, style_name)))
            style_path.append(os.path.normpath(os.path.join('', style_name)))

            for path in style_path:
                exp_user = os.path.expanduser(path)
                if os.path.isfile(exp_user):
                    try:
                        with open(exp_user) as infile:
                            json_style = json.load(infile)
                        set_style(current_style, json_style)
                        break
                    except json.JSONDecodeError as e:
                        warn("Could not decode JSON in file '{}': {}. ".format(
                            path, str(e)) + "Will use default style.", UserWarning, 2)
                        break
                    except (OSError, FileNotFoundError):
                        warn("Error loading JSON file '{}'. Will use default style.".format(
                            path), UserWarning, 2)
                        break
            else:
                warn("Style JSON file '{}' not found in any of these locations: {}. Will use"
                     " default style.".format(style_name, ', '.join(style_path)), UserWarning, 2)

        if isinstance(style, dict):
            set_style(current_style, style)

        # If font/subfont ratio changes from default, have to scale width calculations for
        # subfont. Font change is auto scaled in the self._figure.set_size_inches call in draw()
        self._subfont_factor = current_style['sfs'] * def_font_ratio / current_style['fs']

        return current_style
Beispiel #8
0
    def __init__(self, qubits, clbits, ops, scale, reverse_bits=False,
                 plot_barriers=True, layout=None, initial_state=False,
                 cregbundle=False, global_phase=None):
        """QCircuitImage initializer.

        Args:
            qubits (list[Qubit]): list of qubits
            clbits (list[Clbit]): list of clbits
            ops (list[list[DAGNode]]): list of circuit instructions, grouped by layer
            scale (float): image scaling
            reverse_bits: when True, reverse the bit ordering of the registers
            plot_barriers (bool): Enable/disable drawing barriers in the output
               circuit. Defaults to True.
            layout (Layout or None): If present, the layout information will be
               included.
            initial_state (bool): Optional. Adds |0> in the beginning of the line. Default: `False`.
            cregbundle (bool): Optional. If set True bundle classical registers. Default: `False`.
            global_phase (float): Optional, the global phase for the circuit.
        Raises:
            ImportError: If pylatexenc is not installed
        """
        # list of lists corresponding to layers of the circuit
        self.ops = ops

        # image scaling
        self.scale = 0.7 if scale is None else scale

        # Map of qregs to sizes
        self.qregs = {}

        # Map of cregs to sizes
        self.cregs = {}

        # List of qregs and cregs in order of appearance in code and image
        self.ordered_regs = []

        # Map from registers to the list they appear in the image
        self.img_regs = {}

        # Array to hold the \\LaTeX commands to generate a circuit image.
        self._latex = []

        # Variable to hold image depth (width)
        self.img_depth = 0

        # Variable to hold image width (height)
        self.img_width = 0

        # Variable to hold total circuit depth
        self.sum_column_widths = 0

        # Variable to hold total circuit width
        self.sum_wire_heights = 0

        # em points of separation between circuit columns
        self.column_separation = 1

        # em points of separation between circuit wire
        self.wire_separation = 0

        # presence of "box" or "target" determines wire spacing
        self.has_box = False
        self.has_target = False
        self.layout = layout
        self.initial_state = initial_state
        self.reverse_bits = reverse_bits
        self.plot_barriers = plot_barriers

        #################################
        self.qubit_list = qubits
        self.ordered_regs = qubits + clbits
        self.cregs, self.cregs_bits = self._get_register_specs(clbits)
        self.img_regs = {bit: ind for ind, bit in
                         enumerate(self.ordered_regs)}
        if cregbundle:
            self.img_width = len(qubits) + len(self.cregs)
        else:
            self.img_width = len(self.img_regs)
        self.cregbundle = cregbundle
        self.global_phase = global_phase

        self._style = DefaultStyle().style
Beispiel #9
0
    def __init__(self, qregs, cregs, ops,
                 scale=1.0, style=None, plot_barriers=True,
                 reverse_bits=False, layout=None, fold=25, ax=None,
                 initial_state=False, cregbundle=True):

        if not HAS_MATPLOTLIB:
            raise ImportError('The class MatplotlibDrawer needs matplotlib. '
                              'To install, run "pip install matplotlib".')

        self._ast = None
        self._scale = DEFAULT_SCALE * scale
        self._creg = []
        self._qreg = []
        self._registers(cregs, qregs)
        self._ops = ops

        self._qreg_dict = collections.OrderedDict()
        self._creg_dict = collections.OrderedDict()
        self._cond = {
            'n_lines': 0,
            'xmax': 0,
            'ymax': 0,
        }
        config = user_config.get_config()
        if config and (style is None):
            config_style = config.get('circuit_mpl_style', 'default')
            if config_style == 'default':
                self._style = DefaultStyle()
            elif config_style == 'bw':
                self._style = BWStyle()
        elif style is False:
            self._style = BWStyle()
        else:
            self._style = DefaultStyle()

        self.plot_barriers = plot_barriers
        self.reverse_bits = reverse_bits
        self.layout = layout
        self.initial_state = initial_state
        if style and 'cregbundle' in style.keys():
            self.cregbundle = style['cregbundle']
            del style['cregbundle']
            warn("The style dictionary key 'cregbundle' has been deprecated and will be removed"
                 " in a future release. cregbundle is now a parameter to draw()."
                 " Example: circuit.draw(output='mpl', cregbundle=False)", DeprecationWarning, 2)
        else:
            self.cregbundle = cregbundle

        if style:
            if isinstance(style, dict):
                self._style.set_style(style)
            elif isinstance(style, str):
                with open(style, 'r') as infile:
                    dic = json.load(infile)
                self._style.set_style(dic)

        if ax is None:
            self.return_fig = True
            self.figure = plt.figure()
            self.figure.patch.set_facecolor(color=self._style.bg)
            self.ax = self.figure.add_subplot(111)
        else:
            self.return_fig = False
            self.ax = ax
            self.figure = ax.get_figure()

        self.x_offset = 0
        self._reg_long_text = 0

        # default is to use character table for text width,
        # but get_renderer will work with some mpl backends
        """fig = plt.figure()
        if hasattr(fig.canvas, 'get_renderer'):
            self.renderer = fig.canvas.get_renderer()
        else:
            self.renderer = None"""
        self.renderer = None

        self.fold = fold
        if self.fold < 2:
            self.fold = -1

        self.ax.axis('off')
        self.ax.set_aspect('equal')
        self.ax.tick_params(labelbottom=False, labeltop=False,
                            labelleft=False, labelright=False)

        # these char arrays are for finding text_width when not
        # using get_renderer method for the matplotlib backend
        self._latex_chars = ('$', '{', '}', '_', '\\left', '\\right',
                             '\\dagger', '\\rangle')
        self._latex_chars1 = ('\\mapsto', '\\pi', '\\;')
        self._char_list = {' ': (0.0958, 0.0583), '!': (0.1208, 0.0729), '"': (0.1396, 0.0875),
                           '#': (0.2521, 0.1562), '$': (0.1917, 0.1167), '%': (0.2854, 0.1771),
                           '&': (0.2333, 0.1458), "'": (0.0833, 0.0521), '(': (0.1167, 0.0729),
                           ')': (0.1167, 0.0729), '*': (0.15, 0.0938), '+': (0.25, 0.1562),
                           ',': (0.0958, 0.0583), '-': (0.1083, 0.0667), '.': (0.0958, 0.0604),
                           '/': (0.1021, 0.0625), '0': (0.1875, 0.1167), '1': (0.1896, 0.1167),
                           '2': (0.1917, 0.1188), '3': (0.1917, 0.1167), '4': (0.1917, 0.1188),
                           '5': (0.1917, 0.1167), '6': (0.1896, 0.1167), '7': (0.1917, 0.1188),
                           '8': (0.1896, 0.1188), '9': (0.1917, 0.1188), ':': (0.1021, 0.0604),
                           ';': (0.1021, 0.0604), '<': (0.25, 0.1542), '=': (0.25, 0.1562),
                           '>': (0.25, 0.1542), '?': (0.1583, 0.0979), '@': (0.2979, 0.1854),
                           'A': (0.2062, 0.1271), 'B': (0.2042, 0.1271), 'C': (0.2083, 0.1292),
                           'D': (0.2312, 0.1417), 'E': (0.1875, 0.1167), 'F': (0.1708, 0.1062),
                           'G': (0.2312, 0.1438), 'H': (0.225, 0.1396), 'I': (0.0875, 0.0542),
                           'J': (0.0875, 0.0542), 'K': (0.1958, 0.1208), 'L': (0.1667, 0.1042),
                           'M': (0.2583, 0.1604), 'N': (0.225, 0.1396), 'O': (0.2354, 0.1458),
                           'P': (0.1812, 0.1125), 'Q': (0.2354, 0.1458), 'R': (0.2083, 0.1292),
                           'S': (0.1896, 0.1188), 'T': (0.1854, 0.1125), 'U': (0.2208, 0.1354),
                           'V': (0.2062, 0.1271), 'W': (0.2958, 0.1833), 'X': (0.2062, 0.1271),
                           'Y': (0.1833, 0.1125), 'Z': (0.2042, 0.1271), '[': (0.1167, 0.075),
                           '\\': (0.1021, 0.0625), ']': (0.1167, 0.0729), '^': (0.2521, 0.1562),
                           '_': (0.1521, 0.0938), '`': (0.15, 0.0938), 'a': (0.1854, 0.1146),
                           'b': (0.1917, 0.1167), 'c': (0.1646, 0.1021), 'd': (0.1896, 0.1188),
                           'e': (0.1854, 0.1146), 'f': (0.1042, 0.0667), 'g': (0.1896, 0.1188),
                           'h': (0.1896, 0.1188), 'i': (0.0854, 0.0521), 'j': (0.0854, 0.0521),
                           'k': (0.1729, 0.1083), 'l': (0.0854, 0.0521), 'm': (0.2917, 0.1812),
                           'n': (0.1896, 0.1188), 'o': (0.1833, 0.1125), 'p': (0.1917, 0.1167),
                           'q': (0.1896, 0.1188), 'r': (0.125, 0.0771), 's': (0.1562, 0.0958),
                           't': (0.1167, 0.0729), 'u': (0.1896, 0.1188), 'v': (0.1771, 0.1104),
                           'w': (0.2458, 0.1521), 'x': (0.1771, 0.1104), 'y': (0.1771, 0.1104),
                           'z': (0.1562, 0.0979), '{': (0.1917, 0.1188), '|': (0.1, 0.0604),
                           '}': (0.1896, 0.1188)}