Skip to content

Commit

Permalink
display tags by str instead of repr in circuit diagrams (#6530)
Browse files Browse the repository at this point in the history
Use more readable rendering of tagged operations in diagrams.

Fixes: #6411
  • Loading branch information
richrines1 authored Apr 10, 2024
1 parent 1bec6b5 commit c18feed
Show file tree
Hide file tree
Showing 13 changed files with 221 additions and 223 deletions.
2 changes: 1 addition & 1 deletion cirq-core/cirq/circuits/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -2630,7 +2630,7 @@ def _draw_moment_in_diagram(
if desc:
y = max(label_map.values(), default=0) + 1
if tags and include_tags:
desc = desc + str(tags)
desc = desc + f"[{', '.join(map(str, tags))}]"
out_diagram.write(x0, y, desc)

if not non_global_ops:
Expand Down
4 changes: 2 additions & 2 deletions cirq-core/cirq/circuits/circuit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2305,9 +2305,9 @@ def test_diagram_global_phase(circuit_cls):
cirq.testing.assert_has_diagram(
c,
"""\
2: ───X──────────
2: ───X────────
π['tag']""",
π[tag]""",
)


Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/ops/raw_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,7 @@ def _circuit_diagram_info_(
# Add tag to wire symbol if it exists.
if sub_op_info is not NotImplemented and args.include_tags and sub_op_info.wire_symbols:
sub_op_info.wire_symbols = (
sub_op_info.wire_symbols[0] + str(list(self._tags)),
sub_op_info.wire_symbols[0] + f"[{', '.join(map(str, self._tags))}]",
) + sub_op_info.wire_symbols[1:]
return sub_op_info

Expand Down
28 changes: 13 additions & 15 deletions cirq-core/cirq/ops/raw_types_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,17 +490,17 @@ def test_cannot_remap_non_measurement_gate():

def test_circuit_diagram():
class TaggyTag:
"""Tag with a custom repr function to test circuit diagrams."""
"""Tag with a custom str function to test circuit diagrams."""

def __repr__(self):
return 'TaggyTag()'
def __str__(self):
return '<taggy>'

h = cirq.H(cirq.GridQubit(1, 1))
tagged_h = h.with_tags('tag1')
non_string_tag_h = h.with_tags(TaggyTag())

expected = cirq.CircuitDiagramInfo(
wire_symbols=("H['tag1']",),
wire_symbols=("H[tag1]",),
exponent=1.0,
connected=True,
exponent_qubit_index=None,
Expand All @@ -511,14 +511,14 @@ def __repr__(self):
assert cirq.circuit_diagram_info(tagged_h, args) == cirq.circuit_diagram_info(h)

c = cirq.Circuit(tagged_h)
diagram_with_tags = "(1, 1): ───H['tag1']───"
diagram_with_tags = "(1, 1): ───H[tag1]───"
diagram_without_tags = "(1, 1): ───H───"
assert str(cirq.Circuit(tagged_h)) == diagram_with_tags
assert c.to_text_diagram() == diagram_with_tags
assert c.to_text_diagram(include_tags=False) == diagram_without_tags

c = cirq.Circuit(non_string_tag_h)
diagram_with_non_string_tag = "(1, 1): ───H[TaggyTag()]───"
diagram_with_non_string_tag = "(1, 1): ───H[<taggy>]───"
assert c.to_text_diagram() == diagram_with_non_string_tag
assert c.to_text_diagram(include_tags=False) == diagram_without_tags

Expand All @@ -531,7 +531,7 @@ def test_circuit_diagram_tagged_global_phase():
# Just global phase in a circuit
assert cirq.circuit_diagram_info(global_phase, default='default') == 'default'
cirq.testing.assert_has_diagram(
cirq.Circuit(global_phase), "\n\nglobal phase: π['tag0']", use_unicode_characters=True
cirq.Circuit(global_phase), "\n\nglobal phase: π[tag0]", use_unicode_characters=True
)
cirq.testing.assert_has_diagram(
cirq.Circuit(global_phase),
Expand All @@ -558,9 +558,7 @@ def _circuit_diagram_info_(
no_wire_symbol_op = NoWireSymbols(coefficient=-1.0)().with_tags('tag0')
assert cirq.circuit_diagram_info(no_wire_symbol_op, default='default') == expected
cirq.testing.assert_has_diagram(
cirq.Circuit(no_wire_symbol_op),
"\n\nglobal phase: π['tag0']",
use_unicode_characters=True,
cirq.Circuit(no_wire_symbol_op), "\n\nglobal phase: π[tag0]", use_unicode_characters=True
)

# Two global phases in one moment
Expand All @@ -570,9 +568,9 @@ def _circuit_diagram_info_(
cirq.testing.assert_has_diagram(
c,
"""\
a: ─────────────X───────────────────
a: ─────────────X───────────────
global phase: π['tag1', 'tag2']""",
global phase: π[tag1, tag2]""",
use_unicode_characters=True,
precision=2,
)
Expand All @@ -583,9 +581,9 @@ def _circuit_diagram_info_(
cirq.testing.assert_has_diagram(
c,
"""\
a: ─────────────X['x_tag']─────X──────────────
a: ─────────────X[x_tag]─────X────────────
global phase: 0.5π['tag1'] 0.5π['tag2']
global phase: 0.5π[tag1] 0.5π[tag2]
""",
use_unicode_characters=True,
include_tags=True,
Expand All @@ -603,7 +601,7 @@ def __repr__(self):
q = cirq.GridQubit(1, 1)
expected = "(1, 1): ───guess-i-will-repr───"
assert cirq.Circuit(NoCircuitDiagram()(q)).to_text_diagram() == expected
expected = "(1, 1): ───guess-i-will-repr['taggy']───"
expected = "(1, 1): ───guess-i-will-repr[taggy]───"
assert cirq.Circuit(NoCircuitDiagram()(q).with_tags('taggy')).to_text_diagram() == expected


Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/protocols/circuit_diagram_info_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ def _op_info_with_fallback(

# Add tags onto the representation, if they exist
if op.tags:
name += f'{list(op.tags)}'
name += f"[{', '.join(map(str, op.tags))}]"

# Include ordering in the qubit labels.
symbols = (name,) + tuple(f'#{i + 1}' for i in range(1, len(op.qubits)))
Expand Down
46 changes: 23 additions & 23 deletions cirq-core/cirq/transformers/merge_k_qubit_gates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,13 @@ def test_merge_complex_circuit_preserving_moment_structure():
cirq.testing.assert_has_diagram(
c_orig,
'''
0: ───H───@───@───H───@───X───────@─────────────────X───X['ignore']───@───X───
│ │ │ │ │ ║
1: ───H───┼───X───────@───────Y───X───@['ignore']───────Y─────────────X───╫───
│ │
2: ───H───X───────────────────────────X─────────────────Z─────────────M───╫───
║ ║
a: ═══════════════════════════════════════════════════════════════════@═══^═══
0: ───H───@───@───H───@───X───────@───────────────X───X[ignore]───@───X───
│ │ │ │ │ ║
1: ───H───┼───X───────@───────Y───X───@[ignore]───────Y───────────X───╫───
│ │ ║
2: ───H───X───────────────────────────X───────────────Z───────────M───╫───
║ ║
a: ═══════════════════════════════════════════════════════════════@═══^═══
''',
)
component_id = 0
Expand All @@ -147,15 +147,15 @@ def rewriter_merge_to_circuit_op(op: 'cirq.CircuitOperation') -> 'cirq.OP_TREE':
cirq.testing.assert_has_diagram(
cirq.drop_empty_moments(c_new),
'''
[ 0: ───H───@─── ] [ 0: ───────@───H───@───X───@───X─── ] [ 0: ───────@─── ]
0: ───[ │ ]────────[ │ │ │ ]──────────────────────X['ignore']───────────[ │ ]────────X───
[ 2: ───H───X─── ]['1'] [ 1: ───H───X───────@───Y───X─────── ]['2'] [ 1: ───Y───X─── ]['4'] ║
1: ───┼─────────────────────────#2────────────────────────────────────────────@['ignore']─────────────────────────#2────────────────────────╫───
2: ───#2──────────────────────────────────────────────────────────────────────X─────────────[ 2: ───Z─── ]['3']───M─────────────────────────╫───
a: ═══════════════════════════════════════════════════════════════════════════════════════════════════════════════@═════════════════════════^═══''',
[ 0: ───H───@─── ] [ 0: ───────@───H───@───X───@───X─── ] [ 0: ───────@─── ]
0: ───[ │ ]──────[ │ │ │ ]──────────────────X[ignore]───────────[ │ ]──────X───
[ 2: ───H───X─── ][1] [ 1: ───H───X───────@───Y───X─────── ][2] [ 1: ───Y───X─── ][4] ║
│ │
1: ───┼───────────────────────#2──────────────────────────────────────────@[ignore]───────────────────────#2──────────────────────╫───
2: ───#2──────────────────────────────────────────────────────────────────X───────────[ 2: ───Z─── ][3]───M───────────────────────╫───
a: ═══════════════════════════════════════════════════════════════════════════════════════════════════════@═══════════════════════^═══''',
)

component_id = 0
Expand All @@ -179,13 +179,13 @@ def rewriter_replace_with_decomp(op: 'cirq.CircuitOperation') -> 'cirq.OP_TREE':
cirq.testing.assert_has_diagram(
cirq.drop_empty_moments(c_new),
'''
0: ───T['1']───iSwap['1']───T['1']───T['2']───iSwap['2']───T['2']─────────────────X['ignore']───T['4']───iSwap['4']───T['4']───X───
1: ────────────┼─────────────────────T['2']───iSwap^0.5────T['2']───@['ignore']─────────────────T['4']───iSwap^0.5────T['4']───╫───
2: ───T['1']───iSwap^0.5────T['1']──────────────────────────────────X─────────────T['3']────────M──────────────────────────────╫───
a: ═════════════════════════════════════════════════════════════════════════════════════════════@══════════════════════════════^═══''',
0: ───T[1]───iSwap[1]────T[1]───T[2]───iSwap[2]────T[2]───────────────X[ignore]───T[4]───iSwap[4]────T[4]───X───
│ │
1: ──────────┼──────────────────T[2]───iSwap^0.5───T[2]───@[ignore]───────────────T[4]───iSwap^0.5───T[4]───╫───
2: ───T[1]───iSwap^0.5───T[1]─────────────────────────────X───────────T[3]────────M─────────────────────────╫───
a: ═══════════════════════════════════════════════════════════════════════════════@═════════════════════════^═══''',
)


Expand Down
28 changes: 14 additions & 14 deletions cirq-core/cirq/transformers/merge_single_qubit_gates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,27 +153,27 @@ def test_merge_single_qubit_moments_to_phxz():
cirq.testing.assert_has_diagram(
c_orig,
'''
0: ───X───────Y───@───X───────Y───Y['nocompile']───X───M───────────
1: ───X───T───Y───@───X───T───Y───Z────────────────────╫───X───X───
║ ║
2: ───────T───────Y───────T───────Z────────────────────╫───╫───────
║ ║
a: ════════════════════════════════════════════════════@═══^═══════
0: ───X───────Y───@───X───────Y───Y[nocompile]───X───M───────────
│ ║
1: ───X───T───Y───@───X───T───Y───Z──────────────────╫───X───X───
║ ║
2: ───────T───────Y───────T───────Z──────────────────╫───╫───────
║ ║
a: ══════════════════════════════════════════════════@═══^═══════
''',
)
context = cirq.TransformerContext(tags_to_ignore=("nocompile",))
c_new = cirq.merge_single_qubit_moments_to_phxz(c_orig, context=context)
cirq.testing.assert_has_diagram(
c_new,
'''
0: ───PhXZ(a=-0.5,x=0,z=-1)──────@───PhXZ(a=-0.5,x=0,z=-1)──────Y['nocompile']───X───M───────────
1: ───PhXZ(a=-0.25,x=0,z=0.75)───@───PhXZ(a=-0.25,x=0,z=0.75)───Z────────────────────╫───X───X───
║ ║
2: ───PhXZ(a=0.25,x=0,z=0.25)────Y───PhXZ(a=0.25,x=0,z=0.25)────Z────────────────────╫───╫───────
║ ║
a: ══════════════════════════════════════════════════════════════════════════════════@═══^═══════
0: ───PhXZ(a=-0.5,x=0,z=-1)──────@───PhXZ(a=-0.5,x=0,z=-1)──────Y[nocompile]───X───M───────────
│ ║
1: ───PhXZ(a=-0.25,x=0,z=0.75)───@───PhXZ(a=-0.25,x=0,z=0.75)───Z──────────────────╫───X───X───
║ ║
2: ───PhXZ(a=0.25,x=0,z=0.25)────Y───PhXZ(a=0.25,x=0,z=0.25)────Z──────────────────╫───╫───────
║ ║
a: ════════════════════════════════════════════════════════════════════════════════@═══^═══════
''',
)

Expand Down
Loading

0 comments on commit c18feed

Please sign in to comment.