Esempio n. 1
0
def _draw_moment_in_diagram(moment: Moment, ext: Extensions,
                            use_unicode_characters: bool,
                            qubit_map: Dict[QubitId, int],
                            out_diagram: TextDiagramDrawer,
                            precision: Optional[int]):
    if not moment.operations:
        return []

    x0 = out_diagram.width()
    for op in moment.operations:
        indices = [qubit_map[q] for q in op.qubits]
        y1 = min(indices)
        y2 = max(indices)

        # Find an available column.
        x = x0
        while any(
                out_diagram.content_present(x, y) for y in range(y1, y2 + 1)):
            x += 1

        # Draw vertical line linking the gate's qubits.
        if y2 > y1:
            out_diagram.vertical_line(x, y1, y2)

        # Print gate qubit labels.
        symbols = _get_operation_text_diagram_symbols(op, ext,
                                                      use_unicode_characters,
                                                      precision)
        for s, q in zip(symbols, op.qubits):
            out_diagram.write(x, qubit_map[q], s)

        # Add an exponent to the first label.
        exponent = _get_operation_text_diagram_exponent(op, ext, precision)
        if exponent is not None:
            out_diagram.write(x, y1, '^' + exponent)
Esempio n. 2
0
    def to_text_diagram_drawer(
        self,
        ext: Extensions = None,
        use_unicode_characters: bool = True,
        qubit_name_suffix: str = '',
        precision: Optional[int] = 3,
        qubit_order: ops.QubitOrderOrList = ops.QubitOrder.DEFAULT,
    ) -> TextDiagramDrawer:
        """Returns a TextDiagramDrawer with the circuit drawn into it.

        Args:
            ext: For extending gates to implement TextDiagrammableGate.
            use_unicode_characters: Determines if unicode characters are
                allowed (as opposed to ascii-only diagrams).
            qubit_name_suffix: Appended to qubit names in the diagram.
            precision: Number of digits to use when representing numbers.
            qubit_order: Determines how qubits are ordered in the diagram.

        Returns:
            The TextDiagramDrawer instance.
        """
        if ext is None:
            ext = Extensions()

        qubits = ops.QubitOrder.as_qubit_order(qubit_order).order_for(
            self.qubits())
        qubit_map = {qubits[i]: i for i in range(len(qubits))}

        diagram = TextDiagramDrawer()
        for q, i in qubit_map.items():
            diagram.write(0, i, str(q) + qubit_name_suffix)

        for moment in [Moment()] * 2 + self.moments + [Moment()]:
            _draw_moment_in_diagram(moment, ext, use_unicode_characters,
                                    qubit_map, diagram, precision)

        w = diagram.width()
        for i in qubit_map.values():
            diagram.horizontal_line(i, 0, w)

        return diagram
Esempio n. 3
0
    def to_text_diagram(
        self: 'cirq.Moment',
        *,
        xy_breakdown_func: Callable[['cirq.Qid'],
                                    Tuple[Any, Any]] = _default_breakdown,
        extra_qubits: Iterable['cirq.Qid'] = (),
        use_unicode_characters: bool = True,
        precision: Optional[int] = None,
        include_tags: bool = True,
    ):
        """
        Args:
            xy_breakdown_func: A function to split qubits/qudits into x and y
                components. For example, the default breakdown turns
                `cirq.GridQubit(row, col)` into the tuple `(col, row)` and
                `cirq.LineQubit(x)` into `(x, 0)`.
            extra_qubits: Extra qubits/qudits to include in the diagram, even
                if they don't have any operations applied in the moment.
            use_unicode_characters: Whether or not the output should use fancy
                unicode characters or stick to plain ASCII. Unicode characters
                look nicer, but some environments don't draw them with the same
                width as ascii characters (which ruins the diagrams).
            precision: How precise numbers, such as angles, should be. Use None
                for infinite precision, or an integer for a certain number of
                digits of precision.
            include_tags: Whether or not to include operation tags in the
                diagram.

        Returns:
            The text diagram rendered into text.
        """

        # Figure out where to place everything.
        qs = set(self.qubits) | set(extra_qubits)
        points = {xy_breakdown_func(q) for q in qs}
        x_keys = sorted({pt[0] for pt in points}, key=_SortByValFallbackToType)
        y_keys = sorted({pt[1] for pt in points}, key=_SortByValFallbackToType)
        x_map = {x_key: x + 2 for x, x_key in enumerate(x_keys)}
        y_map = {y_key: y + 2 for y, y_key in enumerate(y_keys)}
        qubit_positions = {}
        for q in qs:
            a, b = xy_breakdown_func(q)
            qubit_positions[q] = x_map[a], y_map[b]

        from cirq.circuits.text_diagram_drawer import TextDiagramDrawer

        diagram = TextDiagramDrawer()

        def cleanup_key(key: Any) -> Any:
            if isinstance(key, float) and key == int(key):
                return str(int(key))
            return str(key)

        # Add table headers.
        for key, x in x_map.items():
            diagram.write(x, 0, cleanup_key(key))
        for key, y in y_map.items():
            diagram.write(0, y, cleanup_key(key))
        diagram.horizontal_line(1, 0, len(x_map) + 2)
        diagram.vertical_line(1, 0, len(y_map) + 2)
        diagram.force_vertical_padding_after(0, 0)
        diagram.force_vertical_padding_after(1, 0)

        # Add operations.
        for op in self.operations:
            args = protocols.CircuitDiagramInfoArgs(
                known_qubits=op.qubits,
                known_qubit_count=len(op.qubits),
                use_unicode_characters=use_unicode_characters,
                qubit_map=None,
                precision=precision,
                include_tags=include_tags,
            )
            info = protocols.CircuitDiagramInfo._op_info_with_fallback(
                op, args=args)
            symbols = info._wire_symbols_including_formatted_exponent(args)
            for label, q in zip(symbols, op.qubits):
                x, y = qubit_positions[q]
                diagram.write(x, y, label)
            if info.connected:
                for q1, q2 in zip(op.qubits, op.qubits[1:]):
                    # Sort to get a more consistent orientation for diagonals.
                    # This reduces how often lines overlap in the diagram.
                    q1, q2 = sorted([q1, q2])

                    x1, y1 = qubit_positions[q1]
                    x2, y2 = qubit_positions[q2]
                    if x1 != x2:
                        diagram.horizontal_line(y1, x1, x2)
                    if y1 != y2:
                        diagram.vertical_line(x2, y1, y2)

        return diagram.render()