def _circuit_diagram_info_(
        self, args: 'cirq.CircuitDiagramInfoArgs'
    ) -> Optional['protocols.CircuitDiagramInfo']:
        n = len(self.controls)

        sub_args = protocols.CircuitDiagramInfoArgs(
            known_qubit_count=(
                args.known_qubit_count - n if args.known_qubit_count is not None else None
            ),
            known_qubits=(args.known_qubits[n:] if args.known_qubits is not None else None),
            use_unicode_characters=args.use_unicode_characters,
            precision=args.precision,
            qubit_map=args.qubit_map,
        )
        sub_info = protocols.circuit_diagram_info(self.sub_operation, sub_args, None)
        if sub_info is None:
            return NotImplemented

        def get_symbol(vals):
            if tuple(vals) == (1,):
                return '@'
            return f"({','.join(map(str, vals))})"

        wire_symbols = (*(get_symbol(vals) for vals in self.control_values), *sub_info.wire_symbols)
        return protocols.CircuitDiagramInfo(
            wire_symbols=wire_symbols,
            exponent=sub_info.exponent,
            exponent_qubit_index=None
            if sub_info.exponent_qubit_index is None
            else sub_info.exponent_qubit_index + 1,
        )
Esempio n. 2
0
    def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs'
                              ) -> 'cirq.CircuitDiagramInfo':
        sub_args = protocols.CircuitDiagramInfoArgs(
            known_qubit_count=(args.known_qubit_count - self.num_controls()
                               if args.known_qubit_count is not None else None),
            known_qubits=(args.known_qubits[self.num_controls():]
                          if args.known_qubits is not None else None),
            use_unicode_characters=args.use_unicode_characters,
            precision=args.precision,
            qubit_map=args.qubit_map)
        sub_info = protocols.circuit_diagram_info(self.sub_gate,
                                                  sub_args,
                                                  None)
        if sub_info is None:
            return NotImplemented

        def get_symbol(vals):
            if tuple(vals) == (1,):
                return '@'
            return '({})'.format(','.join(map(str, vals)))

        return protocols.CircuitDiagramInfo(
            wire_symbols=(*(get_symbol(vals) for vals in self.control_values),
                          *sub_info.wire_symbols),
            exponent=sub_info.exponent)
Esempio n. 3
0
 def _circuit_diagram_info_(
     self, args: 'cirq.CircuitDiagramInfoArgs'
 ) -> Optional['protocols.CircuitDiagramInfo']:
     sub_args = protocols.CircuitDiagramInfoArgs(
         known_qubit_count=args.known_qubit_count,
         known_qubits=args.known_qubits,
         use_unicode_characters=args.use_unicode_characters,
         precision=args.precision,
         label_map=args.label_map,
     )
     sub_info = protocols.circuit_diagram_info(self._sub_operation,
                                               sub_args, None)
     if sub_info is None:
         return NotImplemented  # coverage: ignore
     control_count = len({k for c in self._conditions for k in c.keys})
     wire_symbols = sub_info.wire_symbols + ('^', ) * control_count
     if any(not isinstance(c, value.KeyCondition)
            for c in self._conditions):
         wire_symbols = (wire_symbols[0] + '(conditions=[' + ', '.join(
             str(c) for c in self._conditions) + '])', ) + wire_symbols[1:]
     exponent_qubit_index = None
     if sub_info.exponent_qubit_index is not None:
         exponent_qubit_index = sub_info.exponent_qubit_index + control_count
     elif sub_info.exponent is not None:
         exponent_qubit_index = control_count
     return protocols.CircuitDiagramInfo(
         wire_symbols=wire_symbols,
         exponent=sub_info.exponent,
         exponent_qubit_index=exponent_qubit_index,
     )
Esempio n. 4
0
 def _circuit_diagram_info_(
     self, args: protocols.CircuitDiagramInfoArgs
 ) -> protocols.CircuitDiagramInfo:
     sub_args = protocols.CircuitDiagramInfoArgs(
         known_qubit_count=(args.known_qubit_count - self.num_controls() if
                            args.known_qubit_count is not None else None),
         known_qubits=(args.known_qubits[self.num_controls():]
                       if args.known_qubits is not None else None),
         use_unicode_characters=args.use_unicode_characters,
         precision=args.precision,
         qubit_map=args.qubit_map)
     sub_info = protocols.circuit_diagram_info(self.sub_gate, sub_args,
                                               None)
     if sub_info is None:
         return NotImplemented
     return protocols.CircuitDiagramInfo(
         wire_symbols=('@', ) * self.num_controls() + sub_info.wire_symbols,
         exponent=sub_info.exponent)
Esempio n. 5
0
    def _circuit_diagram_info_(
        self, args: 'cirq.CircuitDiagramInfoArgs'
    ) -> Optional['protocols.CircuitDiagramInfo']:
        n = len(self.controls)

        sub_args = protocols.CircuitDiagramInfoArgs(
            known_qubit_count=(args.known_qubit_count - n if
                               args.known_qubit_count is not None else None),
            known_qubits=(args.known_qubits[n:]
                          if args.known_qubits is not None else None),
            use_unicode_characters=args.use_unicode_characters,
            precision=args.precision,
            label_map=args.label_map,
        )
        sub_info = protocols.circuit_diagram_info(self.sub_operation, sub_args,
                                                  None)
        if sub_info is None:
            return NotImplemented

        def get_symbol(vals):
            if tuple(vals) == (1, ):
                return '@'
            return f"({','.join(map(str, vals))})"

        wire_symbols = (*(get_symbol(vals) for vals in self.control_values),
                        *sub_info.wire_symbols)
        exponent_qubit_index = None
        if sub_info.exponent_qubit_index is not None:
            exponent_qubit_index = sub_info.exponent_qubit_index + len(
                self.control_values)
        elif sub_info.exponent is not None:
            # For a multi-qubit `sub_operation`, if the `exponent_qubit_index` is None, the qubit
            # on which the exponent gets drawn in the controlled case (smallest ordered qubit of
            # sub_operation) can be different from the uncontrolled case (lexicographically largest
            # qubit of sub_operation). See tests for example.
            exponent_qubit_index = len(self.control_values)
        return protocols.CircuitDiagramInfo(
            wire_symbols=wire_symbols,
            exponent=sub_info.exponent,
            exponent_qubit_index=exponent_qubit_index,
        )
Esempio n. 6
0
    def _circuit_diagram_info_(
        self, args: protocols.CircuitDiagramInfoArgs
    ) -> Optional[protocols.CircuitDiagramInfo]:
        n = len(self.controls)

        sub_args = protocols.CircuitDiagramInfoArgs(
            known_qubit_count=(args.known_qubit_count - n if
                               args.known_qubit_count is not None else None),
            known_qubits=(args.known_qubits[n:]
                          if args.known_qubits is not None else None),
            use_unicode_characters=args.use_unicode_characters,
            precision=args.precision,
            qubit_map=args.qubit_map)
        sub_info = protocols.circuit_diagram_info(self.sub_operation, sub_args,
                                                  None)
        if sub_info is None:
            return NotImplemented

        return protocols.CircuitDiagramInfo(wire_symbols=('@', ) * n +
                                            sub_info.wire_symbols,
                                            exponent=sub_info.exponent)
Esempio n. 7
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()