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

Consistent typehints for NLocal family #10479

Merged
merged 6 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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
3 changes: 1 addition & 2 deletions qiskit/circuit/library/evolved_operator_ansatz.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

from __future__ import annotations
from collections.abc import Sequence
from typing import Optional

import numpy as np

Expand All @@ -41,7 +40,7 @@ def __init__(
name: str = "EvolvedOps",
parameter_prefix: str | Sequence[str] = "t",
initial_state: QuantumCircuit | None = None,
flatten: Optional[bool] = None,
flatten: bool | None = None,
):
"""
Args:
Expand Down
32 changes: 15 additions & 17 deletions qiskit/circuit/library/n_local/efficient_su2.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

"""The EfficientSU2 2-local circuit."""

from typing import Union, Optional, List, Tuple, Callable, Any
from __future__ import annotations
from collections.abc import Callable

from numpy import pi

from qiskit.circuit import QuantumCircuit, Instruction
Expand Down Expand Up @@ -76,28 +78,24 @@ class EfficientSU2(TwoLocal):

def __init__(
self,
num_qubits: Optional[int] = None,
su2_gates: Optional[
Union[
str,
type,
Instruction,
QuantumCircuit,
List[Union[str, type, Instruction, QuantumCircuit]],
]
] = None,
entanglement: Union[str, List[List[int]], Callable[[int], List[int]]] = "reverse_linear",
num_qubits: int | None = None,
su2_gates: str
| type
| qiskit.circuit.Instruction
| QuantumCircuit
| list[str | type | qiskit.circuit.Instruction | QuantumCircuit]
| None = None,
entanglement: str | list[list[int]] | Callable[[int], list[int]] = "reverse_linear",
reps: int = 3,
skip_unentangled_qubits: bool = False,
skip_final_rotation_layer: bool = False,
parameter_prefix: str = "θ",
insert_barriers: bool = False,
initial_state: Optional[Any] = None,
initial_state: QuantumCircuit | None = None,
Comment on lines -95 to +98
Copy link
Member

Choose a reason for hiding this comment

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

Did this change deliberately?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh I thought I left a comment on that -- yes this is on purpose, we deprecated Any a few months ago (it's already gone in some NLocal circuits) but it seems we forgot it here 🙂 Any was mainly for backwards compatibility with old applications code so we don't need it anymore

name: str = "EfficientSU2",
flatten: Optional[bool] = None,
flatten: bool | None = None,
) -> None:
"""Create a new EfficientSU2 2-local circuit.

"""
Args:
num_qubits: The number of qubits of the EfficientSU2 circuit.
reps: Specifies how often the structure of a rotation layer followed by an entanglement
Expand Down Expand Up @@ -151,7 +149,7 @@ def __init__(
)

@property
def parameter_bounds(self) -> List[Tuple[float, float]]:
def parameter_bounds(self) -> list[tuple[float, float]]:
"""Return the parameter bounds.

Returns:
Expand Down
16 changes: 8 additions & 8 deletions qiskit/circuit/library/n_local/excitation_preserving.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@

"""The ExcitationPreserving 2-local circuit."""

from typing import Union, Optional, List, Tuple, Callable, Any
from __future__ import annotations
from collections.abc import Callable
from numpy import pi

from qiskit.circuit import QuantumCircuit, Parameter
Expand Down Expand Up @@ -90,20 +91,19 @@ class ExcitationPreserving(TwoLocal):

def __init__(
self,
num_qubits: Optional[int] = None,
num_qubits: int | None = None,
mode: str = "iswap",
entanglement: Union[str, List[List[int]], Callable[[int], List[int]]] = "full",
entanglement: str | list[list[int]] | Callable[[int], list[int]] = "full",
reps: int = 3,
skip_unentangled_qubits: bool = False,
skip_final_rotation_layer: bool = False,
parameter_prefix: str = "θ",
insert_barriers: bool = False,
initial_state: Optional[Any] = None,
initial_state: QuantumCircuit | None = None,
name: str = "ExcitationPreserving",
flatten: Optional[bool] = None,
flatten: bool | None = None,
) -> None:
"""Create a new ExcitationPreserving 2-local circuit.

"""
Args:
num_qubits: The number of qubits of the ExcitationPreserving circuit.
mode: Choose the entangler mode, can be `'iswap'` or `'fsim'`.
Expand Down Expand Up @@ -167,7 +167,7 @@ def __init__(
)

