Skip to content

Commit

Permalink
Merge branch 'main' into move-target
Browse files Browse the repository at this point in the history
  • Loading branch information
raynelfss authored Jun 13, 2024
2 parents 8e42b49 + 8a1bcc2 commit 03da436
Show file tree
Hide file tree
Showing 16 changed files with 204 additions and 73 deletions.
48 changes: 23 additions & 25 deletions qiskit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

# pylint: disable=wrong-import-position
# pylint: disable=wrong-import-position,wrong-import-order

"""Main Qiskit public functionality."""

Expand Down Expand Up @@ -52,38 +52,36 @@
)


import qiskit._accelerate
from . import _accelerate
import qiskit._numpy_compat

# Globally define compiled submodules. The normal import mechanism will not find compiled submodules
# in _accelerate because it relies on file paths, but PyO3 generates only one shared library file.
# We manually define them on import so people can directly import qiskit._accelerate.* submodules
# and not have to rely on attribute access. No action needed for top-level extension packages.
sys.modules["qiskit._accelerate.circuit"] = qiskit._accelerate.circuit
sys.modules["qiskit._accelerate.convert_2q_block_matrix"] = (
qiskit._accelerate.convert_2q_block_matrix
)
sys.modules["qiskit._accelerate.dense_layout"] = qiskit._accelerate.dense_layout
sys.modules["qiskit._accelerate.error_map"] = qiskit._accelerate.error_map
sys.modules["qiskit._accelerate.isometry"] = qiskit._accelerate.isometry
sys.modules["qiskit._accelerate.uc_gate"] = qiskit._accelerate.uc_gate
sys.modules["qiskit._accelerate.circuit"] = _accelerate.circuit
sys.modules["qiskit._accelerate.convert_2q_block_matrix"] = _accelerate.convert_2q_block_matrix
sys.modules["qiskit._accelerate.dense_layout"] = _accelerate.dense_layout
sys.modules["qiskit._accelerate.error_map"] = _accelerate.error_map
sys.modules["qiskit._accelerate.isometry"] = _accelerate.isometry
sys.modules["qiskit._accelerate.uc_gate"] = _accelerate.uc_gate
sys.modules["qiskit._accelerate.euler_one_qubit_decomposer"] = (
qiskit._accelerate.euler_one_qubit_decomposer
_accelerate.euler_one_qubit_decomposer
)
sys.modules["qiskit._accelerate.nlayout"] = qiskit._accelerate.nlayout
sys.modules["qiskit._accelerate.optimize_1q_gates"] = qiskit._accelerate.optimize_1q_gates
sys.modules["qiskit._accelerate.pauli_expval"] = qiskit._accelerate.pauli_expval
sys.modules["qiskit._accelerate.qasm2"] = qiskit._accelerate.qasm2
sys.modules["qiskit._accelerate.qasm3"] = qiskit._accelerate.qasm3
sys.modules["qiskit._accelerate.results"] = qiskit._accelerate.results
sys.modules["qiskit._accelerate.sabre"] = qiskit._accelerate.sabre
sys.modules["qiskit._accelerate.sampled_exp_val"] = qiskit._accelerate.sampled_exp_val
sys.modules["qiskit._accelerate.sparse_pauli_op"] = qiskit._accelerate.sparse_pauli_op
sys.modules["qiskit._accelerate.stochastic_swap"] = qiskit._accelerate.stochastic_swap
sys.modules["qiskit._accelerate.target"] = qiskit._accelerate.target
sys.modules["qiskit._accelerate.two_qubit_decompose"] = qiskit._accelerate.two_qubit_decompose
sys.modules["qiskit._accelerate.vf2_layout"] = qiskit._accelerate.vf2_layout
sys.modules["qiskit._accelerate.permutation"] = qiskit._accelerate.permutation
sys.modules["qiskit._accelerate.nlayout"] = _accelerate.nlayout
sys.modules["qiskit._accelerate.optimize_1q_gates"] = _accelerate.optimize_1q_gates
sys.modules["qiskit._accelerate.pauli_expval"] = _accelerate.pauli_expval
sys.modules["qiskit._accelerate.qasm2"] = _accelerate.qasm2
sys.modules["qiskit._accelerate.qasm3"] = _accelerate.qasm3
sys.modules["qiskit._accelerate.results"] = _accelerate.results
sys.modules["qiskit._accelerate.sabre"] = _accelerate.sabre
sys.modules["qiskit._accelerate.sampled_exp_val"] = _accelerate.sampled_exp_val
sys.modules["qiskit._accelerate.sparse_pauli_op"] = _accelerate.sparse_pauli_op
sys.modules["qiskit._accelerate.stochastic_swap"] = _accelerate.stochastic_swap
sys.modules["qiskit._accelerate.target"] = _accelerate.target
sys.modules["qiskit._accelerate.two_qubit_decompose"] = _accelerate.two_qubit_decompose
sys.modules["qiskit._accelerate.vf2_layout"] = _accelerate.vf2_layout
sys.modules["qiskit._accelerate.permutation"] = _accelerate.permutation

