From 269182bec809d192cda469264a64f368496dce41 Mon Sep 17 00:00:00 2001 From: Vincent Koppen Date: Wed, 29 Jan 2025 11:40:14 +0100 Subject: [PATCH 1/5] refactor(BaseGraph): improve performance of get_components Signed-off-by: Vincent Koppen --- src/power_grid_model_ds/_core/model/graphs/models/base.py | 5 +++-- .../_core/model/graphs/models/rustworkx.py | 7 ++----- 2 files changed, 5 insertions(+), 7 deletions(-) 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 4f0a7bd..1a4cb3a 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 @@ -250,7 +250,8 @@ def get_all_paths(self, ext_start_node_id: int, ext_end_node_id: int) -> list[li def get_components(self, substation_nodes: NDArray[np.int32]) -> 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)) + with self.tmp_remove_nodes(substation_nodes): + internal_components = self._get_components() return [self._internals_to_externals(component) for component in internal_components] def get_connected( @@ -345,7 +346,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 b509391..39c66e5 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]: From 68adcd299bcf192a9a49f7be3151c96d71c66a72 Mon Sep 17 00:00:00 2001 From: Vincent Koppen Date: Wed, 29 Jan 2025 11:58:31 +0100 Subject: [PATCH 2/5] fix typing Signed-off-by: Vincent Koppen --- src/power_grid_model_ds/_core/model/graphs/models/base.py | 2 +- src/power_grid_model_ds/_core/model/grids/helpers.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 1a4cb3a..e717b4a 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 @@ -183,7 +183,7 @@ def delete_branch3_array(self, branch_array: Branch3Array, raise_on_fail: bool = self.delete_branch_array(branches, raise_on_fail=raise_on_fail) @contextmanager - def tmp_remove_nodes(self, nodes: list[int]) -> Generator: + def tmp_remove_nodes(self, nodes: list[int] | NDArray[np.int32]) -> Generator: """Context manager that temporarily removes nodes and their branches from the graph. Example: >>> with graph.tmp_remove_nodes([1, 2, 3]): 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..8fb65ec 100644 --- a/src/power_grid_model_ds/_core/model/grids/helpers.py +++ b/src/power_grid_model_ds/_core/model/grids/helpers.py @@ -45,7 +45,7 @@ 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 + feeder_node_ids = grid.node.filter(node_type=NodeType.SUBSTATION_NODE)["id"] components = grid.graphs.active_graph.get_components(feeder_node_ids) for component_node_ids in components: component_branches = _get_active_component_branches(grid, component_node_ids) From a40bedd0a9e643b6c0070581b1efd566b68f0d08 Mon Sep 17 00:00:00 2001 From: Vincent Koppen Date: Sat, 1 Feb 2025 17:58:48 +0100 Subject: [PATCH 3/5] review Thijs Signed-off-by: Vincent Koppen --- src/power_grid_model_ds/_core/model/graphs/models/base.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 e717b4a..8e7e174 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 @@ -6,7 +6,6 @@ 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 @@ -183,7 +182,7 @@ def delete_branch3_array(self, branch_array: Branch3Array, raise_on_fail: bool = self.delete_branch_array(branches, raise_on_fail=raise_on_fail) @contextmanager - def tmp_remove_nodes(self, nodes: list[int] | NDArray[np.int32]) -> Generator: + def tmp_remove_nodes(self, nodes: list[int]) -> Generator: """Context manager that temporarily removes nodes and their branches from the graph. Example: >>> with graph.tmp_remove_nodes([1, 2, 3]): @@ -248,7 +247,7 @@ 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]) -> list[list[int]]: """Returns all separate components when the substation_nodes are removed of the graph as lists""" with self.tmp_remove_nodes(substation_nodes): internal_components = self._get_components() From f7e008539261fff2a7f54c0f8a6bce88d9d2cdad Mon Sep 17 00:00:00 2001 From: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> Date: Mon, 3 Feb 2025 21:15:36 +0100 Subject: [PATCH 4/5] fix graph imports for performance tests Signed-off-by: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> --- tests/performance/_constants.py | 6 +++--- tests/performance/graph_performance_tests.py | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/performance/_constants.py b/tests/performance/_constants.py index f114754..98c2754 100644 --- a/tests/performance/_constants.py +++ b/tests/performance/_constants.py @@ -14,9 +14,9 @@ } GRAPH_SETUP_CODES = { - "rustworkx": "from power_grid_model_ds.model.grids.base import Grid;" - + "from power_grid_model_ds.data_source.generator.grid_generators import RadialGridGenerator;" - + "from power_grid_model_ds.model.graphs.models import RustworkxGraphModel;" + "rustworkx": "from power_grid_model_ds import Grid;" + + "from power_grid_model_ds.generators import RadialGridGenerator;" + + "from power_grid_model_ds.graph_models import RustworkxGraphModel;" + "grid=RadialGridGenerator(nr_nodes={graph_size}, grid_class=Grid, graph_model=RustworkxGraphModel).run()", } diff --git a/tests/performance/graph_performance_tests.py b/tests/performance/graph_performance_tests.py index 8b242df..50b1aae 100644 --- a/tests/performance/graph_performance_tests.py +++ b/tests/performance/graph_performance_tests.py @@ -48,9 +48,9 @@ def perftest_add_node(): if __name__ == "__main__": - perftest_initialize() - perftest_set_feeder_ids() + # perftest_initialize() + # perftest_set_feeder_ids() perftest_get_components() - perftest_delete_node() - perftest_add_node() - perftest_from_arrays() + # perftest_delete_node() + # perftest_add_node() + # perftest_from_arrays() From 0351b12f90751a4c4705a8d5dbaebe4311fbe536 Mon Sep 17 00:00:00 2001 From: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> Date: Mon, 3 Feb 2025 21:22:58 +0100 Subject: [PATCH 5/5] fix constants for graph performance tests Signed-off-by: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> --- tests/performance/graph_performance_tests.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/performance/graph_performance_tests.py b/tests/performance/graph_performance_tests.py index 50b1aae..55279a4 100644 --- a/tests/performance/graph_performance_tests.py +++ b/tests/performance/graph_performance_tests.py @@ -7,7 +7,6 @@ # pylint: disable=missing-function-docstring GRAPH_SIZES = [100, 500, 1000, 5000] -GRAPH_SIZES = [100, 500, 1000] def perftest_initialize(): @@ -48,9 +47,9 @@ def perftest_add_node(): if __name__ == "__main__": - # perftest_initialize() - # perftest_set_feeder_ids() + perftest_initialize() + perftest_set_feeder_ids() perftest_get_components() - # perftest_delete_node() - # perftest_add_node() - # perftest_from_arrays() + perftest_delete_node() + perftest_add_node() + perftest_from_arrays()