@property
def parameter_bounds(self) -> List[Tuple[float, float]]:
def parameter_bounds(self) -> list[tuple[float, float]]:
"""Return the parameter bounds.

Returns:
Expand Down
53 changes: 19 additions & 34 deletions qiskit/circuit/library/n_local/n_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
"""The n-local circuit class."""

from __future__ import annotations

import typing
from typing import Union, Optional, Any, Sequence, Callable, Mapping
from collections.abc import Callable, Mapping, Sequence

from itertools import combinations

import numpy
Expand Down Expand Up @@ -90,10 +90,9 @@ def __init__(
skip_unentangled_qubits: bool = False,
initial_state: QuantumCircuit | None = None,
name: str | None = "nlocal",
flatten: Optional[bool] = None,
flatten: bool | None = None,
) -> None:
"""Create a new n-local circuit.

"""
Args:
num_qubits: The number of qubits of the circuit.
rotation_blocks: The blocks used in the rotation layers. If multiple are passed,
Expand Down Expand Up @@ -123,9 +122,6 @@ def __init__(
to set this flag to ``True`` to avoid a large performance
overhead for parameter binding.

Examples:
TODO

Raises:
ValueError: If ``reps`` parameter is less than or equal to 0.
TypeError: If ``reps`` parameter is not an int value.
Expand Down Expand Up @@ -207,7 +203,7 @@ def flatten(self, flatten: bool) -> None:
self._invalidate()
self._flatten = flatten

def _convert_to_block(self, layer: Any) -> QuantumCircuit:
def _convert_to_block(self, layer: typing.Any) -> QuantumCircuit:
Comment on lines -210 to +206
Copy link
Member

Choose a reason for hiding this comment

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

Any means "don't type check this", whereas object is the base of all Python objects. The fact that this function takes either probably indicates that there's some usage of these objects that ought to be tightened up a bit, but it's not a big deal (and out of scope of this PR anyway).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this can probably be changed to Operation

"""Try to convert ``layer`` to a QuantumCircuit.

Args:
Expand Down Expand Up @@ -289,17 +285,9 @@ def entanglement_blocks(
@property
def entanglement(
self,
) -> Union[
str,
list[str],
list[list[str]],
list[int],
list[list[int]],
list[list[list[int]]],
list[list[list[list[int]]]],
Callable[[int], str],
Callable[[int], list[list[int]]],
]:
) -> str | list[str] | list[list[str]] | list[int] | list[list[int]] | list[
list[list[int]]
] | list[list[list[list[int]]]] | Callable[[int], str] | Callable[[int], list[list[int]]]:
"""Get the entanglement strategy.

Returns:
Expand All @@ -311,19 +299,16 @@ def entanglement(
@entanglement.setter
def entanglement(
self,
entanglement: Optional[
Union[
str,
list[str],
list[list[str]],
list[int],
list[list[int]],
list[list[list[int]]],
list[list[list[list[int]]]],
Callable[[int], str],
Callable[[int], list[list[int]]],
]
],
entanglement: str
| list[str]
| list[list[str]]
| list[int]
| list[list[int]]
| list[list[list[int]]]
| list[list[list[list[int]]]]
| Callable[[int], str]
| Callable[[int], list[list[int]]]
| None,
) -> None:
"""Set the entanglement strategy.

Expand Down Expand Up @@ -730,7 +715,7 @@ def parameter_bounds(self, bounds: list[tuple[float, float]]) -> None:

def add_layer(
self,
other: Union["NLocal", qiskit.circuit.Instruction, QuantumCircuit],
other: QuantumCircuit | qiskit.circuit.Instruction,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

QuantumCircuit includes "NLocal" therefore I removed the explicit mention

entanglement: list[int] | str | list[list[int]] | None = None,
front: bool = False,
) -> "NLocal":
Expand Down
3 changes: 1 addition & 2 deletions qiskit/circuit/library/n_local/qaoa_ansatz.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

# pylint: disable=cyclic-import
from __future__ import annotations
from typing import Optional

import numpy as np

