Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
433c9d3
Update Layout object to store input Registers.
kdk Dec 18, 2020
b8af1a3
Remove property_set['layout_ancilla_register'] from layout passes.
kdk Mar 19, 2021
7841688
Circuit visualizer: rename {q,c}reg variables to {qu,cl}bit.
kdk Nov 30, 2020
9b62a69
Update text circuit drawer to prefer inspecting Bits over Registers.
kdk Dec 1, 2020
a0de3ab
Update Matplotlib circuit drawer to prefer inspecting Bits over Regis…
kdk Dec 1, 2020
82786a8
Update latex circuit drawer to prefer inspecting Bits over Registers.
kdk Dec 1, 2020
3d9c219
Update Layout object to store input Registers.
kdk Dec 18, 2020
af9ef53
ApplyLayout to store registers of input circuit.
1ucian0 Mar 26, 2021
92669a2
Remove property_set['layout_ancilla_register'] from layout passes.
kdk Mar 19, 2021
42dfde6
Circuit visualizer: rename {q,c}reg variables to {qu,cl}bit.
kdk Nov 30, 2020
f8e24b1
Update text circuit drawer to prefer inspecting Bits over Registers.
kdk Dec 1, 2020
9d2c652
Update Matplotlib circuit drawer to prefer inspecting Bits over Regis…
kdk Dec 1, 2020
2027e7f
Update latex circuit drawer to prefer inspecting Bits over Registers.
kdk Dec 1, 2020
2ab577a
apply layout in tests
1ucian0 Mar 29, 2021
9dbe566
Merge branch 'master' into quantumcircuit-optional-registers-visualiz…
kdk Mar 29, 2021
5090109
Merge branch 'master' into quantumcircuit-optional-registers-visualiz…
kdk Mar 29, 2021
6dcddea
test
1ucian0 Mar 30, 2021
1f9bb75
Merge branch 'master' into quantumcircuit-optional-registers-visualiz…
1ucian0 Mar 30, 2021
038fdaf
Merge branch 'master' into quantumcircuit-optional-registers-visualiz…
mergify[bot] Mar 30, 2021
a1d0d30
Merge branch 'master' into quantumcircuit-optional-registers-visualiz…
mtreinish Mar 30, 2021
7245761
Merge branch 'master' into quantumcircuit-optional-registers-visualiz…
mtreinish Mar 30, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion qiskit/compiler/transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ def _layout_from_raw(initial_layout, circuit):
if all(isinstanceint(elem) for elem in initial_layout):
initial_layout = Layout.from_intlist(initial_layout, *circuit.qregs)
elif all(elem is None or isinstance(elem, Qubit) for elem in initial_layout):
initial_layout = Layout.from_qubit_list(initial_layout)
initial_layout = Layout.from_qubit_list(initial_layout, *circuit.qregs)
elif isinstance(initial_layout, dict):
initial_layout = Layout(initial_layout)
else:
Expand Down
5 changes: 3 additions & 2 deletions qiskit/transpiler/basepasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,10 @@ def __call__(self, circuit, property_set=None):

if isinstance(result, DAGCircuit):
result_circuit = dag_to_circuit(result)

if result is None and self.property_set['layout']:
elif result is None:
result_circuit = circuit.copy()

if self.property_set['layout']:
result_circuit._layout = self.property_set['layout']

return result_circuit
Expand Down
20 changes: 16 additions & 4 deletions qiskit/transpiler/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class Layout():
def __init__(self, input_dict=None):
"""construct a Layout from a bijective dictionary, mapping
virtual qubits to physical qubits"""
self._regs = []
self._p2v = {}
self._v2p = {}
if input_dict is not None:
Expand Down Expand Up @@ -101,6 +102,9 @@ def __getitem__(self, item):
return self._v2p[item]
raise KeyError('The item %s does not exist in the Layout' % (item,))

def __contains__(self, item):
return item in self._p2v or item in self._v2p

