Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 12 additions & 0 deletions qiskit/circuit/bit.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"""
Quantum bit and Classical bit objects.
"""
import warnings

from qiskit.circuit.exceptions import CircuitError


Expand Down Expand Up @@ -58,6 +60,11 @@ def register(self):
if (self._register, self._index) == (None, None):
raise CircuitError('Attmped to query register of a new-style Bit.')

warnings.warn('Back-references to from Bit instances to their containing '
'Registers have been deprecated. Instead, inspect Registers '
'to find their contained Bits.',
DeprecationWarning, stacklevel=2)

return self._register

@property
Expand All @@ -66,6 +73,11 @@ def index(self):
if (self._register, self._index) == (None, None):
raise CircuitError('Attmped to query index of a new-style Bit.')

warnings.warn('Back-references to from Bit instances to their containing '
'Registers have been deprecated. Instead, inspect Registers '
'to find their contained Bits.',
DeprecationWarning, stacklevel=2)

return self._index

def __repr__(self):
Expand Down
8 changes: 5 additions & 3 deletions qiskit/opflow/gradients/circuit_qfis/overlap_diag.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,12 @@ def _partition_circuit(circuit):
# gates from subsequent layers shifted backward.
# The idea being that all parameterized gates should have
# no descendants within their layer
bit_indices = {bit: index for index, bit in enumerate(circuit.qubits)}
for i, (layer, ledger) in enumerate(layers):
op_node = layer.op_nodes()[0]
is_param = op_node.op.is_parameterized()
qargs = op_node.qargs
indices = [qarg.index for qarg in qargs]
indices = [bit_indices[qarg] for qarg in qargs]
if is_param:
for index in indices:
ledger[index] = True
Expand Down Expand Up @@ -187,7 +188,7 @@ def apply_node_op(node, dag, back=True):
for next_node in next_layer.op_nodes():
is_param = next_node.op.is_parameterized()
qargs = next_node.qargs
indices = [qarg.index for qarg in qargs]
indices = [bit_indices[qarg] for qarg in qargs]

# If the next_node can be moved back a layer without
# without becoming the descendant of a parameterized gate,
Expand Down Expand Up @@ -218,6 +219,7 @@ def _get_generators(params, circuit):

generators = {}
num_qubits = dag.num_qubits()
bit_indices = {bit: index for index, bit in enumerate(circuit.qubits)}

for layer in layers:
instr = layer['graph'].op_nodes()[0].op
Expand All @@ -244,7 +246,7 @@ def _get_generators(params, circuit):

# get all qubit indices in this layer where the param parameterizes
# an operation.
indices = [[q.index for q in qreg] for qreg in layer['partition']]
indices = [[bit_indices[q] for q in qreg] for qreg in layer['partition']]
indices = [item for sublist in indices for item in sublist]

if len(indices) > 1:
Expand Down
5 changes: 3 additions & 2 deletions qiskit/quantum_info/operators/dihedral/dihedral.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,9 +411,10 @@ def adjoint(self):
def conjugate(self):
circ = self.to_instruction()
new_circ = QuantumCircuit(self.num_qubits)
qargs = list(range(self.num_qubits))
bit_indices = {bit: index
for index, bit in enumerate(circ.definition.qubits)}
for instr, qregs, _ in circ.definition:
new_qubits = [qargs[tup.index] for tup in qregs]
new_qubits = [bit_indices[tup] for tup in qregs]
if instr.name == 'p':
params = 2 * np.pi - instr.params[0]
instr.params[0] = params
Expand Down
7 changes: 6 additions & 1 deletion qiskit/quantum_info/operators/dihedral/dihedral_circuits.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,14 @@ def _append_circuit(elem, circuit, qargs=None):
raise QiskitError('{} instruction definition is {}; expected QuantumCircuit'.format(
gate.name, type(gate.definition)))

flat_instr = gate.definition
bit_indices = {bit: index
for bits in [flat_instr.qubits, flat_instr.clbits]
for index, bit in enumerate(bits)}

for instr, qregs, _ in gate.definition:
# Get the integer position of the flat register
new_qubits = [qargs[tup.index] for tup in qregs]
new_qubits = [qargs[bit_indices[tup]] for tup in qregs]

