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

Enhance ValueError messages (#148 and #157) #185

Merged
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
81 changes: 44 additions & 37 deletions pulser/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,24 +107,25 @@ def rectangle(cls, rows: int, columns: int, spacing: float = 4.0,
"""
# Check rows
if rows < 1:
raise ValueError(
f"The number of rows ({rows}) must be 1 or above.")
raise ValueError(f"The number of rows (`rows` = {rows})"
" must be greater than or equal to 1.")

# Check columns
if columns < 1:
raise ValueError(
f"The number of columns ({columns}) must be 1 or above.")
raise ValueError(f"The number of columns (`columns` = {columns})"
" must be greater than or equal to 1.")

# Check spacing
if spacing <= 0.0:
raise ValueError(f"Spacing ({spacing}) must be above 0.0.")
raise ValueError(f"Spacing between atoms (`spacing` = {spacing})"
" must be greater than 0.")

coords = np.array([(x, y) for y in range(rows)
for x in range(columns)], dtype=float) * spacing

return cls.from_coordinates(coords, center=True, prefix=prefix)

@classmethod
@ classmethod
def square(cls, side: int, spacing: float = 4.0,
prefix: Optional[str] = None) -> Register:
"""Initializes the register with the qubits in a square array.
Expand All @@ -143,12 +144,12 @@ def square(cls, side: int, spacing: float = 4.0,
"""
# Check side
if side < 1:
raise ValueError(
f"The number of atoms per side ({side}) must be 1 or above.")
raise ValueError(f"The number of atoms per side (`side` = {side})"
" must be greater than or equal to 1.")

return cls.rectangle(side, side, spacing=spacing, prefix=prefix)

@classmethod
@ classmethod
def triangular_lattice(cls, rows: int, atoms_per_row: int,
spacing: float = 4.0,
prefix: Optional[str] = None) -> Register:
Expand All @@ -174,18 +175,19 @@ def triangular_lattice(cls, rows: int, atoms_per_row: int,

# Check rows
if rows < 1:
raise ValueError(
f"The number of rows ({rows}) must be 1 or above.")
raise ValueError(f"The number of rows (`rows` = {rows})"
" must be greater than or equal to 1.")

# Check atoms per row
if atoms_per_row < 1:
raise ValueError(
f"The number of atoms per row ({atoms_per_row})"
" must be 1 or above.")
raise ValueError("The number of atoms per row"
f" (`atoms_per_row` = {atoms_per_row})"
" must be greater than or equal to 1.")

# Check spacing
if spacing <= 0.0:
raise ValueError(f"Spacing ({spacing}) must be above 0.0.")
raise ValueError(f"Spacing between atoms (`spacing` = {spacing})"
" must be greater than 0.")

coords = np.array([(x, y) for y in range(rows)
for x in range(atoms_per_row)], dtype=float)
Expand All @@ -195,7 +197,7 @@ def triangular_lattice(cls, rows: int, atoms_per_row: int,

return cls.from_coordinates(coords, center=True, prefix=prefix)

@classmethod
@ classmethod
def _hexagon_helper(cls, layers: int, atoms_left: int, spacing: float,
prefix: Optional[str] = None) -> Register:
"""Helper function for building hexagonal arrays.
Expand Down Expand Up @@ -226,7 +228,7 @@ def _hexagon_helper(cls, layers: int, atoms_left: int, spacing: float,
delta_y = [crest_y, 0.0, -crest_y, -crest_y, 0.0, crest_y]

coords = np.array([(start_x[side] * layer + atom * delta_x[side],
start_y[side] * layer + atom * delta_y[side])
start_y[side] * layer + atom * delta_y[side])
for layer in range(1, layers + 1)
for side in range(6)
for atom in range(1, layer + 1)], dtype=float)
Expand All @@ -243,12 +245,13 @@ def _hexagon_helper(cls, layers: int, atoms_left: int, spacing: float,
sides_order = [0, 3, 1, 4, 2, 5]

coords2 = np.array([(start_x[side] * layer + atom * delta_x[side],
start_y[side] * layer + atom * delta_y[side])
for side in range(6)
for atom in range(1, min_atoms_per_side + 2
if atoms_left >
sides_order[side]
else min_atoms_per_side + 1)],
start_y[side] * layer + atom * delta_y[side])
for side in range(6)
for atom in range(1, min_atoms_per_side + 2
if atoms_left >
sides_order[side]
else
min_atoms_per_side + 1)],
dtype=float)

coords = np.concatenate((coords, coords2))
Expand All @@ -258,7 +261,7 @@ def _hexagon_helper(cls, layers: int, atoms_left: int, spacing: float,

return cls.from_coordinates(coords, center=False, prefix=prefix)

@classmethod
@ classmethod
def hexagon(cls, layers: int, spacing: float = 4.0,
prefix: Optional[str] = None) -> Register:
"""Initializes the register with the qubits in a hexagonal layout.
Expand All @@ -278,16 +281,17 @@ def hexagon(cls, layers: int, spacing: float = 4.0,

# Check layers
if layers < 1:
raise ValueError(
f"The number of layers ({layers}) must be 1 or above.")
raise ValueError(f"The number of layers (`layers` = {layers})"
" must be greater than or equal to 1.")

# Check spacing
if spacing <= 0.0:
raise ValueError(f"Spacing ({spacing}) must be above 0.0.")
raise ValueError(f"Spacing between atoms (`spacing` = {spacing})"
" must be greater than 0.")

return cls._hexagon_helper(layers, 0, spacing, prefix)

@classmethod
@ classmethod
def max_connectivity(cls, n_qubits: int,
device: pulser.devices._device_datacls.Device,
spacing: float = None,
Expand Down Expand Up @@ -321,22 +325,24 @@ def max_connectivity(cls, n_qubits: int,

# Check number of qubits (1 or above)
if n_qubits < 1:
raise ValueError(
f"The number of qubits ({n_qubits}) must be 1 or above.")
raise ValueError(f"The number of qubits (`n_qubits` = {n_qubits})"
" must be greater than or equal to 1.")

# Check number of qubits (less than the max number of atoms)
if n_qubits > device.max_atom_num:
raise ValueError(f"The number of qubits ({n_qubits})"
" can not exceed the maximum number of"
" atoms supported by this device"
raise ValueError(f"The number of qubits (`n_qubits` = {n_qubits})"
" must be less than or equal to the maximum"
" number of atoms supported by this device"
f" ({device.max_atom_num}).")

# Default spacing or check minimal distance
if spacing is None:
spacing = device.min_atom_distance
elif spacing < device.min_atom_distance:
raise ValueError(f"Spacing ({spacing}) for this device must be"
f" {device.min_atom_distance} or above.")
raise ValueError(f"Spacing between atoms (`spacing = `{spacing})"
" must be greater than or equal to the minimal"
" distance supported by this device"
f" ({device.min_atom_distance}).")

if n_qubits < 7:
crest_y = np.sqrt(3) / 2.0
Expand Down Expand Up @@ -395,8 +401,9 @@ def draw(self, with_labels: bool = True,

# Check spacing
if blockade_radius is not None and blockade_radius <= 0.0:
raise ValueError(
f"Blockade radius ({blockade_radius}) must be above 0.0.")
raise ValueError("Blockade radius (`blockade_radius` ="
f" {blockade_radius})"
" must be greater than 0.")

pos = np.array(self._coords)
diffs = np.max(pos, axis=0) - np.min(pos, axis=0)
Expand Down
6 changes: 4 additions & 2 deletions pulser/tests/test_register.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,13 @@ def test_max_connectivity():
reg = Register.max_connectivity(2, None)

# Check min number of atoms
with pytest.raises(ValueError, match=r"The number of qubits(.+)or above"):
with pytest.raises(ValueError,
match=r"The number of qubits(.+)greater than"):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Cool, I didn't know about this syntax

reg = Register.max_connectivity(0, device)

# Check max number of atoms
with pytest.raises(ValueError, match=r"The number of qubits(.+)exceed"):
with pytest.raises(ValueError,
match=r"The number of qubits(.+)less than"):
reg = Register.max_connectivity(max_atom_num + 1, device)

# Check spacing
Expand Down