Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions src/power_grid_model_ds/_core/model/graphs/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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]]: ...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]:
Expand Down
5 changes: 3 additions & 2 deletions src/power_grid_model_ds/_core/model/grids/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
13 changes: 13 additions & 0 deletions tests/unit/model/graphs/test_graph_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/model/grids/test_grid_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down