@@ -70,6 +70,125 @@ def _duplicate_time_at_bottom(cls, lines: str) -> None:
7070 # duplicate times after an empty line
7171 lines .append (lines [0 ])
7272
73+ @classmethod
74+ def _process_item_properties (
75+ cls , item : Instruction | ResultType , circuit_qubits : QubitSet
76+ ) -> tuple [QubitSet , QubitSet , QubitSet , QubitSet , list [str ], dict | None ]:
77+ """Extract properties from an item, keeping original logic structure."""
78+ if isinstance (item , ResultType ) and not item .target :
79+ target_qubits = circuit_qubits
80+ control_qubits = QubitSet ()
81+ target_and_control = target_qubits .union (control_qubits )
82+ qubits = circuit_qubits
83+ ascii_symbols = [item .ascii_symbols [0 ]] * len (circuit_qubits )
84+ map_control_qubit_states = None
85+ elif isinstance (item , Instruction ) and isinstance (item .operator , CompilerDirective ):
86+ if item .operator .name == "Barrier" :
87+ target_qubits = item .target
88+ if not target_qubits :
89+ # Barrier without qubits - single barrier across all qubits
90+ target_qubits = circuit_qubits
91+ qubits = circuit_qubits
92+ ascii_symbols = [item .ascii_symbols [0 ]] * len (circuit_qubits )
93+ else :
94+ # Barrier with specific qubits
95+ qubits = target_qubits
96+ ascii_symbols = [item .ascii_symbols [0 ]] * len (target_qubits )
97+ target_and_control = target_qubits
98+ else :
99+ target_qubits = circuit_qubits
100+ control_qubits = QubitSet ()
101+ target_and_control = target_qubits .union (control_qubits )
102+ qubits = circuit_qubits
103+ ascii_symbol = item .ascii_symbols [0 ]
104+ marker = "*" * len (ascii_symbol )
105+ num_after = len (circuit_qubits ) - 1
106+ after = ["|" ] * (num_after - 1 ) + ([marker ] if num_after else [])
107+ ascii_symbols = [ascii_symbol , * after ]
108+ control_qubits = QubitSet ()
109+ map_control_qubit_states = None
110+ elif (
111+ isinstance (item , Instruction )
112+ and isinstance (item .operator , Gate )
113+ and item .operator .name == "GPhase"
114+ ):
115+ target_qubits = circuit_qubits
116+ control_qubits = QubitSet ()
117+ target_and_control = QubitSet ()
118+ qubits = circuit_qubits
119+ ascii_symbols = cls ._qubit_line_character () * len (circuit_qubits )
120+ map_control_qubit_states = None
121+ else :
122+ if isinstance (item .target , list ):
123+ target_qubits = reduce (QubitSet .union , map (QubitSet , item .target ), QubitSet ())
124+ else :
125+ target_qubits = item .target
126+ control_qubits = getattr (item , "control" , QubitSet ())
127+ control_state = getattr (item , "control_state" , "1" * len (control_qubits ))
128+ map_control_qubit_states = dict (zip (control_qubits , control_state , strict = True ))
129+ target_and_control = target_qubits .union (control_qubits )
130+ qubits = QubitSet (range (min (target_and_control ), max (target_and_control ) + 1 ))
131+ ascii_symbols = item .ascii_symbols
132+
133+ return (
134+ target_qubits ,
135+ control_qubits ,
136+ target_and_control ,
137+ qubits ,
138+ ascii_symbols ,
139+ map_control_qubit_states ,
140+ )
141+
142+ @classmethod
143+ def _update_qubit_symbols_and_connections (
144+ cls ,
145+ item : Instruction | ResultType ,
146+ qubit : int ,
147+ target_qubits : QubitSet ,
148+ control_qubits : QubitSet ,
149+ target_and_control : QubitSet ,
150+ ascii_symbols : list [str ],
151+ symbols : dict ,
152+ connections : dict ,
153+ map_control_qubit_states : dict | None ,
154+ ) -> None :
155+ """Update symbols and connections for a qubit, keeping original logic."""
156+ # Determine if the qubit is part of the item or in the middle of a
157+ # multi qubit item.
158+ if qubit in target_qubits :
159+ item_qubit_index = next (index for index , q in enumerate (target_qubits ) if q == qubit )
160+ power_string = (
161+ f"^{ power } "
162+ if (
163+ (power := getattr (item , "power" , 1 )) != 1
164+ # this has the limitation of not printing the power
165+ # when a user has a gate genuinely named C, but
166+ # is necessary to enable proper printing of custom
167+ # gates with built-in control qubits
168+ and ascii_symbols [item_qubit_index ] != "C"
169+ )
170+ else ""
171+ )
172+ idx = item_qubit_index
173+ symbols [qubit ] = (
174+ f"({ ascii_symbols [idx ]} { power_string } )" if power_string else ascii_symbols [idx ]
175+ )
176+ elif qubit in control_qubits :
177+ symbols [qubit ] = "C" if map_control_qubit_states [qubit ] else "N"
178+ else :
179+ symbols [qubit ] = "|"
180+
181+ # Set the margin to be a connector if not on the first qubit
182+ if target_and_control and qubit != min (target_and_control ):
183+ is_barrier = (
184+ isinstance (item , Instruction )
185+ and isinstance (item .operator , CompilerDirective )
186+ and item .operator .name == "Barrier"
187+ )
188+ # Add vertical lines for non-barriers or global barriers (no target)
189+ if not is_barrier or not item .target :
190+ connections [qubit ] = "above"
191+
73192 @classmethod
74193 def _create_diagram_column (
75194 cls ,
@@ -91,78 +210,27 @@ def _create_diagram_column(
91210 connections = dict .fromkeys (circuit_qubits , "none" )
92211
93212 for item in items :
94- if isinstance (item , ResultType ) and not item .target :
95- target_qubits = circuit_qubits
96- control_qubits = QubitSet ()
97- target_and_control = target_qubits .union (control_qubits )
98- qubits = circuit_qubits
99- ascii_symbols = [item .ascii_symbols [0 ]] * len (circuit_qubits )
100- elif isinstance (item , Instruction ) and isinstance (item .operator , CompilerDirective ):
101- target_qubits = circuit_qubits
102- control_qubits = QubitSet ()
103- target_and_control = target_qubits .union (control_qubits )
104- qubits = circuit_qubits
105- ascii_symbol = item .ascii_symbols [0 ]
106- marker = "*" * len (ascii_symbol )
107- num_after = len (circuit_qubits ) - 1
108- after = ["|" ] * (num_after - 1 ) + ([marker ] if num_after else [])
109- ascii_symbols = [ascii_symbol , * after ]
110- elif (
111- isinstance (item , Instruction )
112- and isinstance (item .operator , Gate )
113- and item .operator .name == "GPhase"
114- ):
115- target_qubits = circuit_qubits
116- control_qubits = QubitSet ()
117- target_and_control = QubitSet ()
118- qubits = circuit_qubits
119- ascii_symbols = cls ._qubit_line_character () * len (circuit_qubits )
120- else :
121- if isinstance (item .target , list ):
122- target_qubits = reduce (QubitSet .union , map (QubitSet , item .target ), QubitSet ())
123- else :
124- target_qubits = item .target
125- control_qubits = getattr (item , "control" , QubitSet ())
126- control_state = getattr (item , "control_state" , "1" * len (control_qubits ))
127- map_control_qubit_states = dict (zip (control_qubits , control_state , strict = True ))
128-
129- target_and_control = target_qubits .union (control_qubits )
130- qubits = QubitSet (range (min (target_and_control ), max (target_and_control ) + 1 ))
131-
132- ascii_symbols = item .ascii_symbols
213+ (
214+ target_qubits ,
215+ control_qubits ,
216+ target_and_control ,
217+ qubits ,
218+ ascii_symbols ,
219+ map_control_qubit_states ,
220+ ) = cls ._process_item_properties (item , circuit_qubits )
133221
134222 for qubit in qubits :
135- # Determine if the qubit is part of the item or in the middle of a
136- # multi qubit item.
137- if qubit in target_qubits :
138- item_qubit_index = [ # noqa: RUF015
139- index for index , q in enumerate (target_qubits ) if q == qubit
140- ][0 ]
141- power_string = (
142- f"^{ power } "
143- if (
144- (power := getattr (item , "power" , 1 )) != 1
145- # this has the limitation of not printing the power
146- # when a user has a gate genuinely named C, but
147- # is necessary to enable proper printing of custom
148- # gates with built-in control qubits
149- and ascii_symbols [item_qubit_index ] != "C"
150- )
151- else ""
152- )
153- symbols [qubit ] = (
154- f"({ ascii_symbols [item_qubit_index ]} { power_string } )"
155- if power_string
156- else ascii_symbols [item_qubit_index ]
157- )
158- elif qubit in control_qubits :
159- symbols [qubit ] = "C" if map_control_qubit_states [qubit ] else "N"
160- else :
161- symbols [qubit ] = "|"
162-
163- # Set the margin to be a connector if not on the first qubit
164- if target_and_control and qubit != min (target_and_control ):
165- connections [qubit ] = "above"
223+ cls ._update_qubit_symbols_and_connections (
224+ item ,
225+ qubit ,
226+ target_qubits ,
227+ control_qubits ,
228+ target_and_control ,
229+ ascii_symbols ,
230+ symbols ,
231+ connections ,
232+ map_control_qubit_states ,
233+ )
166234
167235 return cls ._create_output (symbols , connections , circuit_qubits , global_phase )
168236
0 commit comments