if (instr.name == 'x' or gate.name == 'x'):
if len(new_qubits) != 1:
Expand Down
10 changes: 8 additions & 2 deletions qiskit/quantum_info/operators/symplectic/base_pauli.py
Original file line number Diff line number Diff line change
Expand Up @@ -486,13 +486,19 @@ def _append_circuit(self, circuit, qargs=None):
raise QiskitError(
'{} instruction definition is {}; expected QuantumCircuit'.format(
gate.name, type(gate.definition)))
for instr, qregs, cregs in gate.definition:

flat_instr = gate.definition
bit_indices = {bit: index
for bits in [flat_instr.qubits, flat_instr.clbits]
for index, bit in enumerate(bits)}

for instr, qregs, cregs in flat_instr:
if cregs:
raise QiskitError(
'Cannot apply Instruction with classical registers: {}'.format(
instr.name))
# Get the integer position of the flat register
new_qubits = [qargs[tup.index] for tup in qregs]
new_qubits = [qargs[bit_indices[tup]] for tup in qregs]
self._append_circuit(instr, new_qubits)

# Since the individual gate evolution functions don't take mod
Expand Down
4 changes: 2 additions & 2 deletions qiskit/transpiler/passes/layout/noise_adaptive_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def _initialize_backend_prop(self):

def _qarg_to_id(self, qubit):
"""Convert qarg with name and value to an integer id."""
return self.qarg_to_id[qubit.register.name + str(qubit.index)]
return self.qarg_to_id[qubit]

def _create_program_graph(self, dag):
"""Program graph has virtual qubits as nodes.
Expand All @@ -143,7 +143,7 @@ def _create_program_graph(self, dag):
"""
idx = 0
for q in dag.qubits:
self.qarg_to_id[q.register.name + str(q.index)] = idx
self.qarg_to_id[q] = idx
idx += 1
edge_list = []
for gate in dag.two_qubit_ops():
Expand Down
7 changes: 5 additions & 2 deletions qiskit/transpiler/passes/utils/check_gate_direction.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

"""Check if the gates follow the right direction with respect to the coupling map."""

from qiskit.transpiler.layout import Layout
from qiskit.transpiler.basepasses import AnalysisPass


Expand Down Expand Up @@ -41,9 +42,11 @@ def run(self, dag):
self.property_set['is_direction_mapped'] = True
edges = self.coupling_map.get_edges()

trivial_layout = Layout.generate_trivial_layout(*dag.qregs.values())

for gate in dag.two_qubit_ops():
physical_q0 = gate.qargs[0].index
physical_q1 = gate.qargs[1].index
physical_q0 = trivial_layout[gate.qargs[0]]
physical_q1 = trivial_layout[gate.qargs[1]]

if (physical_q0, physical_q1) not in edges:
self.property_set['is_direction_mapped'] = False
Expand Down
7 changes: 5 additions & 2 deletions qiskit/transpiler/passes/utils/gate_direction.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from math import pi

from qiskit.transpiler.layout import Layout
from qiskit.transpiler.basepasses import TransformationPass
from qiskit.transpiler.exceptions import TranspilerError

Expand Down Expand Up @@ -91,12 +92,14 @@ def run(self, dag):
'but input DAG had qregs: {}.'.format(
dag.qregs))

trivial_layout = Layout.generate_trivial_layout(*dag.qregs.values())

for node in dag.two_qubit_ops():
control = node.qargs[0]
target = node.qargs[1]

physical_q0 = control.index
physical_q1 = target.index
physical_q0 = trivial_layout[control]
physical_q1 = trivial_layout[target]