def __setitem__(self, key, value):
virtual, physical = Layout.order_based_on_type(key, value)
self._set_type_checked_item(virtual, physical)
Expand Down Expand Up @@ -138,6 +142,7 @@ def copy(self):
"""Returns a copy of a Layout instance."""
layout_copy = type(self)()

layout_copy._regs = self._regs.copy()
layout_copy._p2v = self._p2v.copy()
layout_copy._v2p = self._v2p.copy()

Expand Down Expand Up @@ -166,16 +171,18 @@ def add_register(self, reg):
Args:
reg (Register): A (qu)bit Register. For example, QuantumRegister(3, 'qr').
"""
self._regs.append(reg)
for bit in reg:
self.add(bit)
if bit not in self:
self.add(bit)

def get_registers(self):
"""
Returns the registers in the layout [QuantumRegister(2, 'qr0'), QuantumRegister(3, 'qr1')]
Returns:
List: A list of Register in the layout
Set: A set of Registers in the layout
"""
return {bit.register for bit in self.get_virtual_bits()}
return set(self._regs)

def get_virtual_bits(self):
"""
Expand Down Expand Up @@ -302,20 +309,23 @@ def from_intlist(int_list, *qregs):
for idx in range(qreg.size):
out[qreg[idx]] = int_list[main_idx]
main_idx += 1
out.add_register(qreg)
if main_idx != len(int_list):
for int_item in int_list[main_idx:]:
out[int_item] = None
return out