Expand All @@ -41,7 +40,7 @@ def __init__(
initial_state: QuantumCircuit | None = None,
mixer_operator=None,
name: str = "QAOA",
flatten: Optional[bool] = None,
flatten: bool | None = None,
):
r"""
Args:
Expand Down
18 changes: 10 additions & 8 deletions qiskit/circuit/library/n_local/real_amplitudes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@

"""The real-amplitudes 2-local circuit."""

from typing import Union, Optional, List, Tuple, Callable, Any
from __future__ import annotations
from collections.abc import Callable

import numpy as np

from qiskit.circuit import QuantumCircuit
from qiskit.circuit.library.standard_gates import RYGate, CXGate
from .two_local import TwoLocal

Expand Down Expand Up @@ -115,19 +118,18 @@ class RealAmplitudes(TwoLocal):

def __init__(
self,
num_qubits: Optional[int] = None,
entanglement: Union[str, List[List[int]], Callable[[int], List[int]]] = "reverse_linear",
num_qubits: int | None = None,
entanglement: str | list[list[int]] | Callable[[int], list[int]] = "full",
Copy link
Member

Choose a reason for hiding this comment

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

This is a change in default.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, that change was not on purpose 😄

Copy link
Member

Choose a reason for hiding this comment

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

yes, it's always better to do "reverse_linear" and not "full" since it provides the same unitary, but with O(n) CX gates instead of O(n^2)

reps: int = 3,
skip_unentangled_qubits: bool = False,
skip_final_rotation_layer: bool = False,
parameter_prefix: str = "θ",
insert_barriers: bool = False,
initial_state: Optional[Any] = None,
initial_state: QuantumCircuit | None = None,
name: str = "RealAmplitudes",
flatten: Optional[bool] = None,
flatten: bool | None = None,
) -> None:
"""Create a new RealAmplitudes 2-local circuit.

"""
Args:
num_qubits: The number of qubits of the RealAmplitudes circuit.
reps: Specifies how often the structure of a rotation layer followed by an entanglement
Expand Down Expand Up @@ -178,7 +180,7 @@ def __init__(
)

@property
def parameter_bounds(self) -> List[Tuple[float, float]]:
def parameter_bounds(self) -> list[tuple[float, float]]:
"""Return the parameter bounds.

Returns:
Expand Down
35 changes: 21 additions & 14 deletions qiskit/circuit/library/n_local/two_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"""The two-local gate circuit."""

from __future__ import annotations
from typing import Union, Optional, List, Callable, Any, Sequence
from collections.abc import Callable, Sequence

from qiskit.circuit.quantumcircuit import QuantumCircuit
from qiskit.circuit import Gate, Instruction, Parameter
Expand Down Expand Up @@ -158,25 +158,32 @@ class TwoLocal(NLocal):

def __init__(
self,
num_qubits: Optional[int] = None,
rotation_blocks: Optional[
Union[str, List[str], type, List[type], QuantumCircuit, List[QuantumCircuit]]
] = None,
entanglement_blocks: Optional[
Union[str, List[str], type, List[type], QuantumCircuit, List[QuantumCircuit]]
] = None,
entanglement: Union[str, List[List[int]], Callable[[int], List[int]]] = "full",
num_qubits: int | None = None,
rotation_blocks: str
| list[str]
| type
| list[type]
| QuantumCircuit
| list[QuantumCircuit]
| None = None,
entanglement_blocks: str
| list[str]
| type
| list[type]
| QuantumCircuit
| list[QuantumCircuit]
| None = None,
entanglement: str | list[list[int]] | Callable[[int], list[int]] = "full",
reps: int = 3,
skip_unentangled_qubits: bool = False,
skip_final_rotation_layer: bool = False,
parameter_prefix: str = "θ",
insert_barriers: bool = False,
initial_state: Optional[Any] = None,
initial_state: QuantumCircuit | None = None,
name: str = "TwoLocal",
flatten: Optional[bool] = None,
flatten: bool | None = None,
) -> None:
"""Construct a new two-local circuit.

"""
Args:
num_qubits: The number of qubits of the two-local circuit.
rotation_blocks: The gates used in the rotation layer. Can be specified via the name of
Expand Down Expand Up @@ -233,7 +240,7 @@ def __init__(
flatten=flatten,
)

def _convert_to_block(self, layer: Union[str, type, Gate, QuantumCircuit]) -> QuantumCircuit:
def _convert_to_block(self, layer: str | type | Gate | QuantumCircuit) -> QuantumCircuit:
"""For a layer provided as str (e.g. ``'ry'``) or type (e.g. :class:`.RYGate`) this function
returns the
according layer type along with the number of parameters (e.g. ``(RYGate, 1)``).
Expand Down