from qiskit.exceptions import QiskitError, MissingOptionalLibraryError

Expand Down
3 changes: 3 additions & 0 deletions qiskit/circuit/parameterexpression.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,9 @@ def __int__(self):
raise TypeError("could not cast expression to int") from exc

def __hash__(self):
if not self._parameter_symbols:
# For fully bound expressions, fall back to the underlying value
return hash(self.numeric())
return hash((self._parameter_keys, self._symbol_expr))

def __copy__(self):
Expand Down
38 changes: 22 additions & 16 deletions qiskit/circuit/parametervector.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,10 @@ def __setstate__(self, state):
class ParameterVector:
"""ParameterVector class to quickly generate lists of parameters."""

__slots__ = ("_name", "_params", "_size", "_root_uuid")
__slots__ = ("_name", "_params", "_root_uuid")

def __init__(self, name, length=0):
self._name = name
self._size = length
self._root_uuid = uuid4()
root_uuid_int = self._root_uuid.int
self._params = [
Expand All @@ -76,32 +75,38 @@ def index(self, value):
return self._params.index(value)

def __getitem__(self, key):
if isinstance(key, slice):
start, stop, step = key.indices(self._size)
return self.params[start:stop:step]

if key > self._size:
raise IndexError(f"Index out of range: {key} > {self._size}")
return self.params[key]

def __iter__(self):
return iter(self.params[: self._size])
return iter(self.params)

def __len__(self):
return self._size
return len(self._params)

def __str__(self):
return f"{self.name}, {[str(item) for item in self.params[: self._size]]}"
return f"{self.name}, {[str(item) for item in self.params]}"

def __repr__(self):
return f"{self.__class__.__name__}(name={self.name}, length={len(self)})"

def resize(self, length):
"""Resize the parameter vector.
If necessary, new elements are generated. If length is smaller than before, the
previous elements are cached and not re-generated if the vector is enlarged again.
"""Resize the parameter vector. If necessary, new elements are generated.
Note that the UUID of each :class:`.Parameter` element will be generated
deterministically given the root UUID of the ``ParameterVector`` and the index
of the element. In particular, if a ``ParameterVector`` is resized to
be smaller and then later resized to be larger, the UUID of the later
generated element at a given index will be the same as the UUID of the
previous element at that index.
This is to ensure that the parameter instances do not change.
>>> from qiskit.circuit import ParameterVector
>>> pv = ParameterVector("theta", 20)
>>> elt_19 = pv[19]
>>> rv.resize(10)
>>> rv.resize(20)
>>> pv[19] == elt_19
True
"""
if length > len(self._params):
root_uuid_int = self._root_uuid.int
Expand All @@ -111,4 +116,5 @@ def resize(self, length):
for i in range(len(self._params), length)
]
)
self._size = length
else:
del self._params[length:]
28 changes: 15 additions & 13 deletions qiskit/circuit/quantumcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1757,14 +1757,14 @@ def compose(
this can be anything that :obj:`.append` will accept.
qubits (list[Qubit|int]): qubits of self to compose onto.
clbits (list[Clbit|int]): clbits of self to compose onto.
front (bool): If True, front composition will be performed. This is not possible within
front (bool): If ``True``, front composition will be performed. This is not possible within
control-flow builder context managers.
inplace (bool): If True, modify the object. Otherwise return composed circuit.
inplace (bool): If ``True``, modify the object. Otherwise, return composed circuit.
copy (bool): If ``True`` (the default), then the input is treated as shared, and any
contained instructions will be copied, if they might need to be mutated in the
future. You can set this to ``False`` if the input should be considered owned by
the base circuit, in order to avoid unnecessary copies; in this case, it is not
valid to use ``other`` afterwards, and some instructions may have been mutated in
valid to use ``other`` afterward, and some instructions may have been mutated in
place.
var_remap (Mapping): mapping to use to rewrite :class:`.expr.Var` nodes in ``other`` as
they are inlined into ``self``. This can be used to avoid naming conflicts.
Expand Down Expand Up @@ -2068,7 +2068,7 @@ def tensor(self, other: "QuantumCircuit", inplace: bool = False) -> Optional["Qu
Args:
other (QuantumCircuit): The other circuit to tensor this circuit with.
inplace (bool): If True, modify the object. Otherwise return composed circuit.
inplace (bool): If ``True``, modify the object. Otherwise return composed circuit.
Examples:
Expand All @@ -2084,7 +2084,7 @@ def tensor(self, other: "QuantumCircuit", inplace: bool = False) -> Optional["Qu
tensored.draw('mpl')
Returns:
QuantumCircuit: The tensored circuit (returns None if inplace==True).
QuantumCircuit: The tensored circuit (returns ``None`` if ``inplace=True``).
"""
num_qubits = self.num_qubits + other.num_qubits
num_clbits = self.num_clbits + other.num_clbits
Expand Down Expand Up @@ -3126,7 +3126,7 @@ def draw(
reverse_bits: bool | None = None,
justify: str | None = None,
vertical_compression: str | None = "medium",
idle_wires: bool = True,
idle_wires: bool | None = None,
with_layout: bool = True,
fold: int | None = None,
# The type of ax is matplotlib.axes.Axes, but this is not a fixed dependency, so cannot be
Expand Down Expand Up @@ -3157,7 +3157,7 @@ def draw(
Args:
output: Select the output method to use for drawing the circuit.
Valid choices are ``text``, ``mpl``, ``latex``, ``latex_source``.
By default the `text` drawer is used unless the user config file
By default, the ``text`` drawer is used unless the user config file
(usually ``~/.qiskit/settings.conf``) has an alternative backend set
as the default. For example, ``circuit_drawer = latex``. If the output
kwarg is set, that backend will always be used over the default in
Expand Down Expand Up @@ -3203,7 +3203,9 @@ def draw(
will take less vertical room. Default is ``medium``. Only used by
the ``text`` output, will be silently ignored otherwise.
idle_wires: Include idle wires (wires with no circuit elements)
in output visualization. Default is ``True``.
in output visualization. Default is ``True`` unless the
user config file (usually ``~/.qiskit/settings.conf``) has an
alternative value set. For example, ``circuit_idle_wires = False``.
with_layout: Include layout information, with labels on the
physical layout. Default is ``True``.
fold: Sets pagination. It can be disabled using -1. In ``text``,
Expand Down Expand Up @@ -3292,7 +3294,7 @@ def size(
Args:
filter_function (callable): a function to filter out some instructions.
Should take as input a tuple of (Instruction, list(Qubit), list(Clbit)).
By default filters out "directives", such as barrier or snapshot.
By default, filters out "directives", such as barrier or snapshot.
Returns:
int: Total number of gate operations.
Expand All @@ -3314,7 +3316,7 @@ def depth(
filter_function: A function to decide which instructions count to increase depth.
Should take as a single positional input a :class:`CircuitInstruction`.
Instructions for which the function returns ``False`` are ignored in the
computation of the circuit depth. By default filters out "directives", such as
computation of the circuit depth. By default, filters out "directives", such as
:class:`.Barrier`.
Returns:
Expand Down Expand Up @@ -3445,7 +3447,7 @@ def num_connected_components(self, unitary_only: bool = False) -> int:
bits = self.qubits if unitary_only else (self.qubits + self.clbits)
bit_indices: dict[Qubit | Clbit, int] = {bit: idx for idx, bit in enumerate(bits)}

# Start with each qubit or cbit being its own subgraph.
# Start with each qubit or clbit being its own subgraph.
sub_graphs = [[bit] for bit in range(len(bit_indices))]

num_sub_graphs = len(sub_graphs)
Expand Down Expand Up @@ -3816,7 +3818,7 @@ def measure_active(self, inplace: bool = True) -> Optional["QuantumCircuit"]:
inplace (bool): All measurements inplace or return new circuit.
Returns:
QuantumCircuit: Returns circuit with measurements when `inplace = False`.
QuantumCircuit: Returns circuit with measurements when ``inplace = False``.
"""
from qiskit.converters.circuit_to_dag import circuit_to_dag

Expand Down Expand Up @@ -5704,7 +5706,7 @@ class to prepare the qubits in a specified state.
* Statevector or vector of complex amplitudes to initialize to.
* Labels of basis states of the Pauli eigenstates Z, X, Y. See
:meth:`.Statevector.from_label`. Notice the order of the labels is reversed with
respect to the qubit index to be applied to. Example label '01' initializes the
respect to the qubit index to be applied to. Example label ``'01'`` initializes the
qubit zero to :math:`|1\rangle` and the qubit one to :math:`|0\rangle`.
* An integer that is used as a bitmap indicating which qubits to initialize to
:math:`|1\rangle`. Example: setting params to 5 would initialize qubit 0 and qubit
Expand Down
2 changes: 1 addition & 1 deletion qiskit/dagcircuit/dagcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ def remove_qubits(self, *qubits):

def remove_qregs(self, *qregs):
"""
Remove classical registers from the circuit, leaving underlying bits
Remove quantum registers from the circuit, leaving underlying bits
in place.
Raises:
Expand Down
2 changes: 1 addition & 1 deletion qiskit/qpy/binary_io/value.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def _write_parameter_vec(file_obj, obj):
struct.pack(
formats.PARAMETER_VECTOR_ELEMENT_PACK,
len(name_bytes),
obj._vector._size,
len(obj._vector),
obj.uuid.bytes,
obj._index,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class SparsePauliOp(LinearOp):
:class:`~qiskit.quantum_info.Operator` in terms of N-qubit
:class:`~qiskit.quantum_info.PauliList` and complex coefficients.
It can be used for performing operator arithmetic for hundred of qubits
It can be used for performing operator arithmetic for hundreds of qubits
if the number of non-zero Pauli basis terms is sufficiently small.
The Pauli basis components are stored as a
Expand Down
6 changes: 3 additions & 3 deletions qiskit/transpiler/preset_passmanagers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,12 @@ def generate_preset_pass_manager(
This function is used to quickly generate a preset pass manager. Preset pass
managers are the default pass managers used by the :func:`~.transpile`
function. This function provides a convenient and simple method to construct
a standalone :class:`~.PassManager` object that mirrors what the transpile
a standalone :class:`~.PassManager` object that mirrors what the :func:`~.transpile`
function internally builds and uses.
The target constraints for the pass manager construction can be specified through a :class:`.Target`
instance, a `.BackendV1` or `.BackendV2` instance, or via loose constraints (``basis_gates``,
``inst_map``, ``coupling_map``, ``backend_properties``, ``instruction_durations``,
instance, a :class:`.BackendV1` or :class:`.BackendV2` instance, or via loose constraints
(``basis_gates``, ``inst_map``, ``coupling_map``, ``backend_properties``, ``instruction_durations``,
``dt`` or ``timing_constraints``).
The order of priorities for target constraints works as follows: if a ``target``
input is provided, it will take priority over any ``backend`` input or loose constraints.
Expand Down
14 changes: 14 additions & 0 deletions qiskit/user_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class UserConfig:
circuit_mpl_style = default
circuit_mpl_style_path = ~/.qiskit:<default location>
circuit_reverse_bits = True
circuit_idle_wires = False
transpile_optimization_level = 1
parallel = False
num_processes = 4
Expand Down Expand Up @@ -130,6 +131,18 @@ def read_config_file(self):
if circuit_reverse_bits is not None:
self.settings["circuit_reverse_bits"] = circuit_reverse_bits

# Parse circuit_idle_wires
try:
circuit_idle_wires = self.config_parser.getboolean(
"default", "circuit_idle_wires", fallback=None
)
except ValueError as err:
raise exceptions.QiskitUserConfigError(
f"Value assigned to circuit_idle_wires is not valid. {str(err)}"
)
if circuit_idle_wires is not None:
self.settings["circuit_idle_wires"] = circuit_idle_wires

# Parse transpile_optimization_level
transpile_optimization_level = self.config_parser.getint(
"default", "transpile_optimization_level", fallback=-1
Expand Down Expand Up @@ -191,6 +204,7 @@ def set_config(key, value, section=None, file_path=None):
"circuit_mpl_style",
"circuit_mpl_style_path",
"circuit_reverse_bits",
"circuit_idle_wires",
"transpile_optimization_level",
"parallel",
"num_processes",
Expand Down
12 changes: 9 additions & 3 deletions qiskit/visualization/circuit/circuit_visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def circuit_drawer(
reverse_bits: bool | None = None,
justify: str | None = None,
vertical_compression: str | None = "medium",
idle_wires: bool = True,
idle_wires: bool | None = None,
with_layout: bool = True,
fold: int | None = None,
# The type of ax is matplotlib.axes.Axes, but this is not a fixed dependency, so cannot be
Expand Down Expand Up @@ -115,7 +115,7 @@ def circuit_drawer(
output: Select the output method to use for drawing the circuit.
Valid choices are ``text``, ``mpl``, ``latex``, ``latex_source``.
By default the `text` drawer is used unless the user config file
By default, the ``text`` drawer is used unless the user config file
(usually ``~/.qiskit/settings.conf``) has an alternative backend set
as the default. For example, ``circuit_drawer = latex``. If the output
kwarg is set, that backend will always be used over the default in
Expand All @@ -141,7 +141,9 @@ def circuit_drawer(
will take less vertical room. Default is ``medium``. Only used by
the ``text`` output, will be silently ignored otherwise.
idle_wires: Include idle wires (wires with no circuit elements)
in output visualization. Default is ``True``.
in output visualization. Default is ``True`` unless the
user config file (usually ``~/.qiskit/settings.conf``) has an
alternative value set. For example, ``circuit_idle_wires = False``.
with_layout: Include layout information, with labels on the
physical layout. Default is ``True``.
fold: Sets pagination. It can be disabled using -1. In ``text``,
Expand Down Expand Up @@ -200,6 +202,7 @@ def circuit_drawer(
# Get default from config file else use text
default_output = "text"
default_reverse_bits = False
default_idle_wires = config.get("circuit_idle_wires", True)
if config:
default_output = config.get("circuit_drawer", "text")
if default_output == "auto":
Expand All @@ -215,6 +218,9 @@ def circuit_drawer(
if reverse_bits is None:
reverse_bits = default_reverse_bits

if idle_wires is None:
idle_wires = default_idle_wires

if wire_order is not None and reverse_bits:
raise VisualizationError(
"The wire_order option cannot be set when the reverse_bits option is True."
Expand Down
Loading

0 comments on commit 03da436

Please sign in to comment.