Skip to content

Commit

Permalink
Hotfix: Preserve qubit IDs and order in Register.with_automatic_layou…
Browse files Browse the repository at this point in the history
…t() (#759)

* Preserve qubit IDs and order in Register.with_automatic_layout()

* Bump version to v1.1.1

* Fail for registers with differentiable coordinates
  • Loading branch information
HGSilveri authored Oct 31, 2024
1 parent 14da4eb commit 3c76edd
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 4 deletions.
2 changes: 1 addition & 1 deletion VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.0
1.1.1
20 changes: 18 additions & 2 deletions pulser-core/pulser/register/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,8 @@ def with_automatic_layout(
Raises:
RuntimeError: If the automatic layout generation fails to meet
the device constraints.
NotImplementedError: When the register has differentiable
coordinates (ie torch Tensors with requires_grad=True).
Returns:
Register: A new register instance with identical qubit IDs and
Expand All @@ -353,6 +355,15 @@ def with_automatic_layout(
raise TypeError(
f"'device' must be of type Device, not {type(device)}."
)
if (
self._coords_arr.is_tensor
and self._coords_arr.as_tensor().requires_grad
):
raise NotImplementedError(
"'Register.with_automatic_layout()' does not support "
"registers with differentiable coordinates."
)

trap_coords = generate_trap_coordinates(
self.sorted_coords,
min_trap_dist=device.min_atom_distance,
Expand All @@ -363,8 +374,13 @@ def with_automatic_layout(
max_traps=device.max_layout_traps,
)
layout = pulser.register.RegisterLayout(trap_coords, slug=layout_slug)
trap_ids = layout.get_traps_from_coordinates(*self.sorted_coords)
return cast(Register, layout.define_register(*trap_ids))
trap_ids = layout.get_traps_from_coordinates(
*self._coords_arr.as_array()
)
return cast(
Register,
layout.define_register(*trap_ids, qubit_ids=self.qubit_ids),
)

def rotated(self, degrees: float) -> Register:
"""Makes a new rotated register.
Expand Down
15 changes: 14 additions & 1 deletion tests/test_register.py
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ def test_register_recipes_torch(

@pytest.mark.parametrize("optimal_filling", [None, 0.4, 0.1])
def test_automatic_layout(optimal_filling):
reg = Register.square(4, spacing=5)
reg = Register.square(4, spacing=5, prefix="test")
max_layout_filling = 0.5
min_traps = int(np.ceil(len(reg.qubits) / max_layout_filling))
optimal_traps = int(
Expand All @@ -610,6 +610,8 @@ def test_automatic_layout(optimal_filling):

# On its own, it works
new_reg = reg.with_automatic_layout(device, layout_slug="foo")
assert new_reg.qubit_ids == reg.qubit_ids # Same IDs in the same order
assert new_reg == reg # The register itself is identical
assert isinstance(new_reg.layout, RegisterLayout)
assert str(new_reg.layout) == "foo"
trap_num = new_reg.layout.number_of_traps
Expand Down Expand Up @@ -657,3 +659,14 @@ def test_automatic_layout(optimal_filling):
big_reg.with_automatic_layout(device).layout.number_of_traps
>= min_traps
)


def test_automatic_layout_diff():
torch = pytest.importorskip("torch")
with pytest.raises(
NotImplementedError,
match="does not support registers with differentiable coordinates",
):
Register.square(
2, spacing=torch.tensor(10.0, requires_grad=True)
).with_automatic_layout(AnalogDevice)

0 comments on commit 3c76edd

Please sign in to comment.