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, )
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)
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, )
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)
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, )
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)
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()