Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing Qubits and Clbits classes #2414

Merged
merged 113 commits into from
May 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
ee9982c
bit class
May 3, 2019
f33fb6d
Merge branch 'master' of github.com:Qiskit/qiskit-terra into no_tuple…
May 9, 2019
209e526
compare to tuple
May 9, 2019
e818061
hashable bits
May 9, 2019
41d4570
iter
May 9, 2019
ee328c4
getitem
May 9, 2019
1bdb163
avoid duplication of code
May 9, 2019
7769daf
test_barrier_none
May 9, 2019
88927cb
allow direct access to index and register
May 9, 2019
fb73984
Merge branch 'master' of github.com:Qiskit/qiskit-terra into no_tuple…
May 10, 2019
449b693
layout
May 10, 2019
428948d
snapshot
May 10, 2019
1ea2c86
conditional
May 10, 2019
98fe0d8
defintions
May 10, 2019
05ef560
layout
May 10, 2019
345cfba
test.python.circuit.test_circuit_registers.TestCircuitRegisters.test_…
May 10, 2019
b978268
Merge branch 'master' of github.com:Qiskit/qiskit-terra into no_tuple…
May 10, 2019
0017f18
Merge branch 'master' of github.com:Qiskit/qiskit-terra into no_tuple…
May 10, 2019
b6498c7
removing some tuple representation
May 10, 2019
1e4de02
removing some tuple representation
May 10, 2019
306251a
Merge branch 'master' of github.com:Qiskit/qiskit-terra into no_tuple…
May 13, 2019
ecd101d
repr
May 13, 2019
4a677a8
None
May 13, 2019
c5d6697
test.python.transpiler.test_layout
May 13, 2019
82de9cd
dag
May 13, 2019
b2fed7e
Merge branch 'master' of github.com:Qiskit/qiskit-terra into no_tuple…
May 13, 2019
ee3526e
test.python.compiler.test_compiler.TestCompiler.test_compile_single_q…
May 13, 2019
5635a49
test.python.compiler.test_compiler
May 13, 2019
4ae377a
order
May 13, 2019
dfc4ac6
Merge branch 'master' of github.com:Qiskit/qiskit-terra into no_tuple…
May 14, 2019
0d109fe
StochasticSwap
May 14, 2019
b10d03b
lint
May 14, 2019
d042a1e
register have order
May 14, 2019
2b32d5f
Merge branch 'master' into no_tuple_bits
May 14, 2019
d898e1c
Merge branch 'no_tuple_bits' of https://github.com/1ucian0/qiskit-ter…
May 14, 2019
5da818b
lint
May 14, 2019
0602230
test.python.visualization.test_visualization
May 14, 2019
dc9ff57
test.python.visualization.test_circuit_text_drawer
May 14, 2019
ca0d461
test.python.basicaer.test_basicaer_integration
May 14, 2019
8783026
test.python.compiler.test_transpiler
May 14, 2019
cd91ef4
test.python.transpiler.test_remove_diagonal_gates_before_measure
May 14, 2019
741c7e7
test.python.transpiler.test_stochastic_swap.TestStochasticSwap
May 14, 2019
996ad52
test.python.transpiler.test_unroller
May 15, 2019
f87ee33
test.python.circuit.test_circuit_registers
May 15, 2019
0cffeb8
test.python.transpiler.test_noise_adaptive_layout
May 15, 2019
8288799
test.python.quantum_info.operators.test_operator.TestOperator
May 15, 2019
9d02bb2
Merge branch 'master' into no_tuple_bits
May 15, 2019
61b4e57
merge
May 15, 2019
02f758d
mappers
May 15, 2019
524e9a1
pickles
May 15, 2019
687b067
latex lint
May 15, 2019
8d8d359
Merge branch 'master' of github.com:Qiskit/qiskit-terra into no_tuple…
May 15, 2019
14c3c9f
test.python.transpiler.test_full_ancilla_allocation
May 15, 2019
7fb84ae
test.python.transpiler.test_consolidate_blocks
May 15, 2019
33de488
test.python.transpiler.test_commutative_cancellation
May 15, 2019
1338af1
test.python.transpiler.test_basic_swap
May 15, 2019
1e6188e
test.python.quantum_info.operators.channel.test_superop
May 15, 2019
37436ca
lint qiskit/converters/ast_to_dag.py
May 15, 2019
cde5339
test/python/test_dagcircuit.py
May 15, 2019
69a00b7
test/python/test_dagcircuit.py
May 15, 2019
e8c4176
test.python.compiler.test_assembler
May 15, 2019
e8e5d48
test.python.circuit.test_unitary
May 15, 2019
0c0fcc9
condition
May 15, 2019
ec09bb5
test.python.circuit.test_circuit_properties
May 15, 2019
3226a18
instruction.control
May 15, 2019
2962853
lint
May 15, 2019
6ee6ca4
latex condition
May 15, 2019
5e2931d
qiskit/dagcircuit/dagcircuit.py
May 15, 2019
bb8e943
qiskit/circuit/quantumcircuit.py
May 15, 2019
6c79906
qiskit/assembler/assemble_circuits.py
May 15, 2019
934495f
test for 1898
May 15, 2019
0523436
https://github.com/Qiskit/qiskit-terra/pull/2414#discussion_r284383842
May 15, 2019
22d9999
Merge branch 'master' into no_tuple_bits
1ucian0 May 15, 2019
3a3f92c
docstrings
May 15, 2019
b465e17
Merge branch 'no_tuple_bits' of https://github.com/1ucian0/qiskit-ter…
May 15, 2019
7866e38
removing order by comparing sets in Collect2qBlocks
May 15, 2019
2a350f9
QuBit-> Qubit and ClBit-> Clbit
May 16, 2019
74c1f24
errors
May 16, 2019
ff8770f
lint
May 16, 2019
34cb7a9
QuBit -> Qubit
May 16, 2019
8b66ddb
ctrl_reg, ctrl_val = instruction._control
May 16, 2019
36a65b8
https://github.com/Qiskit/qiskit-terra/pull/2414/files/ff8770f7b195f6…
May 16, 2019
6c8bb16
explicit globals
May 16, 2019
2c9ae5e
lint
May 16, 2019
865f864
Merge branch 'master' of github.com:Qiskit/qiskit-terra into no_tuple…
May 16, 2019
3398896
__getitem__ for deprecation
May 16, 2019
5f44f9b
from_tuple
May 16, 2019
b26051a
new pickles
May 16, 2019
79a5197
docstring
May 16, 2019
fc4e0ea
accept gate arguments as tuples and mark them as deprecated
May 16, 2019
829828d
this fix contradicts whats expected from a negative key lookup
May 16, 2019
126110b
Merge branch 'master' of github.com:Qiskit/qiskit-terra into no_tuple…
May 16, 2019
00b0a82
promote __iter__
May 16, 2019
ebb58b7
simpler negative index check...
May 16, 2019
bf912ca
https://github.com/Qiskit/qiskit-terra/pull/2414/files#r284542889
May 16, 2019
f2abad6
docstring lint
May 16, 2019
0db6ad5
getitem
May 16, 2019
139b1cd
layout backwards compatibility
May 16, 2019
29dbbdf
lint
May 16, 2019
702f35a
Merge branch 'master' of github.com:Qiskit/qiskit-terra into no_tuple…
May 16, 2019
16f90b9
lint!
May 16, 2019
d876acf
deprecated messager only when _is_bit
May 16, 2019
803ea5b
changelog
May 17, 2019
ed5f9a6
Merge branch 'master' into no_tuple_bits
1ucian0 May 17, 2019
bd4f833
expose less the contructor
May 17, 2019
5811aac
Merge branch 'master' of github.com:Qiskit/qiskit-terra into no_tuple…
May 17, 2019
91c6e81
remove prints and raised text
May 17, 2019
b2132b8
simplifications
May 17, 2019
1910b6f
lint
May 17, 2019
4d8ca18
Merge branch 'master' into no_tuple_bits
1ucian0 May 18, 2019
80693b5
Merge branch 'master' into no_tuple_bits
1ucian0 May 20, 2019
0a2117d
Merge branch 'master' into no_tuple_bits
1ucian0 May 20, 2019
9939176
Merge branch 'master' into no_tuple_bits
1ucian0 May 21, 2019
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
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ Removed
- The ``qiskit.qiskiterror`` module has been removed. Please use
``qiskit.exceptions`` instead. (#2399)

Changed
-------
- Qubits and classical bits are not represented as a tuples anymore, but as
instances of ``Qubit`` and ``Clbit`` respectively.

`0.8.0`_ - 2019-05-02
=====================

Expand Down
4 changes: 2 additions & 2 deletions qiskit/assembler/assemble_circuits.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ def assemble_circuits(circuits, run_config, qobj_id, qobj_header):
qargs = op_context[1]
cargs = op_context[2]
if qargs:
qubit_indices = [qubit_labels.index([qubit[0].name, qubit[1]])
qubit_indices = [qubit_labels.index([qubit.register.name, qubit.index])
Copy link
Contributor

Choose a reason for hiding this comment

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

Could this just be qubit_labels.index(qubit)?

Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps you're leaving that to a future PR but without it you don't get the benefit of not having to touch almost all the same pieces of code again when it is implemented.

Copy link
Member Author

Choose a reason for hiding this comment

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

No.. it is not equivalente, because qubit_labels's keys are things like ['c1', 0]. I do see that there is room for optimization... but I would prefer to do that in a different PR.

for qubit in qargs]
instruction.qubits = qubit_indices
if cargs:
clbit_indices = [clbit_labels.index([clbit[0].name, clbit[1]])
clbit_indices = [clbit_labels.index([clbit.register.name, clbit.index])
for clbit in cargs]
instruction.memory = clbit_indices
# If the experiment has conditional instructions, assume every
Expand Down
4 changes: 2 additions & 2 deletions qiskit/circuit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

"""Module for Circuits."""
from .quantumcircuit import QuantumCircuit
from .classicalregister import ClassicalRegister
from .quantumregister import QuantumRegister
from .classicalregister import ClassicalRegister, Clbit
from .quantumregister import QuantumRegister, Qubit
from .gate import Gate
from .instruction import Instruction
from .instructionset import InstructionSet
Expand Down
64 changes: 64 additions & 0 deletions qiskit/circuit/bit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-

# This code is part of Qiskit.
#
# (C) Copyright IBM 2019.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""
Quantum bit and Classical bit objects.
"""
from warnings import warn
from qiskit.exceptions import QiskitError


class Bit:
"""Implement a generic bit."""

def __init__(self, register, index):
"""Create a new generic bit.
"""
try:
index = int(index)
except Exception:
raise QiskitError("index needs to be castable to an int: type %s was provided" %
type(index))

if index < 0:
index += register.size

if index >= register.size:
raise QiskitError("index must be under the size of the register: %s was provided" %
index)

self.register = register
self.index = index

def __repr__(self):
"""Return the official string representing the bit."""
return "%s(%s, %s)" % (self.__class__.__name__, self.register, self.index)

def __getitem__(self, item):
warn('Accessing a bit register by bit[0] or its index by bit[1] is deprecated. '
'Go for bit.register and bit.index.', DeprecationWarning)
if item == 0:
return self.register
elif item == 1:
return self.index
else:
raise IndexError

def __hash__(self):
return hash((self.register, self.index))

def __eq__(self, other):
if isinstance(other, tuple):
return other[1] == self.index and other[0] == self.register
return other.index == self.index and other.register == self.register
14 changes: 14 additions & 0 deletions qiskit/circuit/classicalregister.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,20 @@
"""
import itertools

from qiskit.exceptions import QiskitError
from .register import Register
from .bit import Bit


class Clbit(Bit):
"""Implement a classical bit."""

def __init__(self, register, index):
if isinstance(register, ClassicalRegister):
super().__init__(register, index)
else:
raise QiskitError('Clbit needs a ClassicalRegister and %s was provided' %
type(register).__name__)


class ClassicalRegister(Register):
Expand All @@ -27,6 +40,7 @@ class ClassicalRegister(Register):
instances_counter = itertools.count()
# Prefix to use for auto naming.
prefix = 'c'
bit_type = Clbit

def qasm(self):
"""Return OPENQASM string for this register."""
Expand Down
62 changes: 33 additions & 29 deletions qiskit/circuit/quantumcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,28 @@
import itertools
import sys
import multiprocessing as mp
from warnings import warn

from qiskit.circuit.instruction import Instruction
from qiskit.qasm.qasm import Qasm
from qiskit.exceptions import QiskitError
from qiskit.circuit.parameter import Parameter
from .quantumregister import QuantumRegister
from .classicalregister import ClassicalRegister
from .quantumregister import QuantumRegister, Qubit
from .classicalregister import ClassicalRegister, Clbit
from .parametertable import ParameterTable
from .parametervector import ParameterVector
from .instructionset import InstructionSet
from .register import Register
from .bit import Bit


def _is_bit(obj):
"""Determine if obj is a bit"""
# If there is a bit type this could be replaced by isinstance.
if isinstance(obj, tuple) and len(obj) == 2:
if isinstance(obj[0], Register) and isinstance(obj[1], int) and obj[1] < len(obj[0]):
warn('Referring to a bit as a tuple is being deprecated. '
'Instead go of (qr, 0), use qr[0].', DeprecationWarning)
return True
return False

Expand Down Expand Up @@ -265,35 +269,43 @@ def cast(value, _type):

@staticmethod
def _bit_argument_conversion(bit_representation, in_array):
ret = None
try:
if _is_bit(bit_representation):
# circuit.h((qr, 0)) -> circuit.h([qr[0]])
ret = [bit_representation[0][bit_representation[1]]]
elif isinstance(bit_representation, Bit):
# circuit.h(qr[0]) -> circuit.h([qr[0]])
return [bit_representation]
ret = [bit_representation]
elif isinstance(bit_representation, Register):
# circuit.h(qr) -> circuit.h([qr[0], qr[1]])
return bit_representation[:]
ret = bit_representation[:]
elif isinstance(QuantumCircuit.cast(bit_representation, int), int):
# circuit.h(0) -> circuit.h([qr[0]])
return [in_array[bit_representation]]
ret = [in_array[bit_representation]]
elif isinstance(bit_representation, slice):
# circuit.h(slice(0,2)) -> circuit.h([qr[0], qr[1]])
return in_array[bit_representation]
ret = in_array[bit_representation]
elif isinstance(bit_representation, list) and \
all(_is_bit(bit) for bit in bit_representation):
ret = [bit[0][bit[1]] for bit in bit_representation]
elif isinstance(bit_representation, list) and \
all(isinstance(bit, Bit) for bit in bit_representation):
# circuit.h([qr[0], qr[1]]) -> circuit.h([qr[0], qr[1]])
return bit_representation
ret = bit_representation
elif isinstance(QuantumCircuit.cast(bit_representation, list), (range, list)):
# circuit.h([0, 1]) -> circuit.h([qr[0], qr[1]])
# circuit.h(range(0,2)) -> circuit.h([qr[0], qr[1]])
return [in_array[index] for index in bit_representation]
ret = [in_array[index] for index in bit_representation]
else:
raise QiskitError('Not able to expand a %s (%s)' % (bit_representation,
type(bit_representation)))
except IndexError:
raise QiskitError('Index out of range.')
except TypeError:
raise QiskitError('Type error handeling %s (%s)' % (bit_representation,
type(bit_representation)))
raise QiskitError('Type error handling %s (%s)' % (bit_representation,
type(bit_representation)))
return ret

def qbit_argument_conversion(self, qubit_representation):
"""
Expand Down Expand Up @@ -429,25 +441,17 @@ def _check_dups(self, qubits):

def _check_qargs(self, qargs):
"""Raise exception if a qarg is not in this circuit or bad format."""
if not all(isinstance(i, tuple) and
isinstance(i[0], QuantumRegister) and
isinstance(i[1], int) for i in qargs):
raise QiskitError("qarg not (QuantumRegister, int) tuple")
if not all(self.has_register(i[0]) for i in qargs):
if not all(isinstance(i, Qubit) for i in qargs):
raise QiskitError("qarg is not a Qubit")
if not all(self.has_register(i.register) for i in qargs):
raise QiskitError("register not in this circuit")
for qubit in qargs:
qubit[0].check_range(qubit[1])

def _check_cargs(self, cargs):
"""Raise exception if clbit is not in this circuit or bad format."""
if not all(isinstance(i, tuple) and
isinstance(i[0], ClassicalRegister) and
isinstance(i[1], int) for i in cargs):
raise QiskitError("carg not (ClassicalRegister, int) tuple")
if not all(self.has_register(i[0]) for i in cargs):
if not all(isinstance(i, Clbit) for i in cargs):
raise QiskitError("carg is not a Clbit")
if not all(self.has_register(i.register) for i in cargs):
raise QiskitError("register not in this circuit")
for clbit in cargs:
clbit[0].check_range(clbit[1])

def to_instruction(self, parameter_map=None):
"""Create an Instruction out of this circuit.
Expand Down Expand Up @@ -502,11 +506,11 @@ def qasm(self):
qubit = qargs[0]
clbit = cargs[0]
string_temp += "%s %s[%d] -> %s[%d];\n" % (instruction.qasm(),
qubit[0].name, qubit[1],
clbit[0].name, clbit[1])
qubit.register.name, qubit.index,
clbit.register.name, clbit.index)
else:
string_temp += "%s %s;\n" % (instruction.qasm(),
",".join(["%s[%d]" % (j[0].name, j[1])
",".join(["%s[%d]" % (j.register.name, j.index)
for j in qargs + cargs]))
return string_temp

Expand Down Expand Up @@ -627,7 +631,7 @@ def depth(self):
for ind, reg in enumerate(qargs + cargs):
# Add to the stacks of the qubits and
# cbits used in the gate.
reg_ints.append(reg_map[reg[0].name] + reg[1])
reg_ints.append(reg_map[reg.register.name] + reg.index)
levels.append(op_stack[reg_ints[ind]] + 1)
if instr.control:
# Controls operate over all bits in the
Expand Down Expand Up @@ -719,7 +723,7 @@ def num_connected_components(self, unitary_only=False):
break

for item in args:
reg_int = reg_map[item[0].name] + item[1]
reg_int = reg_map[item.register.name] + item.index
for k in range(num_sub_graphs):
if reg_int in sub_graphs[k]:
if k not in graphs_touched:
Expand Down
14 changes: 14 additions & 0 deletions qiskit/circuit/quantumregister.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,20 @@
"""
import itertools

from qiskit.exceptions import QiskitError
from .register import Register
from .bit import Bit


class Qubit(Bit):
"""Implement a quantum bit."""

def __init__(self, register, index):
if isinstance(register, QuantumRegister):
super().__init__(register, index)
else:
raise QiskitError('Qubit needs a QuantumRegister and %s was provided' %
type(register).__name__)


class QuantumRegister(Register):
Expand All @@ -26,6 +39,7 @@ class QuantumRegister(Register):
instances_counter = itertools.count()
# Prefix to use for auto naming.
prefix = 'q'
bit_type = Qubit

def qasm(self):
"""Return OPENQASM string for this register."""
Expand Down
Loading