diff --git a/VERSION b/VERSION index ea710ab..7e32cd5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2 \ No newline at end of file +1.3 diff --git a/src/power_grid_model_ds/_core/model/graphs/models/base.py b/src/power_grid_model_ds/_core/model/graphs/models/base.py index 4e38bf9..f6e50f9 100644 --- a/src/power_grid_model_ds/_core/model/graphs/models/base.py +++ b/src/power_grid_model_ds/_core/model/graphs/models/base.py @@ -2,11 +2,11 @@ # # SPDX-License-Identifier: MPL-2.0 +import warnings from abc import ABC, abstractmethod from contextlib import contextmanager from typing import Generator -import numpy as np from numpy._typing import NDArray from power_grid_model_ds._core.model.arrays.pgm_arrays import Branch3Array, BranchArray, NodeArray @@ -248,9 +248,23 @@ def get_all_paths(self, ext_start_node_id: int, ext_end_node_id: int) -> list[li return [self._internals_to_externals(path) for path in internal_paths] - def get_components(self, substation_nodes: NDArray[np.int32]) -> list[list[int]]: + def get_components(self, substation_nodes: list[int] | None = None) -> list[list[int]]: """Returns all separate components when the substation_nodes are removed of the graph as lists""" - internal_components = self._get_components(substation_nodes=self._externals_to_internals(substation_nodes)) + if substation_nodes: + warnings.warn( + message=""" +get_components: substation_nodes argument is deprecated and will be removed in a future release. +The functionality is still available with the use of the `tmp_remove_nodes` context manager. + +Example: +>>> with graph.tmp_remove_nodes(substation_nodes): +>>> components = graph.get_components() +""", + category=DeprecationWarning, + stacklevel=2, + ) + with self.tmp_remove_nodes(substation_nodes or []): + internal_components = self._get_components() return [self._internals_to_externals(component) for component in internal_components] def get_connected( @@ -389,7 +403,7 @@ def _get_shortest_path(self, source, target): ... def _get_all_paths(self, source, target) -> list[list[int]]: ... @abstractmethod - def _get_components(self, substation_nodes: list[int]) -> list[list[int]]: ... + def _get_components(self) -> list[list[int]]: ... @abstractmethod def _find_fundamental_cycles(self) -> list[list[int]]: ... diff --git a/src/power_grid_model_ds/_core/model/graphs/models/rustworkx.py b/src/power_grid_model_ds/_core/model/graphs/models/rustworkx.py index 5a68756..728d886 100644 --- a/src/power_grid_model_ds/_core/model/graphs/models/rustworkx.py +++ b/src/power_grid_model_ds/_core/model/graphs/models/rustworkx.py @@ -84,11 +84,8 @@ def _get_shortest_path(self, source: int, target: int) -> tuple[list[int], int]: def _get_all_paths(self, source: int, target: int) -> list[list[int]]: return list(rx.all_simple_paths(self._graph, source, target)) - def _get_components(self, substation_nodes: list[int]) -> list[list[int]]: - no_os_graph = self._graph.copy() - for os_node in substation_nodes: - no_os_graph.remove_node(os_node) - components = rx.connected_components(no_os_graph) + def _get_components(self) -> list[list[int]]: + components = rx.connected_components(self._graph) return [list(component) for component in components] def _get_connected(self, node_id: int, nodes_to_ignore: list[int], inclusive: bool = False) -> list[int]: diff --git a/src/power_grid_model_ds/_core/model/grids/helpers.py b/src/power_grid_model_ds/_core/model/grids/helpers.py index 0d539c7..5dcfbe0 100644 --- a/src/power_grid_model_ds/_core/model/grids/helpers.py +++ b/src/power_grid_model_ds/_core/model/grids/helpers.py @@ -45,8 +45,9 @@ def set_feeder_ids(grid: "Grid"): 601 | 101 | 204 """ _reset_feeder_ids(grid) - feeder_node_ids = grid.node.filter(node_type=NodeType.SUBSTATION_NODE).id - components = grid.graphs.active_graph.get_components(feeder_node_ids) + feeder_node_ids = grid.node.filter(node_type=NodeType.SUBSTATION_NODE)["id"] + with grid.graphs.active_graph.tmp_remove_nodes(feeder_node_ids): + components = grid.graphs.active_graph.get_components() for component_node_ids in components: component_branches = _get_active_component_branches(grid, component_node_ids) diff --git a/tests/unit/model/graphs/test_graph_model.py b/tests/unit/model/graphs/test_graph_model.py index 74cde71..96e3fff 100644 --- a/tests/unit/model/graphs/test_graph_model.py +++ b/tests/unit/model/graphs/test_graph_model.py @@ -164,6 +164,19 @@ def test_tmp_remove_nodes(graph_with_2_routes) -> None: def test_get_components(graph_with_2_routes): + graph = graph_with_2_routes + graph.add_node(99) + graph.add_node(100) + + components = graph.get_components() + + assert len(components) == 3 + assert set(components[0]) == {1, 2, 3, 4, 5} + assert set(components[1]) == {99} + assert set(components[2]) == {100} + + +def test_get_components_with_substation_nodes(graph_with_2_routes): graph = graph_with_2_routes graph.add_node(99) graph.add_branch(1, 99) diff --git a/tests/unit/model/grids/test_grid_search.py b/tests/unit/model/grids/test_grid_search.py index 5463729..f42891b 100644 --- a/tests/unit/model/grids/test_grid_search.py +++ b/tests/unit/model/grids/test_grid_search.py @@ -57,9 +57,9 @@ def test_get_branches_in_path_empty_path(self, basic_grid): def test_component_three_winding_transformer(grid_with_3wt): - component_list = grid_with_3wt.graphs.active_graph.get_components( - grid_with_3wt.node.filter(node_type=NodeType.SUBSTATION_NODE.value).id - ) + substation_nodes = grid_with_3wt.node.filter(node_type=NodeType.SUBSTATION_NODE.value).id + with grid_with_3wt.graphs.active_graph.tmp_remove_nodes(substation_nodes): + component_list = grid_with_3wt.graphs.active_graph.get_components() # check the components are as expected # use sets to make sure the order of the components is not important