diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 1ac65dd0770..b904b6e4aa8 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -210,6 +210,9 @@ still a `_qfunc_output` property on `QNode` instances. [(#4651)](https://github.com/PennyLaneAI/pennylane/pull/4651) +* `qml.data.load` properly handles parameters that come after `'full'` + [(#4663)](https://github.com/PennyLaneAI/pennylane/pull/4663) + * The `qml.jordan_wigner` function has been modified to optionally remove the imaginary components of the computed qubit operator, if imaginary components are smaller than a threshold. [(#4639)](https://github.com/PennyLaneAI/pennylane/pull/4639) diff --git a/pennylane/data/data_manager/foldermap.py b/pennylane/data/data_manager/foldermap.py index 9080535e855..bf4c0cde4e0 100644 --- a/pennylane/data/data_manager/foldermap.py +++ b/pennylane/data/data_manager/foldermap.py @@ -119,6 +119,7 @@ def find( while curr: curr_description, curr_level = curr.pop() + if param_arg == ParamArg.FULL: next_params = curr_level elif param_arg == ParamArg.DEFAULT: @@ -131,18 +132,29 @@ def find( else: next_params = param_arg - try: - todo.extend( + for next_param in next_params: + try: + fmap_next = curr_level[next_param] + except KeyError: + continue + + todo.append( ( Description((*curr_description.items(), (param_name, next_param))), - curr_level[next_param], + fmap_next, ) - for next_param in next_params ) - except KeyError as exc: - raise ValueError( - f"{param_name} '{exc.args[0]}' is not available. Available values are: {list(curr_level)}" - ) from exc + + if len(todo) == 0: + # None of the parameters matched + param_arg_repr = ( + repr([param_arg]) + if isinstance(param_arg, (str, ParamArg)) + else repr(list(param_arg)) + ) + raise ValueError( + f"{param_name} value(s) {param_arg_repr} are not available. Available values are: {list(curr_level)}" + ) curr, todo = todo, curr diff --git a/tests/data/data_manager/test_foldermap.py b/tests/data/data_manager/test_foldermap.py index 2bfa56e6073..8b5b21c8818 100644 --- a/tests/data/data_manager/test_foldermap.py +++ b/tests/data/data_manager/test_foldermap.py @@ -15,6 +15,8 @@ Tests for the :class:`pennylane.data.data_manger.FolderMapView` class. """ +import re + import pytest from pennylane.data.data_manager import DEFAULT, FULL, DataPath @@ -125,6 +127,38 @@ class TestFolderMapView: ), ], ), + ( + {"missing_default": DEFAULT, "molname": "O2", "basis": FULL, "bondlength": ["0.6"]}, + [ + ( + {"molname": "O2", "basis": "STO-3G", "bondlength": "0.6"}, + "qchem/O2/STO-3G/0.6.h5", + ), + ], + ), + ( + { + "missing_default": DEFAULT, + "molname": "O2", + "basis": FULL, + "bondlength": ["0.6", "200"], + }, + [ + ( + {"molname": "O2", "basis": "STO-3G", "bondlength": "0.6"}, + "qchem/O2/STO-3G/0.6.h5", + ), + ], + ), + ( + {"missing_default": FULL, "molname": "O2", "bondlength": ["0.6"]}, + [ + ( + {"molname": "O2", "basis": "STO-3G", "bondlength": "0.6"}, + "qchem/O2/STO-3G/0.6.h5", + ), + ], + ), ], ) def test_find(self, foldermap, kwds, expect): # pylint: disable=redefined-outer-name @@ -155,14 +189,36 @@ def test_find_missing_arg_no_default(self): with pytest.raises(ValueError, match="No default available for parameter 'molname'"): FolderMapView(FOLDERMAP).find("qchem") - def test_find_invalid_parameter(self): + @pytest.mark.parametrize( + "arg, error_fmt", [("Z3", repr(["Z3"])), (("Z3", "Z4"), repr(["Z3", "Z4"]))] + ) + def test_find_invalid_parameter(self, arg, error_fmt): """Test that a ValueError is raised when a parameter provided does not exist.""" with pytest.raises( - ValueError, match=r"molname 'Z3' is not available. Available values are: \['O2', 'H2'\]" + ValueError, + match=re.escape( + f"molname value(s) {error_fmt} are not available. Available values are: ['O2', 'H2']" + ), ): - FolderMapView(FOLDERMAP).find("qchem", molname="Z3") + FolderMapView(FOLDERMAP).find("qchem", molname=arg) + + @pytest.mark.parametrize("basis", [FULL, DEFAULT]) + def test_find_invalid_parameters_after_full_default(self, basis): + """Test that a ValueError is raised when a parameter provided + does not exist, after a 'full' or 'default' parameter has been provided for a + higher-priority parameter.""" + + with pytest.raises( + ValueError, + match=( + r"bondlength value\(s\) \['0.20', '200'\] are not available. Available values are: \['0.5', '0.6'\]" + ), + ): + FolderMapView(FOLDERMAP).find( + "qchem", molname="O2", basis=basis, bondlength=["0.20", "200"] + ) @pytest.mark.parametrize( "init, key, expect",