#
# Copyright © 2022-2024 University of Strasbourg. All Rights Reserved.
# Copyright © 2032-2024 QPerfect. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import mimiqcircuits as mc
import shutil
import math
def _string_with_square(arr, sep):
return f"[{sep.join(map(str, arr))}]"
def _find_unit_range(arr):
if len(arr) < 2:
return arr
narr = []
rangestart = arr[0]
rangestop = arr[0]
for v in arr[1:]:
if v == rangestop + 1:
rangestop = v
elif rangestart == rangestop:
narr.append(rangestart)
rangestart = v
rangestop = v
else:
narr.append(range(rangestart, rangestop + 1))
rangestart = v
rangestop = v
if rangestart == rangestop:
narr.append(rangestart)
else:
narr.append(range(rangestart, rangestop + 1))
return narr
def _gate_name_padding(qubits, bits, zvars):
nq = len(qubits)
qubits_padding = 0 if nq in [1, 0] else math.floor(math.log10(nq)) + 2
bitspadding = 0 if not bits else len(str(bits)) + 1
zvarspadding = 0 if not zvars else len(str(zvars)) + 1
return max(qubits_padding, bitspadding, zvarspadding)
[docs]
class AsciiCanvas:
def __init__(self, width=None):
if width is None:
_, self.width = 0, shutil.get_terminal_size().columns
self.width = width
self.data = []
[docs]
def get_rows(self):
return len(self.data)
[docs]
def get_cols(self):
return self.width
[docs]
def push_line(self):
self.data.append([" "] * self.width)
def __getitem__(self, position):
row, col = position
if row >= len(self.data):
return " "
return self.data[row][col]
def __setitem__(self, position, value):
row, col = position
while row >= self.get_rows():
self.push_line()
while col >= len(self.data[row]):
self.data[row].append(" ")
self.data[row][col] = value
def __str__(self):
return "\n".join("".join(row) for row in self.data if row)
[docs]
def draw_hline(self, row, col, width):
start_col, stop_col = min(col, col + width - 1), max(col, col + width - 1)
for i in range(start_col, stop_col + 1):
current_char = self[row, i]
# Check and replace characters based on conditions
if current_char == "│":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "├", "┼", "┤"
)
elif current_char == "┤":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "┼", "┼", "┤"
)
elif current_char == "├":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "├", "┼", "┼"
)
elif current_char == "╵":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "└", "┴", "┘"
)
elif current_char == "└":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "└", "┴", "┴"
)
elif current_char == "┘":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "┴", "┴", "┘"
)
elif current_char == "╷":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "┌", "┬", "┐"
)
elif current_char == "║":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╟", "╫", "╢"
)
elif current_char == "╟":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╟", "╫", "╫"
)
elif current_char == "╢":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╫", "╫", "╢"
)
elif current_char == "╶":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╶", "─", "─"
)
elif current_char == "╴":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "─", "─", "╴"
)
else:
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╶", "─", "╴"
)
return self
def _start_mid_stop(self, current, start, stop, start_char, mid_char, stop_char):
if current == start:
return start_char
elif current == stop:
return stop_char
return mid_char
[docs]
def draw_vline(self, row, col, height):
start_row, stop_row = min(row, row + height - 1), max(row, row + height - 1)
for i in range(start_row, stop_row + 1):
current_char = self[i, col]
if current_char == "─":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "┬", "┼", "┴"
)
elif current_char == "┴":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "┼", "┼", "┴"
)
elif current_char == "┬":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "┬", "┼", "┼"
)
elif current_char == "╴":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "┐", "┤", "┘"
)
elif current_char == "┐":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "┐", "┤", "┤"
)
elif current_char == "┘":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "┤", "┤", "┘"
)
elif current_char == "╶":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "┌", "├", "└"
)
elif current_char == "┌":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "┌", "├", "├"
)
elif current_char == "└":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "├", "├", "└"
)
elif current_char == "╵":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "│", "│", "╵"
)
elif current_char == "╷":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╷", "│", "│"
)
elif current_char == "═":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╤", "╪", "╧"
)
elif current_char == "╤":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╤", "╪", "╪"
)
elif current_char == "╧":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╪", "╪", "╧"
)
else:
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╷", "│", "╵"
)
return self
[docs]
def draw_double_hline(self, row, col, width):
start_col, stop_col = min(col, col + width - 1), max(col, col + width - 1)
for i in range(start_col, stop_col + 1):
if self[row, i] == "│":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╞", "╪", "╡"
)
elif self[row, i] == "╞":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╞", "╪", "╪"
)
elif self[row, i] == "╡":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╪", "╪", "╡"
)
elif self[row, i] == "╵":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╘", "╧", "╛"
)
elif self[row, i] == "╘":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╘", "╧", "╧"
)
elif self[row, i] == "╛":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╧", "╧", "╛"
)
elif self[row, i] == "╷":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╒", "╤", "╕"
)
elif self[row, i] == "╒":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╒", "╤", "╤"
)
elif self[row, i] == "╕":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╤", "╤", "╕"
)
elif self[row, i] == "║":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╠", "╬", "╣"
)
elif self[row, i] == "╠":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╠", "╬", "╣"
)
elif self[row, i] == "╣":
self[row, i] = self._start_mid_stop(
i, start_col, stop_col, "╠", "╬", "╣"
)
else:
self[row, i] = "═"
[docs]
def draw_double_vline(self, row, col, height):
start_row, stop_row = min(row, row + height - 1), max(row, row + height - 1)
for i in range(start_row, stop_row + 1):
if self[i, col] == "─":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╥", "╫", "╨"
)
elif self[i, col] == "╥":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╥", "╫", "╫"
)
elif self[i, col] == "╨":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╫", "╫", "╨"
)
elif self[i, col] == "╶":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╓", "╟", "╙"
)
elif self[i, col] == "╓":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╓", "╟", "╟"
)
elif self[i, col] == "╙":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╟", "╟", "╙"
)
elif self[i, col] == "╴":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╖", "╢", "╜"
)
elif self[i, col] == "╖":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╖", "╢", "╢"
)
elif self[i, col] == "╜":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╢", "╢", "╜"
)
elif self[i, col] == "═":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╦", "╬", "╩"
)
elif self[i, col] == "╩":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╬", "╬", "╩"
)
elif self[i, col] == "╦":
self[i, col] = self._start_mid_stop(
i, start_row, stop_row, "╦", "╬", "╬"
)
else:
self[i, col] = "║"
[docs]
def draw_fill(self, char, row, col, width, height):
for i in range(row, row + height):
for j in range(col, col + width):
self[i, j] = char
[docs]
def draw_empty(self, row, col, width, height):
for i in range(row, row + height):
while i >= len(self.data):
self.push_line()
for j in range(col, col + width):
while j >= len(self.data[i]):
self.data[i].append(" ")
if j == col and self.data[i][j] == "─":
self.data[i][j] = "╴"
elif j == col + width - 1 and self.data[i][j] == "─":
self.data[i][j] = "╶"
elif i == row and self.data[i][j] == "│":
self.data[i][j] = "╵"
elif i == row + height - 1 and self.data[i][j] == "│":
self.data[i][j] = "╷"
else:
self.data[i][j] = " "
[docs]
def draw_box(self, row, col, width, height, clean=False):
if clean:
self.draw_empty(row, col, width, height)
self.draw_hline(row, col, width)
self.draw_hline(row + height - 1, col, width)
self.draw_vline(row, col, height)
self.draw_vline(row, col + width - 1, height)
return self
[docs]
def draw_text(self, text, row, col):
for i, char in enumerate(text):
self[row, col + i] = char
return self
[docs]
def draw_vtext(self, text, row, col):
for i, char in enumerate(text):
self[row + i, col] = char
return self
[docs]
def reset(self):
self.data = []
return self
[docs]
class AsciiCircuit:
def __init__(self, width=None):
if width is None:
_, width = 0, shutil.get_terminal_size().columns
self.canvas = AsciiCanvas(width)
self.qubitrow = {}
self.bitrow = None
self.zvarrow = None
self.nonerow = None
self.currentcol = 0
[docs]
def set_current_col(self, col):
self.currentcol = max(self.currentcol, col)
[docs]
def get_current_col(self):
return self.currentcol
[docs]
def get_qubit_row(self, qubit):
return self.qubitrow.get(qubit)
[docs]
def get_bit_row(self):
return self.bitrow
[docs]
def get_zvars_row(self):
return self.zvarrow
[docs]
def reset(self):
self.canvas.reset()
self.qubitrow = {}
self.bitrow = None
self.zvars = None
self.nonerow = None
self.currentcol = 1
return self
[docs]
def draw_wires(self, qubits, bits, zvars):
# Draw qubit wires and labels
for i, q in enumerate(qubits):
row = i * 2 + 1
qubitstr = f"q[{q}]: "
self.canvas.draw_text(qubitstr, row, 1)
self.qubitrow[q] = row
self.set_current_col(len(qubitstr) + 1)
if len(bits) > 0:
row = len(qubits) * 2 + 3
bitstr = "c: "
self.canvas.draw_text(bitstr, row, 1)
self.bitrow = row
self.set_current_col(len(bitstr) + 1)
if len(zvars) > 0:
if len(bits) < 1:
row = (len(qubits)) * 2 + 3
else:
row = (len(qubits) + 1) * 2 + 3
zstr = "z: "
self.canvas.draw_text(zstr, row, 1)
self.zvarrow = row
self.set_current_col(len(zstr) + 1)
ccol = self.get_current_col() - 3
ccol = self.get_current_col()
# Fill space and draw horizontal line for qubits
for i in range(len(qubits)):
row = i * 2
self.canvas.draw_fill(" ", row, ccol, self.canvas.get_cols() - ccol, 1)
self.canvas.draw_hline(row + 1, ccol, self.canvas.get_cols() - ccol)
self.canvas.draw_fill(
" ", (len(qubits) - 1) * 2 + 3, ccol, self.canvas.get_cols() - ccol, 1
)
# Prepare space and draw double horizontal line for bits if more than one bit
if len(bits) > 0:
row = len(qubits) * 2 + 2
self.canvas.draw_fill(" ", row, ccol, self.canvas.get_cols() - ccol, 1)
self.canvas.draw_double_hline(row + 1, ccol, self.canvas.get_cols() - ccol)
if len(zvars) > 0:
if len(bits) < 1:
row = (len(qubits)) * 2 + 2
else:
row = (len(qubits) + 1) * 2 + 2
self.canvas.draw_fill(" ", row, ccol, self.canvas.get_cols() - ccol, 1)
self.canvas.draw_double_hline(row + 1, ccol, self.canvas.get_cols() - ccol)
self.set_current_col(ccol + 1)
return self
[docs]
def draw_operation(self, operation, qubits, bits=None, zvars=None):
# Initialize default values for bits and zvars if they are None
bits = bits or []
zvars = zvars or []
# Calculate padding for qubits, bits, and zvars
namepadding = _gate_name_padding(qubits, bits, zvars)
ccol = self.get_current_col()
qubitrow = [self.get_qubit_row(q) for q in qubits]
bitrow = self.get_bit_row()
zvarrow = self.get_zvars_row()
if not qubits and not bits and not zvars:
# Draw the None row only if it's not already drawn
if self.nonerow is None:
none_row_start = (
len(self.qubitrow)
+ (1 if self.bitrow else 0)
+ (1 if self.zvarrow else 0)
) * 2 + 3
self.nonerow = none_row_start
ccol = 0
self.canvas.draw_fill(
" ", none_row_start, ccol, self.canvas.get_cols(), 1
)
self.canvas.draw_double_hline(
none_row_start, ccol, self.canvas.get_cols()
)
# Now draw the operation on the None line
none_row = self.nonerow
ccol = self.get_current_col()
gw = operation.asciiwidth([], [], [])
self.canvas.draw_box(none_row - 1, ccol, gw, 3, clean=True) # 3 rows height
self.canvas.draw_text(str(operation), none_row, ccol + 1)
self.set_current_col(ccol + gw)
return self
# Determine start and stop rows for qubits, bits, and zvars
if bits or zvars:
qubit_startrow = min(qubitrow, default=float("inf"))
qubit_stoprow = max(qubitrow, default=0)
bits_startrow = bitrow if bits else float("inf")
bits_stoprow = bitrow if bits else 0
zvar_startrow = zvarrow if zvars else float("inf")
zvar_stoprow = zvarrow if zvars else 0
# Handle case where both qubits and zvars are present
if qubitrow and zvars:
# Draw box for qubits
qubit_gateheight = qubit_stoprow - qubit_startrow + 1
qubit_midrow = qubit_startrow + qubit_gateheight // 2
gw = operation.asciiwidth(qubits, bits, [])
# Calculate zvar width first
gw_zvar = operation.asciiwidth([], [], zvars)
# Ensure both boxes have the same width
gw = max(gw, gw_zvar)
midcol = ccol + gw // 2
self.canvas.draw_box(
qubit_startrow - 1, ccol, gw, qubit_gateheight + 2, clean=True
)
self.canvas.draw_text(
str(operation), qubit_midrow, ccol + namepadding - 1
)
# Draw zvars without a box, with adjusted spacing
self.canvas.draw_text(",".join(map(str, zvars)), zvarrow + 1, midcol)
# Draw vertical double line connecting qubits and zvars
self.canvas.draw_double_vline(
qubit_stoprow + 1, midcol, zvar_startrow - qubit_stoprow
)
endcol = ccol + gw
elif qubitrow and bits:
# Draw box for qubits
qubit_gateheight = qubit_stoprow - qubit_startrow + 1
qubit_midrow = qubit_startrow + qubit_gateheight // 2
gw_qubits = operation.asciiwidth(qubits, [], [])
gw_bits = operation.asciiwidth([], bits, [])
# Ensure the box for qubits is as wide as needed for both qubits and bits
gw = max(gw_qubits, gw_bits)
midcol = ccol + gw // 2
self.canvas.draw_box(
qubit_startrow - 1, ccol, gw, qubit_gateheight + 2, clean=True
)
self.canvas.draw_text(
str(operation), qubit_midrow, ccol + namepadding - 1
)
# Draw the bits below the qubits, centered horizontally
bitstr = ",".join(map(str, bits))
bit_start_col = midcol - len(bitstr) // 2
self.canvas.draw_text(bitstr, bits_startrow + 1, bit_start_col)
# Draw vertical double line connecting qubits and bits
self.canvas.draw_double_vline(
qubit_stoprow + 1, midcol, bits_stoprow - qubit_stoprow
)
endcol = ccol + gw
elif zvars and not qubitrow:
startrow = min(qubit_startrow, zvar_startrow) - 1
stoprow = max(qubit_stoprow, zvar_stoprow) + 1
gateheight = stoprow - startrow + 1
midrow = startrow + gateheight // 2
# Draw a single box
gw = operation.asciiwidth(qubits, bits, zvars)
self.canvas.draw_box(startrow, ccol, gw, gateheight, clean=True)
zstr = f"{','.join(map(str, zvars))} ═> "
self.canvas.draw_text(zstr, midrow, ccol + 1)
text_start_col = ccol + len(zstr) + 1
# Draw the operation name
self.canvas.draw_text(str(operation), midrow, text_start_col)
midcol = ccol + gw // 2
endcol = ccol + gw
elif bits and not qubitrow:
startrow = min(qubit_startrow, bits_startrow) - 1
stoprow = max(qubit_stoprow, bits_stoprow) + 1
gateheight = stoprow - startrow + 1
midrow = startrow + gateheight // 2
# Draw a single box
gw = operation.asciiwidth(qubits, bits, zvars)
self.canvas.draw_box(startrow, ccol, gw, gateheight, clean=True)
zstr = f"{','.join(map(str, bits))} ═> "
self.canvas.draw_text(zstr, midrow, ccol + 1)
text_start_col = ccol + len(zstr) + 1
# Draw the operation name
self.canvas.draw_text(str(operation), midrow, text_start_col)
midcol = ccol + gw // 2
endcol = ccol + gw
else:
startrow = min(qubitrow) - 1
stoprow = max(qubitrow) + 1
gateheight = stoprow - startrow + 1
midrow = startrow + gateheight // 2
# Draw the box around the operation
gw = operation.asciiwidth(qubits, bits, zvars)
self.canvas.draw_box(startrow, ccol, gw, gateheight, clean=True)
# Properly centered
self.canvas.draw_text(str(operation), midrow, ccol + namepadding + 1)
midcol = ccol + gw // 2
endcol = ccol + gw + namepadding
# If more than one qubit, label each qubit within the box
if len(qubits) > 1:
for i, qr in enumerate(qubitrow):
self.canvas.draw_text(str(i), qr, ccol + 1)
self.set_current_col(endcol)
return self
[docs]
def draw_control(self, operation, qubits, _):
if not isinstance(operation, mc.Control):
raise TypeError("operation must be an instance of Operation")
if operation.op.num_qubits == 1:
target_row = self.get_qubit_row(qubits[-1])
control_rows = [self.get_qubit_row(q) for q in qubits[:-1]]
max_row = max(control_rows + [target_row])
min_row = min(control_rows + [target_row])
current_col = self.get_current_col()
gate_width = operation.get_operation().asciiwidth([qubits[-1]], [], [])
middle_column = current_col + gate_width // 2
self.canvas.draw_vline(min_row, middle_column, max_row - min_row + 1)
for row in control_rows:
self.canvas[row, middle_column] = "●"
self.draw_operation(operation.get_operation(), [qubits[-1]], [], [])
else:
self.draw_operation(operation, qubits, [])
[docs]
def draw_barrier(self, barrier, qubits, bits, zvars):
for qubit in qubits:
qubit_row = self.get_qubit_row(qubit)
current_col = self.get_current_col()
self.canvas.draw_text("░", qubit_row, current_col)
self.canvas.draw_text("░", qubit_row, current_col)
self.canvas.draw_text("░", qubit_row + 1, current_col)
self.set_current_col(current_col + 1)
return self
[docs]
def draw_ifstatement(self, g, qubits, bits, zvars):
qubitrow = [self.get_qubit_row(q) for q in qubits]
bitrow = self.get_bit_row()
nb = len(bits)
val = g.get_bitstring()
ccol = self.get_current_col()
bstr = _string_with_square(_find_unit_range(bits), ",")
btext = f"c{bstr}==" + val.to01()
self.canvas.draw_box(bitrow - 1, ccol, len(btext) + 2, 3, clean=True)
self.canvas.draw_text(btext, bitrow, ccol + 1)
self.set_current_col(ccol + len(btext) + 2)
ifcol = self.get_current_col()
qstartrow = min(qubitrow) - 1
qstoprow = max(qubitrow) + 1
qw = g.op.asciiwidth(qubits, [], [])
qh = qstoprow - qstartrow + 1
qmh = qstartrow + qh // 2
namepadding = _gate_name_padding(qubits, [], [])
self.canvas.draw_box(qstartrow, ifcol, qw, qh, clean=True)
for i, qr in enumerate(qubitrow):
self.canvas.draw_text(str(i), qr, ifcol + 1)
self.canvas.draw_text(repr(g.op), qmh, ifcol + namepadding + 1)
midcol = ifcol + qw // 2
self.canvas.draw_double_vline(qstoprow, midcol, bitrow - qstoprow)
self.canvas.draw_double_hline(bitrow - 1, ifcol, midcol - ifcol)
self.canvas.draw_text("╝", bitrow - 1, midcol)
self.canvas.draw_text("○", bitrow - 1, ifcol)
self.set_current_col(ifcol + qw)
[docs]
def draw_reset(self, reset, qubits, _, zvars):
if not isinstance(reset, mc.Reset):
raise TypeError("Must be a Reset Operation")
qubit_row = self.get_qubit_row(qubits[0])
current_col = self.get_current_col()
self.canvas.draw_box(qubit_row - 1, current_col, 5, 3, clean=True)
# Draw the reset symbol (|0⟩) in the center of the box
self.canvas.draw_text("|0⟩", qubit_row, current_col + 1)
# Move the current column index forward to prevent overlapping with future elements
self.set_current_col(current_col + 5)
return self
[docs]
def draw_parallel(self, parallel, qubits, _, zvars):
if not isinstance(parallel, mc.Parallel):
raise TypeError("Must be a Parallel")
op = parallel.get_operation()
nq = op.num_qubits
nb = op.num_bits
ccol = self.get_current_col()
for i in range(parallel.num_repeats):
self.currentcol = ccol
self.draw_operation(op, qubits[nq * i : nq * (i + 1)], [], [])
return self
[docs]
def draw_paulistring(self, g, qubits, bits, zvars):
ccol = self.get_current_col()
qubitrow = [self.get_qubit_row(q) for q in qubits]
startrow = min(qubitrow) - 1
stoprow = max(qubitrow) + 1
gateheight = stoprow - startrow + 1
gw = g.asciiwidth(qubits, bits, zvars)
self.canvas.draw_box(startrow, ccol, gw, gateheight, clean=True)
for i, qr in enumerate(qubitrow):
pauli_char = g.pauli[i]
label = f"{i}: {pauli_char}" if len(qubits) > 1 else f"{pauli_char}"
self.canvas.draw_text(label, qr, ccol + 1)
self.set_current_col(ccol + gw)
return self
[docs]
def draw_instruction(self, instruction):
if not isinstance(instruction, mc.Instruction):
raise TypeError("Must be an Instruction")
return self.draw_operation(
instruction.get_operation(),
instruction._qubits,
instruction._bits,
instruction._zvars,
)
__all__ = ["AsciiCircuit", "AsciiCanvas"]