if self.coupling_map.distance(physical_q0, physical_q1) != 1:
raise TranspilerError('The circuit requires a connection between physical '
Expand Down
15 changes: 12 additions & 3 deletions qiskit/visualization/gate_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,15 +358,24 @@ def plot_circuit_layout(circuit, backend, view='virtual'):
qubits = []
qubit_labels = [None] * num_qubits

bit_locations = {bit: {'register': register, 'index': index}
for register in circuit._layout.get_registers()
for index, bit in enumerate(register)}
Comment on lines 361 to 363
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember how we handled registerless bits in the layout, but won't this potentially miss a virtual bit if it's not in a register?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, fixed in afdffa3 .

for index, qubit in enumerate(circuit._layout.get_virtual_bits()):
if qubit not in bit_locations:
bit_locations[qubit] = {'register': None, 'index': index}

if view == 'virtual':
for key, val in circuit._layout.get_virtual_bits().items():
if key.register.name != 'ancilla':
bit_register = bit_locations[key]['register']
if bit_register is None or bit_register.name != 'ancilla':
qubits.append(val)
qubit_labels[val] = key.index
qubit_labels[val] = bit_locations[key]['index']

elif view == 'physical':
for key, val in circuit._layout.get_physical_bits().items():
if val.register.name != 'ancilla':
bit_register = bit_locations[val]['register']
if bit_register is None or bit_register.name != 'ancilla':
qubits.append(key)
qubit_labels[key] = key

Expand Down
12 changes: 2 additions & 10 deletions qiskit/visualization/latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def __init__(self, qubits, clbits, ops, scale, reverse_bits=False,
#################################
self.qubit_list = qubits
self.ordered_bits = qubits + clbits
self.cregs, self.cregs_bits = self._get_register_specs(clbits)
self.cregs = {reg: reg.size for reg in cregs}

self.bit_locations = {
bit: {'register': register, 'index': index}
Expand All @@ -121,6 +121,7 @@ def __init__(self, qubits, clbits, ops, scale, reverse_bits=False,
if bit not in self.bit_locations:
self.bit_locations[bit] = {'register': None, 'index': index}

self.cregs_bits = [self.bit_locations[bit]['register'] for bit in clbits]
self.img_regs = {bit: ind for ind, bit in
enumerate(self.ordered_bits)}
if cregbundle:
Expand Down Expand Up @@ -623,15 +624,6 @@ def _add_condition(self, op, wire_list, col):
self._latex[cwire + i][col] = f"{control} \\cw \\cwx[-" + str(gap) + "]"
gap = 1

def _get_register_specs(self, bits):
"""Get the number and size of unique registers from bits list."""
regs = {}
regs_bits = []
for bit in bits:
regs[bit.register] = bit.register.size
regs_bits.append(bit.register)
return regs, regs_bits

def _truncate_float(self, matchobj, ndigits=4):
"""Truncate long floats."""
if matchobj.group(0):
Expand Down
40 changes: 24 additions & 16 deletions qiskit/visualization/timeline/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ def my_object_generator(
the plotter API.
"""

import warnings

from typing import List, Union, Dict, Any

from qiskit.circuit.exceptions import CircuitError
Expand Down Expand Up @@ -126,15 +128,17 @@ def gen_sched_gate(gate: types.ScheduledGate,
except AttributeError:
label = 'n/a'

meta = {
'name': gate.operand.name,
'label': label,
'bits': ', '.join([bit.register.name for bit in gate.bits]),
't0': gate.t0,
'duration': gate.duration,
'unitary': unitary,
'parameters': ', '.join(map(str, gate.operand.params))
}
with warnings.catch_warnings():
warnings.simplefilter("ignore")
meta = {
'name': gate.operand.name,
'label': label,
'bits': ', '.join([bit.register.name for bit in gate.bits]),
't0': gate.t0,
'duration': gate.duration,
'unitary': unitary,
'parameters': ', '.join(map(str, gate.operand.params))
}

# find color
color = formatter['color.gates'].get(gate.operand.name, formatter['color.default_gate'])
Expand Down Expand Up @@ -226,10 +230,12 @@ def gen_full_gate_name(gate: types.ScheduledGate,
label_latex = r'{name}'.format(name=latex_name)

# bit index
if len(gate.bits) > 1:
bits_str = ', '.join(map(str, [bit.index for bit in gate.bits]))
label_plain += '[{bits}]'.format(bits=bits_str)
label_latex += '[{bits}]'.format(bits=bits_str)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
if len(gate.bits) > 1:
bits_str = ', '.join(map(str, [bit.index for bit in gate.bits]))
label_plain += '[{bits}]'.format(bits=bits_str)
label_latex += '[{bits}]'.format(bits=bits_str)

# parameter list
params = []
Expand Down Expand Up @@ -380,9 +386,11 @@ def gen_bit_name(bit: types.Bits,
'ha': 'right'
}

label_plain = '{name}'.format(name=bit.register.name)
label_latex = r'{{\rm {register}}}_{{{index}}}'.format(register=bit.register.prefix,
index=bit.index)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
label_plain = '{name}'.format(name=bit.register.name)
label_latex = r'{{\rm {register}}}_{{{index}}}'.format(register=bit.register.prefix,
index=bit.index)

drawing = drawings.TextData(data_type=types.LabelType.BIT_NAME,
xval=types.AbstractCoordinate.LEFT,
Expand Down
8 changes: 6 additions & 2 deletions qiskit/visualization/timeline/layouts.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ def my_layout(time_window: Tuple[int, int]) -> types.HorizontalAxis:
Arbitrary layout function satisfying the above format can be accepted.
"""

import warnings

from typing import List, Tuple
import numpy as np

Expand Down Expand Up @@ -79,8 +81,10 @@ def qreg_creg_ascending(bits: List[types.Bits]) -> List[types.Bits]:
else:
VisualizationError('Unknown bit {bit} is provided.'.format(bit=bit))

qregs = sorted(qregs, key=lambda x: x.index, reverse=False)
cregs = sorted(cregs, key=lambda x: x.index, reverse=False)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
qregs = sorted(qregs, key=lambda x: x.index, reverse=False)
cregs = sorted(cregs, key=lambda x: x.index, reverse=False)

return qregs + cregs

Expand Down
12 changes: 9 additions & 3 deletions qiskit/visualization/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,8 @@ def slide_from_left(self, node, index):
"""Insert node into first layer where there is no conflict going l > r"""
measure_layer = None
if isinstance(node.op, Measure):
measure_reg = node.cargs[0].register
measure_reg = next(reg for reg in self.measure_map
if node.cargs[0] in reg)

if not self:
inserted = True
Expand All @@ -238,8 +239,13 @@ def slide_from_left(self, node, index):
index_stop = self.measure_map[node.condition[0]]
elif node.cargs:
for carg in node.cargs:
if self.measure_map[carg.register] > index_stop:
index_stop = self.measure_map[carg.register]
try:
carg_reg = next(reg for reg in self.measure_map
if carg in reg)
if self.measure_map[carg_reg] > index_stop:
index_stop = self.measure_map[carg_reg]
except StopIteration:
pass

while curr_index > index_stop:
if self.is_found_in(node, self[curr_index]):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
deprecations:
- |
Accessing references from :class:`~qiskit.circuit.Qubit` and
:class:`~qiskit.circuit.Clbit` instances to their containing registers
via the :attr:`~qiskit.circuit.Qubit.register` or :attr:`~qiskit.circuit.Qubit.index`
properties has been deprecated. Instead, :class:`~qiskit.circuit.Register` s
can be queried to find the :class:`~qiskit.circuit.Bit` s they contain.
14 changes: 13 additions & 1 deletion test/python/circuit/test_bit.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from unittest import mock

from qiskit.test import QiskitTestCase
from qiskit.circuit import bit
from qiskit.circuit import bit, QuantumRegister


class TestBitClass(QiskitTestCase):
Expand Down Expand Up @@ -73,3 +73,15 @@ def test_newstyle_bit_equality(self):
self.assertEqual(bit1, bit1)
self.assertNotEqual(bit1, bit2)
self.assertNotEqual(bit1, 3.14)

def test_bit_register_backreferences_deprecated(self):
"""Verify we raise a deprecation warning for register back-references."""

qr = QuantumRegister(3, 'test_qr')
qubit = qr[0]

with self.assertWarnsRegex(DeprecationWarning, 'deprecated'):
_ = qubit.index

with self.assertWarnsRegex(DeprecationWarning, 'deprecated'):
_ = qubit.register
Loading