diff --git a/.pylintdict b/.pylintdict index d6e0ce89e1..12111cd514 100644 --- a/.pylintdict +++ b/.pylintdict @@ -259,6 +259,8 @@ mol morse mpl mul +multi +multigraph multinomial mypy namelist diff --git a/qiskit_nature/problems/second_quantization/lattice/lattices/lattice.py b/qiskit_nature/problems/second_quantization/lattice/lattices/lattice.py index 92cb9051c7..c17c126411 100644 --- a/qiskit_nature/problems/second_quantization/lattice/lattices/lattice.py +++ b/qiskit_nature/problems/second_quantization/lattice/lattices/lattice.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2021. +# (C) Copyright IBM 2021, 2022. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -11,11 +11,14 @@ # that they have been altered from the originals. """General Lattice.""" + from copy import deepcopy from dataclasses import asdict, dataclass from typing import Callable, List, Optional, Sequence, Tuple, Union +import numbers import numpy as np + from retworkx import NodeIndices, PyGraph, WeightedEdgeList, adjacency_matrix from retworkx.visualization import mpl_draw @@ -113,17 +116,24 @@ def __init__(self, graph: PyGraph) -> None: graph: Input graph for Lattice. `graph.multigraph` must be False. Raises: - ValueError: If `graph.multigraph` is True for a given graph, it is invalid. + ValueError: If the input graph is a multigraph. + ValueError: If the graph edges are non-numeric. """ if graph.multigraph: raise ValueError( f"Invalid `graph.multigraph` {graph.multigraph} is given. " "`graph.multigraph` must be `False`." ) - if graph.edges() == [None] * graph.num_edges(): - weighted_edges = [edge + (1.0,) for edge in graph.edge_list()] - for start, end, weight in weighted_edges: - graph.update_edge(start, end, weight) + + # validate the edge weights + for edge_index, edge in graph.edge_index_map().items(): + weight = edge[2] + if weight is None or weight == {}: + # None or {} is updated to be 1 + graph.update_edge_by_index(edge_index, 1) + elif not isinstance(weight, numbers.Number): + raise ValueError(f"Unsupported weight {weight} on edge with index {edge_index}.") + self._graph = graph self.pos: Optional[dict] = None diff --git a/releasenotes/notes/lattice-edge-typecheck-3f5b4896fe26c8dc.yaml b/releasenotes/notes/lattice-edge-typecheck-3f5b4896fe26c8dc.yaml new file mode 100644 index 0000000000..e789307195 --- /dev/null +++ b/releasenotes/notes/lattice-edge-typecheck-3f5b4896fe26c8dc.yaml @@ -0,0 +1,21 @@ +--- +fixes: + - | + Add a type check for the input graphs to + :class:`~qiskit_nature.problems.second_quantization.lattice.lattices.Lattice` + which asserts that the edge weights of the graph are either numeric (or one of `None` or `{}` + which is replaced by a unit weight). This prevents possibly unexpected errors in the + application stack when an operator is constructed from the lattice. + + In particular, the following now raises a `ValueError`: + + .. code-block:: python + + from retworkx import PyGraph + from qiskit_nature.problems.second_quantization.lattice import Lattice + + graph = PyGraph(multigraph=False) + graph.add_nodes_from(range(3)) + graph.add_edges_from([(0, 1, 1), (1, 2, "banana")]) # banana is not a valid weight! + + lattice = Lattice(graph) \ No newline at end of file diff --git a/test/problems/second_quantization/lattice/lattices/test_lattice.py b/test/problems/second_quantization/lattice/lattices/test_lattice.py index 7d823f74f8..cb51707fd4 100644 --- a/test/problems/second_quantization/lattice/lattices/test_lattice.py +++ b/test/problems/second_quantization/lattice/lattices/test_lattice.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2021. +# (C) Copyright IBM 2021, 2022. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -133,3 +133,29 @@ def test_to_adjacency_matrix(self): target_matrix = np.array([[0, 1, 1], [1, 0, 0], [1, 0, 1]]) assert_array_equal(lattice.to_adjacency_matrix(), target_matrix) + + def test_nonnumeric_weight_raises(self): + """Test the initialization with a graph with non-numeric edge weights raises.""" + graph = PyGraph(multigraph=False) + graph.add_nodes_from(range(3)) + graph.add_edges_from([(0, 1, 1), (1, 2, "banana")]) + + with self.assertRaises(ValueError): + _ = Lattice(graph) + + def test_edges_removed(self): + """Test the initialization with a graph where edges have been removed.""" + graph = PyGraph(multigraph=False) + graph.add_nodes_from(range(3)) + graph.add_edges_from([(0, 1, 1), (1, 2, 1)]) + graph.remove_edge_from_index(0) + + lattice = Lattice(graph) + + target_graph = PyGraph(multigraph=False) + target_graph.add_nodes_from(range(3)) + target_graph.add_edges_from([(1, 2, 1)]) + + self.assertTrue( + is_isomorphic(lattice.graph, target_graph, edge_matcher=lambda x, y: x == y) + )