Skip to content

Commit

Permalink
Merge branch 'master' into fermi-commute
Browse files Browse the repository at this point in the history
  • Loading branch information
willjmax committed Sep 16, 2024
2 parents 3cd4415 + 94f067a commit 1a63c26
Show file tree
Hide file tree
Showing 17 changed files with 88 additions and 60 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/install_deps/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,23 @@ inputs:
jax_version:
description: The version of JAX to install for any job that requires JAX
required: false
default: 0.4.23
default: '0.4.23'
install_tensorflow:
description: Indicate if TensorFlow should be installed or not
required: false
default: 'true'
tensorflow_version:
description: The version of TensorFlow to install for any job that requires TensorFlow
required: false
default: 2.16.0
default: '2.16.0'
install_pytorch:
description: Indicate if PyTorch should be installed or not
required: false
default: 'true'
pytorch_version:
description: The version of PyTorch to install for any job that requires PyTorch
required: false
default: 2.3.0
default: '2.3.0'
install_pennylane_lightning_master:
description: Indicate if PennyLane-Lightning should be installed from the master branch
required: false
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ config.toml
qml_debug.log
datasets/*
.benchmarks/*
*.h5
*.hdf5
5 changes: 5 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

<h3>Improvements 🛠</h3>

* PennyLane is now compatible with NumPy 2.0.
[(#6061)](https://github.com/PennyLaneAI/pennylane/pull/6061)

* `qml.qchem.excitations` now optionally returns fermionic operators.
[(#6171)](https://github.com/PennyLaneAI/pennylane/pull/6171)

Expand Down Expand Up @@ -127,6 +130,8 @@ This release contains contributions from (in alphabetical order):
Guillermo Alonso,
Utkarsh Azad,
Lillian M. A. Frederiksen,
Pietropaolo Frisoni,
Emiliano Godinez,
Christina Lee,
William Maxwell,
Lee J. O'Riordan,
Expand Down
5 changes: 3 additions & 2 deletions pennylane/numpy/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,19 @@
it works with the PennyLane :class:`~.tensor` class.
"""

from autograd.numpy import random as _random
# isort: skip_file
from numpy import __version__ as np_version
from numpy.random import MT19937, PCG64, SFC64, Philox # pylint: disable=unused-import
from autograd.numpy import random as _random
from packaging.specifiers import SpecifierSet
from packaging.version import Version

from .wrapper import tensor_wrapper, wrap_arrays

wrap_arrays(_random.__dict__, globals())


if Version(np_version) in SpecifierSet(">=0.17.0"):

# pylint: disable=too-few-public-methods
# pylint: disable=missing-class-docstring
class Generator(_random.Generator):
Expand Down
2 changes: 1 addition & 1 deletion requirements-ci.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
numpy
scipy<1.13.0
scipy<=1.13.0
cvxpy
cvxopt
networkx
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
version = f.readlines()[-1].split()[-1].strip("\"'")

requirements = [
"numpy<2.0",
"numpy<=2.0",
"scipy",
"networkx",
"rustworkx>=0.14.0",
Expand Down
11 changes: 8 additions & 3 deletions tests/data/attributes/operator/test_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ def test_value_init(self, attribute_cls, op_in):
"""Test that a DatasetOperator can be value-initialized
from an operator, and that the deserialized operator
is equivalent."""

if not qml.operation.active_new_opmath() and isinstance(op_in, qml.ops.LinearCombination):
op_in = qml.operation.convert_to_legacy_H(op_in)

Expand All @@ -183,7 +184,8 @@ def test_value_init(self, attribute_cls, op_in):
assert dset_op.info["py_type"] == get_type_str(type(op_in))

op_out = dset_op.get_value()
assert repr(op_out) == repr(op_in)
with np.printoptions(legacy="1.21"):
assert repr(op_out) == repr(op_in)
assert op_in.data == op_out.data

@pytest.mark.parametrize(
Expand All @@ -199,6 +201,7 @@ def test_bind_init(self, attribute_cls, op_in):
"""Test that a DatasetOperator can be bind-initialized
from an operator, and that the deserialized operator
is equivalent."""

if not qml.operation.active_new_opmath() and isinstance(op_in, qml.ops.LinearCombination):
op_in = qml.operation.convert_to_legacy_H(op_in)

Expand All @@ -210,10 +213,12 @@ def test_bind_init(self, attribute_cls, op_in):
assert dset_op.info["py_type"] == get_type_str(type(op_in))

op_out = dset_op.get_value()
assert repr(op_out) == repr(op_in)
with np.printoptions(legacy="1.21"):
assert repr(op_out) == repr(op_in)
assert op_in.data == op_out.data
assert op_in.wires == op_out.wires
assert repr(op_in) == repr(op_out)
with np.printoptions(legacy="1.21"):
assert repr(op_in) == repr(op_out)


@pytest.mark.parametrize("attribute_cls", [DatasetOperator, DatasetPyTree])
Expand Down
10 changes: 7 additions & 3 deletions tests/data/attributes/test_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
Tests for the ``DatasetDict`` attribute type.
"""

import numpy as np
import pytest

from pennylane.data.attributes import DatasetDict
Expand Down Expand Up @@ -45,7 +46,8 @@ def test_value_init(self, value):
assert dset_dict.info.py_type == "dict"
assert dset_dict.bind.keys() == value.keys()
assert len(dset_dict) == len(value)
assert repr(value) == repr(dset_dict)
with np.printoptions(legacy="1.21"):
assert repr(value) == repr(dset_dict)

@pytest.mark.parametrize(
"value", [{"a": 1, "b": 2}, {}, {"a": 1, "b": {"x": "y", "z": [1, 2]}}]
Expand Down Expand Up @@ -93,7 +95,8 @@ def test_copy(self, value):

assert builtin_dict.keys() == value.keys()
assert len(builtin_dict) == len(value)
assert repr(builtin_dict) == repr(value)
with np.printoptions(legacy="1.21"):
assert repr(builtin_dict) == repr(value)

@pytest.mark.parametrize(
"value", [{"a": 1, "b": 2}, {}, {"a": 1, "b": {"x": "y", "z": [1, 2]}}]
Expand Down Expand Up @@ -121,4 +124,5 @@ def test_equality_same_length(self):
)
def test_string_conversion(self, value):
dset_dict = DatasetDict(value)
assert str(dset_dict) == str(value)
with np.printoptions(legacy="1.21"):
assert str(dset_dict) == str(value)
12 changes: 9 additions & 3 deletions tests/data/attributes/test_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from itertools import combinations

import numpy as np
import pytest

from pennylane.data import DatasetList
Expand Down Expand Up @@ -56,8 +57,9 @@ def test_value_init(self, input_type, value):

lst = DatasetList(input_type(value))
assert lst == value
assert repr(lst) == repr(value)
assert len(lst) == len(value)
with np.printoptions(legacy="1.21"):
assert repr(lst) == repr(value)

@pytest.mark.parametrize("input_type", (list, tuple))
@pytest.mark.parametrize("value", [[], [1], [1, 2, 3], ["a", "b", "c"], [{"a": 1}]])
Expand Down Expand Up @@ -148,12 +150,14 @@ def test_setitem_out_of_range(self, index):
@pytest.mark.parametrize("value", [[], [1], [1, 2, 3], ["a", "b", "c"], [{"a": 1}]])
def test_copy(self, input_type, value):
"""Test that a `DatasetList` can be copied."""

ds = DatasetList(input_type(value))
ds_copy = ds.copy()

assert ds_copy == value
assert repr(ds_copy) == repr(value)
assert len(ds_copy) == len(value)
with np.printoptions(legacy="1.21"):
assert repr(ds_copy) == repr(value)

@pytest.mark.parametrize("input_type", (list, tuple))
@pytest.mark.parametrize("value", [[], [1], [1, 2, 3], ["a", "b", "c"], [{"a": 1}]])
Expand All @@ -169,8 +173,10 @@ def test_equality(self, input_type, value):
@pytest.mark.parametrize("value", [[], [1], [1, 2, 3], ["a", "b", "c"], [{"a": 1}]])
def test_string_conversion(self, value):
"""Test that a `DatasetList` is converted to a string correctly."""

dset_dict = DatasetList(value)
assert str(dset_dict) == str(value)
with np.printoptions(legacy="1.21"):
assert str(dset_dict) == str(value)

@pytest.mark.parametrize("value", [[1], [1, 2, 3], ["a", "b", "c"], [{"a": 1}]])
def test_deleting_elements(self, value):
Expand Down
4 changes: 2 additions & 2 deletions tests/data/base/test_attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,8 @@ def test_bind_init_from_other_bind(self):
)
def test_repr(self, val, attribute_type):
"""Test that __repr__ has the expected format."""

assert repr(attribute(val)) == f"{attribute_type.__name__}({repr(val)})"
with np.printoptions(legacy="1.21"):
assert repr(attribute(val)) == f"{attribute_type.__name__}({repr(val)})"

@pytest.mark.parametrize(
"val",
Expand Down
8 changes: 4 additions & 4 deletions tests/devices/qubit/test_measure.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ class TestNaNMeasurements:
def test_nan_float_result(self, mp, interface):
"""Test that the result of circuits with 0 probability postselections is NaN with the
expected shape."""
state = qml.math.full((2, 2), np.NaN, like=interface)
state = qml.math.full((2, 2), np.nan, like=interface)
res = measure(mp, state, is_state_batched=False)

assert qml.math.ndim(res) == 0
Expand Down Expand Up @@ -339,7 +339,7 @@ def test_nan_float_result(self, mp, interface):
def test_nan_float_result_jax(self, mp, use_jit):
"""Test that the result of circuits with 0 probability postselections is NaN with the
expected shape."""
state = qml.math.full((2, 2), np.NaN, like="jax")
state = qml.math.full((2, 2), np.nan, like="jax")
if use_jit:
import jax

Expand All @@ -360,7 +360,7 @@ def test_nan_float_result_jax(self, mp, use_jit):
def test_nan_probs(self, mp, interface):
"""Test that the result of circuits with 0 probability postselections is NaN with the
expected shape."""
state = qml.math.full((2, 2), np.NaN, like=interface)
state = qml.math.full((2, 2), np.nan, like=interface)
res = measure(mp, state, is_state_batched=False)

assert qml.math.shape(res) == (2 ** len(mp.wires),)
Expand All @@ -375,7 +375,7 @@ def test_nan_probs(self, mp, interface):
def test_nan_probs_jax(self, mp, use_jit):
"""Test that the result of circuits with 0 probability postselections is NaN with the
expected shape."""
state = qml.math.full((2, 2), np.NaN, like="jax")
state = qml.math.full((2, 2), np.nan, like="jax")
if use_jit:
import jax

Expand Down
14 changes: 7 additions & 7 deletions tests/devices/qubit/test_sampling.py
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ def test_only_catch_nan_errors(self, shots):
mp = qml.expval(qml.PauliZ(0))
_shots = Shots(shots)

with pytest.raises(ValueError, match="probabilities do not sum to 1"):
with pytest.raises(ValueError, match=r"(?i)probabilities do not sum to 1"):
_ = measure_with_samples([mp], state, _shots)

@pytest.mark.all_interfaces
Expand Down Expand Up @@ -619,7 +619,7 @@ def test_only_catch_nan_errors(self, shots):
def test_nan_float_result(self, mp, interface, shots):
"""Test that the result of circuits with 0 probability postselections is NaN with the
expected shape."""
state = qml.math.full((2, 2), np.NaN, like=interface)
state = qml.math.full((2, 2), np.nan, like=interface)
res = measure_with_samples((mp,), state, _FlexShots(shots), is_state_batched=False)

if not isinstance(shots, list):
Expand All @@ -646,7 +646,7 @@ def test_nan_float_result(self, mp, interface, shots):
def test_nan_samples(self, mp, interface, shots):
"""Test that the result of circuits with 0 probability postselections is NaN with the
expected shape."""
state = qml.math.full((2, 2), np.NaN, like=interface)
state = qml.math.full((2, 2), np.nan, like=interface)
res = measure_with_samples((mp,), state, _FlexShots(shots), is_state_batched=False)

if not isinstance(shots, list):
Expand All @@ -672,7 +672,7 @@ def test_nan_samples(self, mp, interface, shots):
def test_nan_classical_shadows(self, interface, shots):
"""Test that classical_shadows returns an empty array when the state has
NaN values"""
state = qml.math.full((2, 2), np.NaN, like=interface)
state = qml.math.full((2, 2), np.nan, like=interface)
res = measure_with_samples(
(qml.classical_shadow([0]),), state, _FlexShots(shots), is_state_batched=False
)
Expand All @@ -699,7 +699,7 @@ def test_nan_classical_shadows(self, interface, shots):
def test_nan_shadow_expval(self, H, interface, shots):
"""Test that shadow_expval returns an empty array when the state has
NaN values"""
state = qml.math.full((2, 2), np.NaN, like=interface)
state = qml.math.full((2, 2), np.nan, like=interface)
res = measure_with_samples(
(qml.shadow_expval(H),), state, _FlexShots(shots), is_state_batched=False
)
Expand Down Expand Up @@ -757,7 +757,7 @@ def test_sample_state_renorm_error(self, interface):
"""Test that renormalization does not occur if the error is too large."""

state = qml.math.array(two_qubit_state_not_normalized, like=interface)
with pytest.raises(ValueError, match="probabilities do not sum to 1"):
with pytest.raises(ValueError, match=r"(?i)probabilities do not sum to 1"):
_ = sample_state(state, 10)

@pytest.mark.all_interfaces
Expand All @@ -775,7 +775,7 @@ def test_sample_batched_state_renorm_error(self, interface):
"""Test that renormalization does not occur if the error is too large."""

state = qml.math.array(batched_state_not_normalized, like=interface)
with pytest.raises(ValueError, match="probabilities do not sum to 1"):
with pytest.raises(ValueError, match=r"(?i)probabilities do not sum to 1"):
_ = sample_state(state, 10, is_state_batched=True)


Expand Down
2 changes: 1 addition & 1 deletion tests/devices/qutrit_mixed/test_qutrit_mixed_sampling.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ def test_only_catch_nan_errors(self, shots):
mp = qml.sample(wires=range(2))
_shots = Shots(shots)

with pytest.raises(ValueError, match="probabilities do not sum to 1"):
with pytest.raises(ValueError, match=r"(?i)probabilities do not sum to 1"):
_ = measure_with_samples(mp, state, _shots)

@pytest.mark.parametrize("mp", [qml.probs(0), qml.probs(op=qml.GellMann(0, 1))])
Expand Down
44 changes: 23 additions & 21 deletions tests/devices/test_default_qubit_legacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# pylint: disable=protected-access,cell-var-from-loop
import cmath
import math
from importlib.metadata import version

import pytest

Expand Down Expand Up @@ -628,7 +629,8 @@ def test_apply_global_phase(self, qubit_device_3_wires, tol, wire, input_state):
expected_output = np.array(input_state) * np.exp(-1j * phase)

assert np.allclose(qubit_device_3_wires._state, np.array(expected_output), atol=tol, rtol=0)
assert qubit_device_3_wires._state.dtype == qubit_device_3_wires.C_DTYPE
if version("numpy") < "2.0.0":
assert qubit_device_3_wires._state.dtype == qubit_device_3_wires.C_DTYPE

def test_apply_errors_qubit_state_vector(self, qubit_device_2_wires):
"""Test that apply fails for incorrect state preparation, and > 2 qubit gates"""
Expand All @@ -650,26 +652,26 @@ def test_apply_errors_qubit_state_vector(self, qubit_device_2_wires):
)

def test_apply_errors_basis_state(self, qubit_device_2_wires):

with pytest.raises(
ValueError, match=r"Basis state must only consist of 0s and 1s; got \[-0\.2, 4\.2\]"
):
qubit_device_2_wires.apply([qml.BasisState(np.array([-0.2, 4.2]), wires=[0, 1])])

with pytest.raises(
ValueError, match=r"State must be of length 1; got length 2 \(state=\[0 1\]\)\."
):
qubit_device_2_wires.apply([qml.BasisState(np.array([0, 1]), wires=[0])])

with pytest.raises(
qml.DeviceError,
match="Operation BasisState cannot be used after other Operations have already been applied "
"on a default.qubit.legacy device.",
):
qubit_device_2_wires.reset()
qubit_device_2_wires.apply(
[qml.RZ(0.5, wires=[0]), qml.BasisState(np.array([1, 1]), wires=[0, 1])]
)
with np.printoptions(legacy="1.21"):
with pytest.raises(
ValueError, match=r"Basis state must only consist of 0s and 1s; got \[-0\.2, 4\.2\]"
):
qubit_device_2_wires.apply([qml.BasisState(np.array([-0.2, 4.2]), wires=[0, 1])])

with pytest.raises(
ValueError, match=r"State must be of length 1; got length 2 \(state=\[0 1\]\)\."
):
qubit_device_2_wires.apply([qml.BasisState(np.array([0, 1]), wires=[0])])

with pytest.raises(
qml.DeviceError,
match="Operation BasisState cannot be used after other Operations have already been applied "
"on a default.qubit.legacy device.",
):
qubit_device_2_wires.reset()
qubit_device_2_wires.apply(
[qml.RZ(0.5, wires=[0]), qml.BasisState(np.array([1, 1]), wires=[0, 1])]
)


class TestExpval:
Expand Down
Loading

0 comments on commit 1a63c26

Please sign in to comment.