@staticmethod
def from_qubit_list(qubit_list):
def from_qubit_list(qubit_list, *qregs):
"""
Populates a Layout from a list containing virtual
qubits, Qubit or None.

Args:
qubit_list (list):
e.g.: [qr[0], None, qr[2], qr[3]]
*qregs (QuantumRegisters): The quantum registers to apply
the layout to.
Returns:
Layout: the corresponding Layout object
Raises:
Expand All @@ -331,4 +341,6 @@ def from_qubit_list(qubit_list):
out[virtual] = physical
else:
raise LayoutError("The list should contain elements of the Bits or NoneTypes")
for qreg in qregs:
out.add_register(qreg)
return out
3 changes: 3 additions & 0 deletions qiskit/transpiler/passes/layout/apply_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ def run(self, dag):
raise TranspilerError(
"The 'layout' must be full (with ancilla).")

for qreg in dag.qregs.values():
self.property_set["layout"].add_register(qreg)

q = QuantumRegister(len(layout), 'q')

new_dag = DAGCircuit()
Expand Down
2 changes: 2 additions & 0 deletions qiskit/transpiler/passes/layout/csp_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,5 +144,7 @@ def constraint(control, target):
else:
stop_reason = 'solution found'
self.property_set['layout'] = Layout({v: qubits[k] for k, v in solution.items()})
for reg in dag.qregs.values():
self.property_set['layout'].add_register(reg)
Comment thread
1ucian0 marked this conversation as resolved.

self.property_set['CSPLayout_stop_reason'] = stop_reason
1 change: 1 addition & 0 deletions qiskit/transpiler/passes/layout/dense_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def run(self, dag):
for i in range(qreg.size):
layout[qreg[i]] = int(best_sub[map_iter])
map_iter += 1
layout.add_register(qreg)
Comment thread
1ucian0 marked this conversation as resolved.
self.property_set['layout'] = layout

def _best_subset(self, num_qubits):
Expand Down
8 changes: 5 additions & 3 deletions qiskit/transpiler/passes/layout/enlarge_with_ancilla.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ def run(self, dag):
if layout is None:
raise TranspilerError('EnlargeWithAncilla requires property_set["layout"]')

new_qreg = self.property_set['layout_ancilla_register']
if new_qreg:
dag.add_qreg(new_qreg)
new_qregs = {reg for reg in layout.get_registers()
if reg not in dag.qregs.values()}

for qreg in new_qregs:
dag.add_qreg(qreg)

return dag
3 changes: 1 addition & 2 deletions qiskit/transpiler/passes/layout/full_ancilla_allocation.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,9 @@ def run(self, dag):
else:
qreg = QuantumRegister(len(idle_physical_qubits), name=self.ancilla_name)

self.property_set['layout_ancilla_register'] = qreg
for idx, idle_q in enumerate(idle_physical_qubits):
self.property_set['layout'][idle_q] = qreg[idx]

self.property_set['layout'].add_register(qreg)
return dag

@staticmethod
Expand Down
2 changes: 2 additions & 0 deletions qiskit/transpiler/passes/layout/noise_adaptive_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,4 +275,6 @@ def run(self, dag):
pid = self._qarg_to_id(q)
hwid = self.prog2hw[pid]
layout[q] = hwid
for qreg in dag.qregs.values():
layout.add_register(qreg)
self.property_set['layout'] = layout
3 changes: 3 additions & 0 deletions qiskit/transpiler/passes/layout/sabre_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ def run(self, dag):
logger.info('new initial layout')
logger.info(initial_layout)

for qreg in dag.qregs.values():
initial_layout.add_register(qreg)

self.property_set['layout'] = initial_layout

def _layout_and_route_passmanager(self, initial_layout):
Expand Down
3 changes: 2 additions & 1 deletion qiskit/transpiler/passes/layout/trivial_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@ def run(self, dag):
"""
if dag.num_qubits() > self.coupling_map.size():
raise TranspilerError('Number of qubits greater than device.')
self.property_set['layout'] = Layout.generate_trivial_layout(*dag.qubits)
self.property_set['layout'] = Layout.generate_trivial_layout(
*(dag.qubits + list(dag.qregs.values())))
38 changes: 21 additions & 17 deletions qiskit/visualization/circuit_visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,19 +278,21 @@ def _text_circuit_drawer(circuit, filename=None, reverse_bits=False,
Returns:
TextDrawing: An instance that, when printed, draws the circuit in ascii art.
"""
qregs, cregs, ops = utils._get_layered_instructions(circuit,
reverse_bits=reverse_bits,
justify=justify,
idle_wires=idle_wires)
qubits, clbits, ops = utils._get_layered_instructions(circuit,
reverse_bits=reverse_bits,
justify=justify,
idle_wires=idle_wires)

if with_layout:
layout = circuit._layout
else:
layout = None
global_phase = circuit.global_phase if hasattr(circuit, 'global_phase') else None
text_drawing = _text.TextDrawing(qregs, cregs, ops, layout=layout, initial_state=initial_state,
text_drawing = _text.TextDrawing(qubits, clbits, ops, layout=layout,
initial_state=initial_state,
cregbundle=cregbundle, global_phase=global_phase,
encoding=encoding)
encoding=encoding,
qregs=circuit.qregs, cregs=circuit.cregs)
text_drawing.plotbarriers = plot_barriers
text_drawing.line_length = fold
text_drawing.vertical_compression = vertical_compression
Expand Down Expand Up @@ -424,20 +426,21 @@ def _generate_latex_source(circuit, filename=None,
Returns:
str: Latex string appropriate for writing to file.
"""
qregs, cregs, ops = utils._get_layered_instructions(circuit,
reverse_bits=reverse_bits,
justify=justify, idle_wires=idle_wires)
qubits, clbits, ops = utils._get_layered_instructions(circuit,
reverse_bits=reverse_bits,
justify=justify, idle_wires=idle_wires)
if with_layout:
layout = circuit._layout
else:
layout = None

global_phase = circuit.global_phase if hasattr(circuit, 'global_phase') else None
qcimg = _latex.QCircuitImage(qregs, cregs, ops, scale, reverse_bits=reverse_bits,
qcimg = _latex.QCircuitImage(qubits, clbits, ops, scale, reverse_bits=reverse_bits,
plot_barriers=plot_barriers, layout=layout,
initial_state=initial_state,
cregbundle=cregbundle,
global_phase=global_phase)
global_phase=global_phase,
qregs=circuit.qregs, cregs=circuit.cregs)
latex = qcimg.latex()
if filename:
with open(filename, 'w') as latex_file:
Expand Down Expand Up @@ -498,10 +501,10 @@ def _matplotlib_circuit_drawer(circuit,
if the ``ax`` kwarg is not set.
"""

qregs, cregs, ops = utils._get_layered_instructions(circuit,
reverse_bits=reverse_bits,
justify=justify,
idle_wires=idle_wires)
qubits, clbits, ops = utils._get_layered_instructions(circuit,
reverse_bits=reverse_bits,
justify=justify,
idle_wires=idle_wires)
if with_layout:
layout = circuit._layout
else:
Expand All @@ -511,8 +514,9 @@ def _matplotlib_circuit_drawer(circuit,
fold = 25

global_phase = circuit.global_phase if hasattr(circuit, 'global_phase') else None
qcd = _matplotlib.MatplotlibDrawer(qregs, cregs, ops, scale=scale, style=style,
qcd = _matplotlib.MatplotlibDrawer(qubits, clbits, ops, scale=scale, style=style,
plot_barriers=plot_barriers, layout=layout,
fold=fold, ax=ax, initial_state=initial_state,
cregbundle=cregbundle, global_phase=global_phase)
cregbundle=cregbundle, global_phase=global_phase,
qregs=circuit.qregs, cregs=circuit.cregs)
return qcd.draw(filename)
68 changes: 47 additions & 21 deletions qiskit/visualization/latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,24 @@ class QCircuitImage:

def __init__(self, qubits, clbits, ops, scale, reverse_bits=False,
plot_barriers=True, layout=None, initial_state=False,
cregbundle=False, global_phase=None):
cregbundle=False, global_phase=None, qregs=None, cregs=None):
"""QCircuitImage initializer.

Args:
qubits (list[Qubit]): list of qubits
clbits (list[Clbit]): list of clbits
ops (list[list[DAGNode]]): list of circuit instructions, grouped by layer
scale (float): image scaling
reverse_bits: when True, reverse the bit ordering of the registers
reverse_bits (bool): when True, reverse the bit ordering of the registers
plot_barriers (bool): Enable/disable drawing barriers in the output
circuit. Defaults to True.
layout (Layout or None): If present, the layout information will be
included.
initial_state (bool): Optional. Adds |0> in the beginning of the line. Default: `False`.
cregbundle (bool): Optional. If set True bundle classical registers. Default: `False`.
global_phase (float): Optional, the global phase for the circuit.
qregs (list): List qregs present in the circuit.
cregs (list): List of cregs present in the circuit.
Raises:
ImportError: If pylatexenc is not installed
"""
Expand All @@ -70,8 +72,9 @@ def __init__(self, qubits, clbits, ops, scale, reverse_bits=False,
# Map of cregs to sizes
self.cregs = {}

# List of qregs and cregs in order of appearance in code and image
self.ordered_regs = []
# List of qubits and cbits in order of appearance in code and image
# May also include ClassicalRegisters if cregbundle=True
self.ordered_bits = []

# Map from registers to the list they appear in the image
self.img_regs = {}
Expand Down Expand Up @@ -107,10 +110,19 @@ def __init__(self, qubits, clbits, ops, scale, reverse_bits=False,

#################################
self.qubit_list = qubits
self.ordered_regs = qubits + clbits
self.ordered_bits = qubits + clbits
self.cregs, self.cregs_bits = self._get_register_specs(clbits)

self.bit_locations = {
bit: {'register': register, 'index': index}
for register in cregs + qregs
for index, bit in enumerate(register)}
for index, bit in list(enumerate(qubits)) + list(enumerate(clbits)):
if bit not in self.bit_locations:
self.bit_locations[bit] = {'register': None, 'index': index}

self.img_regs = {bit: ind for ind, bit in
enumerate(self.ordered_regs)}
enumerate(self.ordered_bits)}
if cregbundle:
self.img_width = len(qubits) + len(self.cregs)
else:
Expand Down Expand Up @@ -182,38 +194,52 @@ def _initialize_latex_array(self):
else:
self.wire_separation = 1.0
self._latex = [
["\\cw" if isinstance(self.ordered_regs[j], Clbit)
["\\cw" if isinstance(self.ordered_bits[j], Clbit)
else "\\qw" for _ in range(self.img_depth + 1)]
for j in range(self.img_width)]
self._latex.append([" "] * (self.img_depth + 1))
if self.cregbundle:
offset = 0
for i in range(self.img_width):
if isinstance(self.ordered_regs[i], Clbit):
if isinstance(self.ordered_bits[i], Clbit):
if self.cregbundle:
reg = self.bit_locations[self.ordered_bits[i + offset]]['register']
self._latex[i][0] = \
"\\lstick{" + self.ordered_regs[i + offset].register.name + ":"
clbitsize = self.cregs[self.ordered_regs[i + offset].register]
"\\lstick{" + reg.name + ":"
clbitsize = self.cregs[reg]
self._latex[i][1] = "\\lstick{/_{_{" + str(clbitsize) + "}}} \\cw"
offset += clbitsize - 1
else:
self._latex[i][0] = "\\lstick{" + self.ordered_regs[i].register.name + \
"_{" + str(self.ordered_regs[i].index) + "}:"
self._latex[i][0] = (
"\\lstick{"
+ self.bit_locations[self.ordered_bits[i]]['register'].name
+ "_{" + str(self.bit_locations[self.ordered_bits[i]]['index']) + "}:"
)
if self.initial_state:
self._latex[i][0] += "0"
self._latex[i][0] += "}"
else:
if self.layout is None:
label = "\\lstick{{ {{{}}}_{{{}}} : ".format(
self.ordered_regs[i].register.name, self.ordered_regs[i].index)
self.bit_locations[self.ordered_bits[i]]['register'].name,
self.bit_locations[self.ordered_bits[i]]['index'])
else:
if self.layout[self.ordered_regs[i].index]:
label = "\\lstick{{ {{{}}}_{{{}}}\\mapsto{{{}}} : ".format(
self.layout[self.ordered_regs[i].index].register.name,
self.layout[self.ordered_regs[i].index].index,
self.ordered_regs[i].index)
bit_location = self.bit_locations[self.ordered_bits[i]]
if bit_location and self.layout[bit_location['index']]:
virt_bit = self.layout[bit_location['index']]
try:
virt_reg = next(reg for reg in self.layout.get_registers()
if virt_bit in reg)
label = "\\lstick{{ {{{}}}_{{{}}}\\mapsto{{{}}} : ".format(
virt_reg.name,
virt_reg[:].index(virt_bit),
bit_location['index'])
except StopIteration:
label = "\\lstick{{ {{{}}} : ".format(
bit_location['index'])
else:
label = "\\lstick{{ {{{}}} : ".format(self.ordered_regs[i].index)
label = "\\lstick{{ {{{}}} : ".format(
bit_location['index'])
if self.initial_state:
label += "\\ket{{0}}"
label += " }"
Expand Down Expand Up @@ -279,9 +305,9 @@ def _get_image_depth(self):
sum_column_widths = sum(1 + v / 3 for v in max_column_widths)

max_reg_name = 3
for reg in self.ordered_regs:
for reg in self.ordered_bits:
max_reg_name = max(max_reg_name,
len(reg.register.name))
len(self.bit_locations[reg]['register'].name))
sum_column_widths += 5 + max_reg_name / 3

# could be a fraction so ceil
Expand Down
Loading