From af13c6b264f2836bbf44fa16410d241397ee4cd8 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Tue, 6 Feb 2024 15:16:04 +0100 Subject: [PATCH 01/10] Network actions compatibility Signed-off-by: Thomas Bouquet --- .../NetworkActionsCompatibilityChecker.java | 107 +++++++ .../algorithms/SearchTreeBloomer.java | 16 + ...etworkActionsCompatibilityCheckerTest.java | 278 ++++++++++++++++++ .../algorithms/SearchTreeBloomerTest.java | 89 ++++++ 4 files changed, 490 insertions(+) create mode 100644 ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/NetworkActionsCompatibilityChecker.java create mode 100644 ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/NetworkActionsCompatibilityCheckerTest.java diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/NetworkActionsCompatibilityChecker.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/NetworkActionsCompatibilityChecker.java new file mode 100644 index 0000000000..11d4bf9019 --- /dev/null +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/NetworkActionsCompatibilityChecker.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package com.powsybl.openrao.searchtreerao.searchtree; + +import com.powsybl.openrao.commons.OpenRaoException; +import com.powsybl.openrao.data.cracapi.NetworkElement; +import com.powsybl.openrao.data.cracapi.networkaction.ActionType; +import com.powsybl.openrao.data.cracapi.networkaction.ElementaryAction; +import com.powsybl.openrao.data.cracapi.networkaction.InjectionSetpoint; +import com.powsybl.openrao.data.cracapi.networkaction.NetworkAction; +import com.powsybl.openrao.data.cracapi.networkaction.PstSetpoint; +import com.powsybl.openrao.data.cracapi.networkaction.SwitchPair; +import com.powsybl.openrao.data.cracapi.networkaction.TopologicalAction; + +import java.util.HashSet; +import java.util.Set; + +/** + * @author Thomas Bouquet {@literal } + */ +public final class NetworkActionsCompatibilityChecker { + private NetworkActionsCompatibilityChecker() { } + + public static boolean areNetworkActionsCompatible(NetworkAction networkAction1, NetworkAction networkAction2) { + for (ElementaryAction elementaryAction1 : networkAction1.getElementaryActions()) { + for (ElementaryAction elementaryAction2 : networkAction2.getElementaryActions()) { + if (!areElementaryActionsCompatible(elementaryAction1, elementaryAction2)) { + return false; + } + } + } + return true; + } + + static boolean areElementaryActionsCompatible(ElementaryAction elementaryAction1, ElementaryAction elementaryAction2) { + if (elementaryAction1 instanceof TopologicalAction && elementaryAction2 instanceof SwitchPair) { + return areTopologicalActionAndSwitchPairCompatible((TopologicalAction) elementaryAction1, (SwitchPair) elementaryAction2); + } else if (elementaryAction1 instanceof SwitchPair && elementaryAction2 instanceof TopologicalAction) { + return areTopologicalActionAndSwitchPairCompatible((TopologicalAction) elementaryAction2, (SwitchPair) elementaryAction1); + } else if (elementaryAction1.getClass() != elementaryAction2.getClass()) { + return true; + } else if (elementaryAction1 instanceof TopologicalAction) { + return areTopologicalActionsCompatible((TopologicalAction) elementaryAction1, (TopologicalAction) elementaryAction2); + } else if (elementaryAction1 instanceof PstSetpoint) { + return arePstSetpointsCompatible((PstSetpoint) elementaryAction1, (PstSetpoint) elementaryAction2); + } else if (elementaryAction1 instanceof InjectionSetpoint) { + return areInjectionSetpointsCompatible((InjectionSetpoint) elementaryAction1, (InjectionSetpoint) elementaryAction2); + } else if (elementaryAction1 instanceof SwitchPair) { + return areSwitchPairsCompatible((SwitchPair) elementaryAction1, (SwitchPair) elementaryAction2); + } else { + throw new OpenRaoException("Unsupported network action type: " + elementaryAction1.getClass().getName()); + } + } + + private static boolean areTopologicalActionAndSwitchPairCompatible(TopologicalAction topologicalAction, SwitchPair switchPair) { + return ActionType.OPEN.equals(topologicalAction.getActionType()) && topologicalAction.getNetworkElement().equals(switchPair.getSwitchToOpen()) + || ActionType.CLOSE.equals(topologicalAction.getActionType()) && topologicalAction.getNetworkElement().equals(switchPair.getSwitchToClose()); + } + + private static boolean areTopologicalActionsCompatible(TopologicalAction elementaryAction1, TopologicalAction elementaryAction2) { + NetworkElement switch1 = elementaryAction1.getNetworkElement(); + NetworkElement switch2 = elementaryAction2.getNetworkElement(); + ActionType actionType1 = elementaryAction1.getActionType(); + ActionType actionType2 = elementaryAction2.getActionType(); + return !switch1.equals(switch2) || actionType1.equals(actionType2); + } + + private static boolean arePstSetpointsCompatible(PstSetpoint elementaryAction1, PstSetpoint elementaryAction2) { + NetworkElement pst1 = elementaryAction1.getNetworkElement(); + NetworkElement pst2 = elementaryAction2.getNetworkElement(); + double setpoint1 = elementaryAction1.getSetpoint(); + double setpoint2 = elementaryAction2.getSetpoint(); + return !pst1.equals(pst2) || setpoint1 == setpoint2; + } + + private static boolean areInjectionSetpointsCompatible(InjectionSetpoint elementaryAction1, InjectionSetpoint elementaryAction2) { + NetworkElement networkElement1 = elementaryAction1.getNetworkElement(); + NetworkElement networkElement2 = elementaryAction2.getNetworkElement(); + double setpoint1 = elementaryAction1.getSetpoint(); + double setpoint2 = elementaryAction2.getSetpoint(); + return !networkElement1.equals(networkElement2) || setpoint1 == setpoint2; + } + + private static boolean areSwitchPairsCompatible(SwitchPair elementaryAction1, SwitchPair elementaryAction2) { + NetworkElement switchToOpen1 = elementaryAction1.getSwitchToOpen(); + NetworkElement switchToClose1 = elementaryAction1.getSwitchToClose(); + NetworkElement switchToOpen2 = elementaryAction2.getSwitchToOpen(); + NetworkElement switchToClose2 = elementaryAction2.getSwitchToClose(); + return !switchToOpen1.equals(switchToOpen2) && !switchToOpen1.equals(switchToClose2) && !switchToClose1.equals(switchToClose2) && !switchToClose1.equals(switchToOpen2) + || switchToOpen1.equals(switchToOpen2) && switchToClose1.equals(switchToClose2); + } + + public static Set filterOutIncompatibleRemedialActions(Set appliedNetworkActions, Set availableRemedialActions) { + Set compatibleNetworkActions = new HashSet<>(); + for (NetworkAction availableRemedialAction : availableRemedialActions) { + if (appliedNetworkActions.stream().allMatch(networkAction -> areNetworkActionsCompatible(networkAction, availableRemedialAction))) { + compatibleNetworkActions.add(availableRemedialAction); + } + } + return compatibleNetworkActions; + } +} diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java index 0f2a9ed181..6a9510c72b 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java @@ -14,6 +14,7 @@ import com.powsybl.openrao.searchtreerao.commons.NetworkActionCombination; import com.powsybl.iidm.network.Country; import com.powsybl.iidm.network.Network; +import com.powsybl.openrao.searchtreerao.searchtree.NetworkActionsCompatibilityChecker; import java.util.*; import java.util.stream.Collectors; @@ -101,6 +102,8 @@ Map bloom(Leaf fromLeaf, Set n networkActionCombinations = removeCombinationsWhichExceedMaxNumberOfTsos(networkActionCombinations, fromLeaf); networkActionCombinations = removeCombinationsFarFromMostLimitingElement(networkActionCombinations, fromLeaf); + networkActionCombinations = removeIncompatibleCombinations(networkActionCombinations, fromLeaf); + return networkActionCombinations; } @@ -260,6 +263,19 @@ Map removeCombinationsFarFromMostLimitingElem return filteredNaCombinations; } + /** + * Ignore a combination if any of the network actions if conflictual with the + * already applied network actions on the parent leaf. + * @param naCombinations : the network actions combination + * @param fromLeaf : the parent lead + * @return filtered version of the input map + */ + Map removeIncompatibleCombinations(Map naCombinations, Leaf fromLeaf) { + return naCombinations.keySet().stream() + .filter(naCombination -> NetworkActionsCompatibilityChecker.filterOutIncompatibleRemedialActions(fromLeaf.getActivatedNetworkActions(), naCombination.getNetworkActionSet()).size() == naCombination.getNetworkActionSet().size()) + .collect(Collectors.toMap(naCombination -> naCombination, naCombinations::get)); + } + /** * This function computes the allowed number of network actions for each TSO, as the minimum between the given * parameter and the maximum number of RA reduced by the number of remedial actions already used diff --git a/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/NetworkActionsCompatibilityCheckerTest.java b/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/NetworkActionsCompatibilityCheckerTest.java new file mode 100644 index 0000000000..4e81301216 --- /dev/null +++ b/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/NetworkActionsCompatibilityCheckerTest.java @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package com.powsybl.openrao.searchtreerao.searchtree; + +import com.powsybl.openrao.data.cracapi.NetworkElement; +import com.powsybl.openrao.data.cracapi.networkaction.ActionType; +import com.powsybl.openrao.data.cracapi.networkaction.InjectionSetpoint; +import com.powsybl.openrao.data.cracapi.networkaction.NetworkAction; +import com.powsybl.openrao.data.cracapi.networkaction.PstSetpoint; +import com.powsybl.openrao.data.cracapi.networkaction.SwitchPair; +import com.powsybl.openrao.data.cracapi.networkaction.TopologicalAction; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * @author Thomas Bouquet {@literal } + */ +class NetworkActionsCompatibilityCheckerTest { + + private final NetworkElement switch1 = Mockito.mock(NetworkElement.class); + private final NetworkElement switch2 = Mockito.mock(NetworkElement.class); + private final NetworkElement switch3 = Mockito.mock(NetworkElement.class); + private final NetworkElement switch4 = Mockito.mock(NetworkElement.class); + private final NetworkElement pst1 = Mockito.mock(NetworkElement.class); + private final NetworkElement pst2 = Mockito.mock(NetworkElement.class); + private final NetworkElement generator1 = Mockito.mock(NetworkElement.class); + private final NetworkElement generator2 = Mockito.mock(NetworkElement.class); + + @BeforeEach + void setUp() { + Mockito.when(switch1.getId()).thenReturn("switch-1"); + Mockito.when(switch2.getId()).thenReturn("switch-2"); + Mockito.when(switch3.getId()).thenReturn("switch-3"); + Mockito.when(switch4.getId()).thenReturn("switch-4"); + Mockito.when(pst1.getId()).thenReturn("pst-1"); + Mockito.when(pst2.getId()).thenReturn("pst-2"); + Mockito.when(generator1.getId()).thenReturn("generator-1"); + Mockito.when(generator2.getId()).thenReturn("generator-2"); + } + + @Test + void topologicalActionsCompatibility() { + TopologicalAction topologicalAction1 = Mockito.mock(TopologicalAction.class); + TopologicalAction topologicalAction2 = Mockito.mock(TopologicalAction.class); + // Different switches + Mockito.when(topologicalAction1.getNetworkElement()).thenReturn(switch1); + Mockito.when(topologicalAction1.getActionType()).thenReturn(ActionType.OPEN); + Mockito.when(topologicalAction2.getNetworkElement()).thenReturn(switch2); + Mockito.when(topologicalAction2.getActionType()).thenReturn(ActionType.CLOSE); + assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(topologicalAction1, topologicalAction2)); + // Same switch, different action + Mockito.when(topologicalAction1.getNetworkElement()).thenReturn(switch1); + Mockito.when(topologicalAction1.getActionType()).thenReturn(ActionType.OPEN); + Mockito.when(topologicalAction2.getNetworkElement()).thenReturn(switch1); + Mockito.when(topologicalAction2.getActionType()).thenReturn(ActionType.CLOSE); + assertFalse(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(topologicalAction1, topologicalAction2)); + // Same switch, same action type + Mockito.when(topologicalAction1.getNetworkElement()).thenReturn(switch1); + Mockito.when(topologicalAction1.getActionType()).thenReturn(ActionType.OPEN); + Mockito.when(topologicalAction2.getNetworkElement()).thenReturn(switch1); + Mockito.when(topologicalAction2.getActionType()).thenReturn(ActionType.OPEN); + assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(topologicalAction1, topologicalAction2)); + } + + @Test + void pstSetpointsCompatibility() { + PstSetpoint pstSetpoint1 = Mockito.mock(PstSetpoint.class); + PstSetpoint pstSetpoint2 = Mockito.mock(PstSetpoint.class); + // Different PSTs + Mockito.when(pstSetpoint1.getNetworkElement()).thenReturn(pst1); + Mockito.when(pstSetpoint1.getSetpoint()).thenReturn(1); + Mockito.when(pstSetpoint2.getNetworkElement()).thenReturn(pst2); + Mockito.when(pstSetpoint2.getSetpoint()).thenReturn(2); + assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(pstSetpoint1, pstSetpoint2)); + // Same PST, different setpoints + Mockito.when(pstSetpoint1.getNetworkElement()).thenReturn(pst1); + Mockito.when(pstSetpoint1.getSetpoint()).thenReturn(1); + Mockito.when(pstSetpoint2.getNetworkElement()).thenReturn(pst1); + Mockito.when(pstSetpoint2.getSetpoint()).thenReturn(2); + assertFalse(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(pstSetpoint1, pstSetpoint2)); + // Same PST, same setpoint + Mockito.when(pstSetpoint1.getNetworkElement()).thenReturn(pst1); + Mockito.when(pstSetpoint1.getSetpoint()).thenReturn(1); + Mockito.when(pstSetpoint2.getNetworkElement()).thenReturn(pst1); + Mockito.when(pstSetpoint2.getSetpoint()).thenReturn(1); + assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(pstSetpoint1, pstSetpoint2)); + } + + @Test + void injectionSetpointsCompatibility() { + InjectionSetpoint injectionSetpoint1 = Mockito.mock(InjectionSetpoint.class); + InjectionSetpoint injectionSetpoint2 = Mockito.mock(InjectionSetpoint.class); + // Different generators + Mockito.when(injectionSetpoint1.getNetworkElement()).thenReturn(generator1); + Mockito.when(injectionSetpoint1.getSetpoint()).thenReturn(100d); + Mockito.when(injectionSetpoint2.getNetworkElement()).thenReturn(generator2); + Mockito.when(injectionSetpoint2.getSetpoint()).thenReturn(75d); + assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(injectionSetpoint1, injectionSetpoint2)); + // Same generator, different setpoints + Mockito.when(injectionSetpoint1.getNetworkElement()).thenReturn(generator1); + Mockito.when(injectionSetpoint1.getSetpoint()).thenReturn(100d); + Mockito.when(injectionSetpoint2.getNetworkElement()).thenReturn(generator1); + Mockito.when(injectionSetpoint2.getSetpoint()).thenReturn(75d); + assertFalse(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(injectionSetpoint1, injectionSetpoint2)); + // Same generator, same setpoint + Mockito.when(injectionSetpoint1.getNetworkElement()).thenReturn(generator1); + Mockito.when(injectionSetpoint1.getSetpoint()).thenReturn(100d); + Mockito.when(injectionSetpoint2.getNetworkElement()).thenReturn(generator1); + Mockito.when(injectionSetpoint2.getSetpoint()).thenReturn(100d); + assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(injectionSetpoint1, injectionSetpoint2)); + } + + @Test + void switchPairsCompatibility() { + SwitchPair switchPair1 = Mockito.mock(SwitchPair.class); + SwitchPair switchPair2 = Mockito.mock(SwitchPair.class); + // Completely different switches + Mockito.when(switchPair1.getSwitchToOpen()).thenReturn(switch1); + Mockito.when(switchPair1.getSwitchToClose()).thenReturn(switch2); + Mockito.when(switchPair2.getSwitchToOpen()).thenReturn(switch3); + Mockito.when(switchPair2.getSwitchToClose()).thenReturn(switch4); + assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(switchPair1, switchPair2)); + // Common switches, different roles + Mockito.when(switchPair1.getSwitchToOpen()).thenReturn(switch1); + Mockito.when(switchPair1.getSwitchToClose()).thenReturn(switch2); + Mockito.when(switchPair2.getSwitchToOpen()).thenReturn(switch3); + Mockito.when(switchPair2.getSwitchToClose()).thenReturn(switch1); + assertFalse(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(switchPair1, switchPair2)); + // Same switches, same roles + Mockito.when(switchPair1.getSwitchToOpen()).thenReturn(switch1); + Mockito.when(switchPair1.getSwitchToClose()).thenReturn(switch2); + Mockito.when(switchPair2.getSwitchToOpen()).thenReturn(switch1); + Mockito.when(switchPair2.getSwitchToClose()).thenReturn(switch2); + assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(switchPair1, switchPair2)); + } + + @Test + void topologicalActionAndSwitchCompatibility() { + TopologicalAction topologicalAction = Mockito.mock(TopologicalAction.class); + SwitchPair switchPair = Mockito.mock(SwitchPair.class); + // Compatible closing switches + Mockito.when(topologicalAction.getNetworkElement()).thenReturn(switch2); + Mockito.when(topologicalAction.getActionType()).thenReturn(ActionType.CLOSE); + Mockito.when(switchPair.getSwitchToOpen()).thenReturn(switch1); + Mockito.when(switchPair.getSwitchToClose()).thenReturn(switch2); + assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(topologicalAction, switchPair)); + // Incompatible closing switches + Mockito.when(topologicalAction.getNetworkElement()).thenReturn(switch1); + Mockito.when(topologicalAction.getActionType()).thenReturn(ActionType.CLOSE); + Mockito.when(switchPair.getSwitchToOpen()).thenReturn(switch1); + Mockito.when(switchPair.getSwitchToClose()).thenReturn(switch2); + assertFalse(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(topologicalAction, switchPair)); + // Compatible opening switches + Mockito.when(topologicalAction.getNetworkElement()).thenReturn(switch1); + Mockito.when(topologicalAction.getActionType()).thenReturn(ActionType.OPEN); + Mockito.when(switchPair.getSwitchToOpen()).thenReturn(switch1); + Mockito.when(switchPair.getSwitchToClose()).thenReturn(switch2); + assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(topologicalAction, switchPair)); + // Incompatible opening switches + Mockito.when(topologicalAction.getNetworkElement()).thenReturn(switch1); + Mockito.when(topologicalAction.getActionType()).thenReturn(ActionType.OPEN); + Mockito.when(switchPair.getSwitchToOpen()).thenReturn(switch2); + Mockito.when(switchPair.getSwitchToClose()).thenReturn(switch1); + assertFalse(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(topologicalAction, switchPair)); + } + + @Test + void compatibleNetworkActions() { + NetworkAction networkAction1 = Mockito.mock(NetworkAction.class); + NetworkAction networkAction2 = Mockito.mock(NetworkAction.class); + + TopologicalAction topologicalAction1 = Mockito.mock(TopologicalAction.class); + Mockito.when(topologicalAction1.getNetworkElement()).thenReturn(switch1); + Mockito.when(topologicalAction1.getActionType()).thenReturn(ActionType.OPEN); + + TopologicalAction topologicalAction2 = Mockito.mock(TopologicalAction.class); + Mockito.when(topologicalAction2.getNetworkElement()).thenReturn(switch2); + Mockito.when(topologicalAction2.getActionType()).thenReturn(ActionType.CLOSE); + + TopologicalAction topologicalAction3 = Mockito.mock(TopologicalAction.class); + Mockito.when(topologicalAction3.getNetworkElement()).thenReturn(switch2); + Mockito.when(topologicalAction3.getActionType()).thenReturn(ActionType.OPEN); + + InjectionSetpoint injectionSetpoint1 = Mockito.mock(InjectionSetpoint.class); + Mockito.when(injectionSetpoint1.getNetworkElement()).thenReturn(generator1); + Mockito.when(injectionSetpoint1.getSetpoint()).thenReturn(100d); + + InjectionSetpoint injectionSetpoint2 = Mockito.mock(InjectionSetpoint.class); + Mockito.when(injectionSetpoint2.getNetworkElement()).thenReturn(generator2); + Mockito.when(injectionSetpoint2.getSetpoint()).thenReturn(75d); + + // Completely separated network actions + Mockito.when(networkAction1.getElementaryActions()).thenReturn(Set.of(topologicalAction1, injectionSetpoint1)); + Mockito.when(networkAction2.getElementaryActions()).thenReturn(Set.of(topologicalAction2, injectionSetpoint2)); + assertTrue(NetworkActionsCompatibilityChecker.areNetworkActionsCompatible(networkAction1, networkAction2)); + // One common elementary action + Mockito.when(networkAction1.getElementaryActions()).thenReturn(Set.of(topologicalAction1, topologicalAction2, injectionSetpoint1)); + Mockito.when(networkAction2.getElementaryActions()).thenReturn(Set.of(topologicalAction2, injectionSetpoint2)); + assertTrue(NetworkActionsCompatibilityChecker.areNetworkActionsCompatible(networkAction1, networkAction2)); + // Conflictual elementary actions + Mockito.when(networkAction1.getElementaryActions()).thenReturn(Set.of(injectionSetpoint1, topologicalAction2)); + Mockito.when(networkAction2.getElementaryActions()).thenReturn(Set.of(topologicalAction3, injectionSetpoint2)); + assertFalse(NetworkActionsCompatibilityChecker.areNetworkActionsCompatible(networkAction1, networkAction2)); + } + + @Test + void filterOutIncompatibleRemedialActions() { + TopologicalAction topologicalAction1 = Mockito.mock(TopologicalAction.class); + Mockito.when(topologicalAction1.getNetworkElement()).thenReturn(switch1); + Mockito.when(topologicalAction1.getActionType()).thenReturn(ActionType.OPEN); + + TopologicalAction topologicalAction2 = Mockito.mock(TopologicalAction.class); + Mockito.when(topologicalAction2.getNetworkElement()).thenReturn(switch2); + Mockito.when(topologicalAction2.getActionType()).thenReturn(ActionType.CLOSE); + + TopologicalAction topologicalAction3 = Mockito.mock(TopologicalAction.class); + Mockito.when(topologicalAction3.getNetworkElement()).thenReturn(switch2); + Mockito.when(topologicalAction3.getActionType()).thenReturn(ActionType.OPEN); + + TopologicalAction topologicalAction4 = Mockito.mock(TopologicalAction.class); + Mockito.when(topologicalAction4.getNetworkElement()).thenReturn(switch3); + Mockito.when(topologicalAction4.getActionType()).thenReturn(ActionType.CLOSE); + + InjectionSetpoint injectionSetpoint1 = Mockito.mock(InjectionSetpoint.class); + Mockito.when(injectionSetpoint1.getNetworkElement()).thenReturn(generator1); + Mockito.when(injectionSetpoint1.getSetpoint()).thenReturn(100d); + + InjectionSetpoint injectionSetpoint2 = Mockito.mock(InjectionSetpoint.class); + Mockito.when(injectionSetpoint2.getNetworkElement()).thenReturn(generator2); + Mockito.when(injectionSetpoint2.getSetpoint()).thenReturn(75d); + + PstSetpoint pstSetpoint = Mockito.mock(PstSetpoint.class); + Mockito.when(pstSetpoint.getNetworkElement()).thenReturn(pst1); + Mockito.when(pstSetpoint.getSetpoint()).thenReturn(1); + + SwitchPair switchPair = Mockito.mock(SwitchPair.class); + Mockito.when(switchPair.getSwitchToOpen()).thenReturn(switch2); + Mockito.when(switchPair.getSwitchToClose()).thenReturn(switch1); + + NetworkAction appliedRemedialAction1 = Mockito.mock(NetworkAction.class); + Mockito.when(appliedRemedialAction1.getElementaryActions()).thenReturn(Set.of(topologicalAction1)); + + NetworkAction appliedRemedialAction2 = Mockito.mock(NetworkAction.class); + Mockito.when(appliedRemedialAction2.getElementaryActions()).thenReturn(Set.of(topologicalAction2, injectionSetpoint1)); + + NetworkAction availableRemedialAction1 = Mockito.mock(NetworkAction.class); + Mockito.when(availableRemedialAction1.getElementaryActions()).thenReturn(Set.of(topologicalAction3, pstSetpoint)); + + NetworkAction availableRemedialAction2 = Mockito.mock(NetworkAction.class); + Mockito.when(availableRemedialAction2.getElementaryActions()).thenReturn(Set.of(injectionSetpoint2)); + + NetworkAction availableRemedialAction3 = Mockito.mock(NetworkAction.class); + Mockito.when(availableRemedialAction3.getElementaryActions()).thenReturn(Set.of(injectionSetpoint1, topologicalAction4)); + + NetworkAction availableRemedialAction4 = Mockito.mock(NetworkAction.class); + Mockito.when(availableRemedialAction4.getElementaryActions()).thenReturn(Set.of(switchPair)); + + assertEquals( + Set.of(availableRemedialAction2, availableRemedialAction3), + NetworkActionsCompatibilityChecker.filterOutIncompatibleRemedialActions( + Set.of(appliedRemedialAction1, appliedRemedialAction2), + Set.of(availableRemedialAction1, availableRemedialAction2, availableRemedialAction3, availableRemedialAction4) + ) + ); + } +} diff --git a/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomerTest.java b/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomerTest.java index a74fe428e7..f723a7f4ac 100644 --- a/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomerTest.java +++ b/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomerTest.java @@ -10,10 +10,15 @@ import com.powsybl.openrao.commons.CountryGraph; import com.powsybl.openrao.commons.Unit; import com.powsybl.openrao.data.cracapi.Crac; +import com.powsybl.openrao.data.cracapi.NetworkElement; import com.powsybl.openrao.data.cracapi.State; import com.powsybl.openrao.data.cracapi.cnec.Side; import com.powsybl.openrao.data.cracapi.networkaction.ActionType; +import com.powsybl.openrao.data.cracapi.networkaction.InjectionSetpoint; import com.powsybl.openrao.data.cracapi.networkaction.NetworkAction; +import com.powsybl.openrao.data.cracapi.networkaction.PstSetpoint; +import com.powsybl.openrao.data.cracapi.networkaction.SwitchPair; +import com.powsybl.openrao.data.cracapi.networkaction.TopologicalAction; import com.powsybl.openrao.data.cracapi.rangeaction.PstRangeAction; import com.powsybl.openrao.data.cracapi.rangeaction.RangeAction; import com.powsybl.openrao.data.cracapi.range.RangeType; @@ -569,4 +574,88 @@ void testDontFilterNullOperator() { assertEquals(1, filteredNaCombination.size()); // no combination filtered, because null operator should not count } + + @Test + void removeIncompatibleCombinations() { + NetworkElement switch1 = Mockito.mock(NetworkElement.class); + NetworkElement switch2 = Mockito.mock(NetworkElement.class); + NetworkElement switch3 = Mockito.mock(NetworkElement.class); + NetworkElement pst1 = Mockito.mock(NetworkElement.class); + NetworkElement generator1 = Mockito.mock(NetworkElement.class); + NetworkElement generator2 = Mockito.mock(NetworkElement.class); + + Mockito.when(switch1.getId()).thenReturn("switch-1"); + Mockito.when(switch2.getId()).thenReturn("switch-2"); + Mockito.when(switch3.getId()).thenReturn("switch-3"); + Mockito.when(pst1.getId()).thenReturn("pst-1"); + Mockito.when(generator1.getId()).thenReturn("generator-1"); + Mockito.when(generator2.getId()).thenReturn("generator-2"); + + TopologicalAction topologicalAction1 = Mockito.mock(TopologicalAction.class); + Mockito.when(topologicalAction1.getNetworkElement()).thenReturn(switch1); + Mockito.when(topologicalAction1.getActionType()).thenReturn(ActionType.OPEN); + + TopologicalAction topologicalAction2 = Mockito.mock(TopologicalAction.class); + Mockito.when(topologicalAction2.getNetworkElement()).thenReturn(switch2); + Mockito.when(topologicalAction2.getActionType()).thenReturn(ActionType.CLOSE); + + TopologicalAction topologicalAction3 = Mockito.mock(TopologicalAction.class); + Mockito.when(topologicalAction3.getNetworkElement()).thenReturn(switch2); + Mockito.when(topologicalAction3.getActionType()).thenReturn(ActionType.OPEN); + + TopologicalAction topologicalAction4 = Mockito.mock(TopologicalAction.class); + Mockito.when(topologicalAction4.getNetworkElement()).thenReturn(switch3); + Mockito.when(topologicalAction4.getActionType()).thenReturn(ActionType.CLOSE); + + InjectionSetpoint injectionSetpoint1 = Mockito.mock(InjectionSetpoint.class); + Mockito.when(injectionSetpoint1.getNetworkElement()).thenReturn(generator1); + Mockito.when(injectionSetpoint1.getSetpoint()).thenReturn(100d); + + InjectionSetpoint injectionSetpoint2 = Mockito.mock(InjectionSetpoint.class); + Mockito.when(injectionSetpoint2.getNetworkElement()).thenReturn(generator2); + Mockito.when(injectionSetpoint2.getSetpoint()).thenReturn(75d); + + PstSetpoint pstSetpoint = Mockito.mock(PstSetpoint.class); + Mockito.when(pstSetpoint.getNetworkElement()).thenReturn(pst1); + Mockito.when(pstSetpoint.getSetpoint()).thenReturn(1); + + SwitchPair switchPair = Mockito.mock(SwitchPair.class); + Mockito.when(switchPair.getSwitchToOpen()).thenReturn(switch2); + Mockito.when(switchPair.getSwitchToClose()).thenReturn(switch1); + + NetworkAction appliedRemedialAction1 = Mockito.mock(NetworkAction.class); + Mockito.when(appliedRemedialAction1.getElementaryActions()).thenReturn(Set.of(topologicalAction1)); + + NetworkAction appliedRemedialAction2 = Mockito.mock(NetworkAction.class); + Mockito.when(appliedRemedialAction2.getElementaryActions()).thenReturn(Set.of(topologicalAction2, injectionSetpoint1)); + + NetworkAction availableRemedialAction1 = Mockito.mock(NetworkAction.class); + Mockito.when(availableRemedialAction1.getElementaryActions()).thenReturn(Set.of(topologicalAction3, pstSetpoint)); + + NetworkAction availableRemedialAction2 = Mockito.mock(NetworkAction.class); + Mockito.when(availableRemedialAction2.getElementaryActions()).thenReturn(Set.of(injectionSetpoint2)); + + NetworkAction availableRemedialAction3 = Mockito.mock(NetworkAction.class); + Mockito.when(availableRemedialAction3.getElementaryActions()).thenReturn(Set.of(injectionSetpoint1, topologicalAction4)); + + NetworkAction availableRemedialAction4 = Mockito.mock(NetworkAction.class); + Mockito.when(availableRemedialAction4.getElementaryActions()).thenReturn(Set.of(switchPair)); + + Leaf previousLeaf = Mockito.mock(Leaf.class); + Mockito.when(previousLeaf.getActivatedNetworkActions()).thenReturn(Set.of(appliedRemedialAction1, appliedRemedialAction2)); + + NetworkActionCombination networkActionCombination1 = new NetworkActionCombination(Set.of(availableRemedialAction1, availableRemedialAction2)); + NetworkActionCombination networkActionCombination2 = new NetworkActionCombination(Set.of(availableRemedialAction3)); + NetworkActionCombination networkActionCombination3 = new NetworkActionCombination(Set.of(availableRemedialAction4)); + + Map naCombinations = Map.of( + networkActionCombination1, false, + networkActionCombination2, false, + networkActionCombination3, true + ); + + SearchTreeBloomer bloomer = new SearchTreeBloomer(network, Integer.MAX_VALUE, 2, null, null, false, 0, new ArrayList<>(), pState); + + assertEquals(Map.of(networkActionCombination2, false), bloomer.removeIncompatibleCombinations(naCombinations, previousLeaf)); + } } From b6d536f3c75f1b5b9382c66d2678b53e9594a9b2 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Tue, 5 Mar 2024 16:25:22 +0100 Subject: [PATCH 02/10] Move compatibility checker to RAO utils Signed-off-by: Thomas Bouquet --- .../searchtreerao/searchtree/algorithms/SearchTreeBloomer.java | 2 +- .../openrao/util}/NetworkActionsCompatibilityChecker.java | 2 +- .../openrao/util}/NetworkActionsCompatibilityCheckerTest.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename {ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree => util/src/main/java/com/powsybl/openrao/util}/NetworkActionsCompatibilityChecker.java (99%) rename {ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree => util/src/test/java/com/powsybl/openrao/util}/NetworkActionsCompatibilityCheckerTest.java (99%) diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java index 6a9510c72b..10fb08ff73 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java @@ -14,7 +14,7 @@ import com.powsybl.openrao.searchtreerao.commons.NetworkActionCombination; import com.powsybl.iidm.network.Country; import com.powsybl.iidm.network.Network; -import com.powsybl.openrao.searchtreerao.searchtree.NetworkActionsCompatibilityChecker; +import com.powsybl.openrao.util.NetworkActionsCompatibilityChecker; import java.util.*; import java.util.stream.Collectors; diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/NetworkActionsCompatibilityChecker.java b/util/src/main/java/com/powsybl/openrao/util/NetworkActionsCompatibilityChecker.java similarity index 99% rename from ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/NetworkActionsCompatibilityChecker.java rename to util/src/main/java/com/powsybl/openrao/util/NetworkActionsCompatibilityChecker.java index 11d4bf9019..54f6a4c3b2 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/NetworkActionsCompatibilityChecker.java +++ b/util/src/main/java/com/powsybl/openrao/util/NetworkActionsCompatibilityChecker.java @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.powsybl.openrao.searchtreerao.searchtree; +package com.powsybl.openrao.util; import com.powsybl.openrao.commons.OpenRaoException; import com.powsybl.openrao.data.cracapi.NetworkElement; diff --git a/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/NetworkActionsCompatibilityCheckerTest.java b/util/src/test/java/com/powsybl/openrao/util/NetworkActionsCompatibilityCheckerTest.java similarity index 99% rename from ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/NetworkActionsCompatibilityCheckerTest.java rename to util/src/test/java/com/powsybl/openrao/util/NetworkActionsCompatibilityCheckerTest.java index 4e81301216..26977f5642 100644 --- a/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/NetworkActionsCompatibilityCheckerTest.java +++ b/util/src/test/java/com/powsybl/openrao/util/NetworkActionsCompatibilityCheckerTest.java @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.powsybl.openrao.searchtreerao.searchtree; +package com.powsybl.openrao.util; import com.powsybl.openrao.data.cracapi.NetworkElement; import com.powsybl.openrao.data.cracapi.networkaction.ActionType; From bef7b8f8e65f6ac6e420ae50575c255c7a4b90a0 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Wed, 6 Mar 2024 12:07:17 +0100 Subject: [PATCH 03/10] Refactor by adding methods in respective APIs Signed-off-by: Thomas Bouquet --- .../networkaction/ElementaryAction.java | 7 + .../cracapi/networkaction/NetworkAction.java | 7 + .../data/cracimpl/InjectionSetpointImpl.java | 9 + .../data/cracimpl/NetworkActionImpl.java | 12 + .../data/cracimpl/PstSetpointImpl.java | 9 + .../openrao/data/cracimpl/SwitchPairImpl.java | 10 + .../data/cracimpl/TopologicalActionImpl.java | 9 + .../cracimpl/InjectionSetpointImplTest.java | 30 ++ .../data/cracimpl/NetworkActionImplTest.java | 18 + .../data/cracimpl/PstSetpointImplTest.java | 29 ++ .../data/cracimpl/SwitchPairImplTest.java | 29 ++ .../cracimpl/TopologicalActionImplTest.java | 30 ++ .../cracimpl/utils/CommonCracCreation.java | 334 +++++++++++++++++ .../NetworkActionsCompatibilityChecker.java | 79 +--- ...etworkActionsCompatibilityCheckerTest.java | 343 +++++------------- 15 files changed, 632 insertions(+), 323 deletions(-) diff --git a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/ElementaryAction.java b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/ElementaryAction.java index cabe1ddbdb..dcb7f93ebb 100644 --- a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/ElementaryAction.java +++ b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/ElementaryAction.java @@ -44,4 +44,11 @@ public interface ElementaryAction { * Get the Network Elements associated to the elementary action */ Set getNetworkElements(); + + /** + * States if the elementary action can be applied without infringing on elementary network action's scope. + * @param otherElementaryAction the other elementary action to check compatibility with + * @return true if both elementary actions can be applied without any conflictual behaviour + */ + boolean isCompatibleWith(ElementaryAction otherElementaryAction); } diff --git a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/NetworkAction.java b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/NetworkAction.java index 6d3f22dcff..878951cd46 100644 --- a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/NetworkAction.java +++ b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/NetworkAction.java @@ -44,4 +44,11 @@ public interface NetworkAction extends RemedialAction { * Get the set of the elementary actions constituting then network action */ Set getElementaryActions(); + + /** + * States if the network action can be applied without infringing on another network action's scope. + * @param otherNetworkAction the other network action to check compatibility with + * @return true if both network actions can be applied without any conflictual behaviour + */ + boolean isCompatibleWith(NetworkAction otherNetworkAction); } diff --git a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InjectionSetpointImpl.java b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InjectionSetpointImpl.java index e5a227e50d..967faf398c 100644 --- a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InjectionSetpointImpl.java +++ b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InjectionSetpointImpl.java @@ -8,6 +8,7 @@ package com.powsybl.openrao.data.cracimpl; import com.powsybl.openrao.commons.Unit; +import com.powsybl.openrao.data.cracapi.networkaction.ElementaryAction; import com.powsybl.openrao.data.cracapi.networkaction.InjectionSetpoint; import com.powsybl.openrao.data.cracapi.NetworkElement; import com.powsybl.iidm.network.*; @@ -95,6 +96,14 @@ public Set getNetworkElements() { return Collections.singleton(networkElement); } + @Override + public boolean isCompatibleWith(ElementaryAction otherElementaryAction) { + if (otherElementaryAction instanceof InjectionSetpoint injectionSetpoint) { + return !networkElement.equals(injectionSetpoint.getNetworkElement()) || setpoint == injectionSetpoint.getSetpoint(); + } + return true; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/NetworkActionImpl.java b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/NetworkActionImpl.java index 3915a6e676..4b2db9cd52 100644 --- a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/NetworkActionImpl.java +++ b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/NetworkActionImpl.java @@ -58,6 +58,18 @@ public Set getNetworkElements() { return networkElements; } + @Override + public boolean isCompatibleWith(NetworkAction otherNetworkAction) { + for (ElementaryAction elementaryAction1 : elementaryActions) { + for (ElementaryAction elementaryAction2 : otherNetworkAction.getElementaryActions()) { + if (!elementaryAction1.isCompatibleWith(elementaryAction2)) { + return false; + } + } + } + return true; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/PstSetpointImpl.java b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/PstSetpointImpl.java index c6f544e56c..81989798b8 100644 --- a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/PstSetpointImpl.java +++ b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/PstSetpointImpl.java @@ -9,6 +9,7 @@ import com.powsybl.openrao.commons.OpenRaoException; import com.powsybl.openrao.data.cracapi.NetworkElement; +import com.powsybl.openrao.data.cracapi.networkaction.ElementaryAction; import com.powsybl.openrao.data.cracapi.networkaction.PstSetpoint; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.PhaseTapChanger; @@ -98,6 +99,14 @@ public boolean canBeApplied(Network network) { return true; } + @Override + public boolean isCompatibleWith(ElementaryAction otherElementaryAction) { + if (otherElementaryAction instanceof PstSetpoint pstSetpoint) { + return !networkElement.equals(pstSetpoint.getNetworkElement()) || setpoint == pstSetpoint.getSetpoint(); + } + return true; + } + @Override public int hashCode() { return networkElement.hashCode() + 7 * Double.valueOf(setpoint).hashCode(); diff --git a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/SwitchPairImpl.java b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/SwitchPairImpl.java index 05f36b99b9..5626bf65da 100644 --- a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/SwitchPairImpl.java +++ b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/SwitchPairImpl.java @@ -8,6 +8,7 @@ package com.powsybl.openrao.data.cracimpl; import com.powsybl.openrao.data.cracapi.NetworkElement; +import com.powsybl.openrao.data.cracapi.networkaction.ElementaryAction; import com.powsybl.openrao.data.cracapi.networkaction.SwitchPair; import com.powsybl.iidm.network.Network; @@ -57,6 +58,15 @@ public NetworkElement getSwitchToClose() { return switchToClose; } + @Override + public boolean isCompatibleWith(ElementaryAction otherElementaryAction) { + if (otherElementaryAction instanceof SwitchPair switchPair) { + return !switchToOpen.equals(switchPair.getSwitchToOpen()) && !switchToOpen.equals(switchPair.getSwitchToClose()) && !switchToClose.equals(switchPair.getSwitchToClose()) && !switchToClose.equals(switchPair.getSwitchToOpen()) + || switchToOpen.equals(switchPair.getSwitchToOpen()) || switchToClose.equals(switchPair.getSwitchToClose()); + } + return true; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/TopologicalActionImpl.java b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/TopologicalActionImpl.java index 781ec550a8..da3b1b2bb9 100644 --- a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/TopologicalActionImpl.java +++ b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/TopologicalActionImpl.java @@ -9,6 +9,7 @@ import com.powsybl.openrao.data.cracapi.networkaction.ActionType; import com.powsybl.openrao.data.cracapi.NetworkElement; +import com.powsybl.openrao.data.cracapi.networkaction.ElementaryAction; import com.powsybl.openrao.data.cracapi.networkaction.TopologicalAction; import com.powsybl.iidm.network.Branch; import com.powsybl.iidm.network.Identifiable; @@ -104,6 +105,14 @@ public Set getNetworkElements() { return Collections.singleton(networkElement); } + @Override + public boolean isCompatibleWith(ElementaryAction otherElementaryAction) { + if (otherElementaryAction instanceof TopologicalAction topologicalAction) { + return !networkElement.equals(topologicalAction.getNetworkElement()) || actionType.equals(topologicalAction.getActionType()); + } + return true; + } + @Override public int hashCode() { return networkElement.hashCode() + 37 * actionType.hashCode(); diff --git a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/InjectionSetpointImplTest.java b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/InjectionSetpointImplTest.java index 5c6efcb65d..f36bdfd52d 100644 --- a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/InjectionSetpointImplTest.java +++ b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/InjectionSetpointImplTest.java @@ -10,7 +10,9 @@ package com.powsybl.openrao.data.cracimpl; import com.powsybl.openrao.commons.Unit; +import com.powsybl.openrao.data.cracapi.Crac; import com.powsybl.openrao.data.cracapi.NetworkElement; +import com.powsybl.openrao.data.cracapi.networkaction.InjectionSetpoint; import com.powsybl.openrao.data.cracimpl.utils.NetworkImportsUtil; import com.powsybl.iidm.network.Network; import org.apache.commons.lang3.NotImplementedException; @@ -19,6 +21,7 @@ import java.util.Set; +import static com.powsybl.openrao.data.cracimpl.utils.CommonCracCreation.createCracWithRemedialActions; import static org.junit.jupiter.api.Assertions.*; /** @@ -198,4 +201,31 @@ void equals() { 12., Unit.MEGAWATT); assertNotEquals(injectionSetpoint, differentInjectionSetpoint); } + + @Test + void compatibility() { + Crac crac = createCracWithRemedialActions(); + InjectionSetpoint injectionSetpoint = (InjectionSetpoint) crac.getNetworkAction("generator-1-75-mw").getElementaryActions().iterator().next(); + + assertTrue(injectionSetpoint.isCompatibleWith(injectionSetpoint)); + assertTrue(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("open-switch-2").getElementaryActions().iterator().next())); + assertTrue(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("close-switch-1").getElementaryActions().iterator().next())); + assertTrue(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("close-switch-2").getElementaryActions().iterator().next())); + + assertTrue(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("generator-1-75-mw").getElementaryActions().iterator().next())); + assertFalse(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("generator-1-100-mw").getElementaryActions().iterator().next())); + assertTrue(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("generator-2-75-mw").getElementaryActions().iterator().next())); + assertTrue(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("generator-2-100-mw").getElementaryActions().iterator().next())); + + assertTrue(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("pst-1-tap-3").getElementaryActions().iterator().next())); + assertTrue(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("pst-1-tap-8").getElementaryActions().iterator().next())); + assertTrue(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("pst-2-tap-3").getElementaryActions().iterator().next())); + assertTrue(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("pst-2-tap-8").getElementaryActions().iterator().next())); + + assertTrue(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("open-switch-1-close-switch-2").getElementaryActions().iterator().next())); + assertTrue(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("open-switch-2-close-switch-1").getElementaryActions().iterator().next())); + assertTrue(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("open-switch-3-close-switch-4").getElementaryActions().iterator().next())); + assertTrue(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("open-switch-1-close-switch-3").getElementaryActions().iterator().next())); + assertTrue(injectionSetpoint.isCompatibleWith(crac.getNetworkAction("open-switch-3-close-switch-2").getElementaryActions().iterator().next())); + } } diff --git a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/NetworkActionImplTest.java b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/NetworkActionImplTest.java index ab28524a6c..c7e5584d9e 100644 --- a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/NetworkActionImplTest.java +++ b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/NetworkActionImplTest.java @@ -7,6 +7,7 @@ package com.powsybl.openrao.data.cracimpl; +import com.powsybl.openrao.data.cracapi.Crac; import com.powsybl.openrao.data.cracapi.Identifiable; import com.powsybl.openrao.data.cracapi.networkaction.ElementaryAction; import com.powsybl.openrao.data.cracapi.networkaction.NetworkAction; @@ -19,6 +20,7 @@ import java.util.*; import java.util.stream.Collectors; +import static com.powsybl.openrao.data.cracimpl.utils.CommonCracCreation.createCracWithRemedialActions; import static org.junit.jupiter.api.Assertions.*; /** @@ -121,4 +123,20 @@ void testHasImpactOnNetworkAction() { Mockito.when(mockedElementaryAction1.hasImpactOnNetwork(Mockito.any())).thenReturn(false); assertFalse(networkAction.hasImpactOnNetwork(network)); } + + @Test + void compatibility() { + Crac crac = createCracWithRemedialActions(); + + assertTrue(crac.getNetworkAction("hvdc-fr-es-200-mw").isCompatibleWith(crac.getNetworkAction("hvdc-fr-es-200-mw"))); + assertFalse(crac.getNetworkAction("hvdc-fr-es-200-mw").isCompatibleWith(crac.getNetworkAction("hvdc-es-fr-200-mw"))); + assertTrue(crac.getNetworkAction("hvdc-fr-es-200-mw").isCompatibleWith(crac.getNetworkAction("aligned-psts"))); + assertTrue(crac.getNetworkAction("hvdc-fr-es-200-mw").isCompatibleWith(crac.getNetworkAction("switch-pair-and-pst"))); + assertTrue(crac.getNetworkAction("hvdc-es-fr-200-mw").isCompatibleWith(crac.getNetworkAction("hvdc-es-fr-200-mw"))); + assertTrue(crac.getNetworkAction("hvdc-es-fr-200-mw").isCompatibleWith(crac.getNetworkAction("aligned-psts"))); + assertTrue(crac.getNetworkAction("hvdc-es-fr-200-mw").isCompatibleWith(crac.getNetworkAction("switch-pair-and-pst"))); + assertTrue(crac.getNetworkAction("aligned-psts").isCompatibleWith(crac.getNetworkAction("aligned-psts"))); + assertFalse(crac.getNetworkAction("aligned-psts").isCompatibleWith(crac.getNetworkAction("switch-pair-and-pst"))); + assertTrue(crac.getNetworkAction("switch-pair-and-pst").isCompatibleWith(crac.getNetworkAction("switch-pair-and-pst"))); + } } diff --git a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/PstSetpointImplTest.java b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/PstSetpointImplTest.java index 3a3a7c486b..402cab26b9 100644 --- a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/PstSetpointImplTest.java +++ b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/PstSetpointImplTest.java @@ -8,6 +8,7 @@ package com.powsybl.openrao.data.cracimpl; import com.powsybl.openrao.commons.OpenRaoException; +import com.powsybl.openrao.data.cracapi.Crac; import com.powsybl.openrao.data.cracapi.NetworkElement; import com.powsybl.openrao.data.cracapi.networkaction.PstSetpoint; import com.powsybl.openrao.data.cracimpl.utils.NetworkImportsUtil; @@ -17,6 +18,7 @@ import java.util.Set; +import static com.powsybl.openrao.data.cracimpl.utils.CommonCracCreation.createCracWithRemedialActions; import static org.junit.jupiter.api.Assertions.*; /** @@ -111,4 +113,31 @@ void equals() { -10); assertNotEquals(pstSetpoint, differentPstSetpoint); } + + @Test + void compatibility() { + Crac crac = createCracWithRemedialActions(); + PstSetpoint pstSetpoint = (PstSetpoint) crac.getNetworkAction("pst-1-tap-3").getElementaryActions().iterator().next(); + + assertTrue(pstSetpoint.isCompatibleWith(pstSetpoint)); + assertTrue(pstSetpoint.isCompatibleWith(crac.getNetworkAction("open-switch-2").getElementaryActions().iterator().next())); + assertTrue(pstSetpoint.isCompatibleWith(crac.getNetworkAction("close-switch-1").getElementaryActions().iterator().next())); + assertTrue(pstSetpoint.isCompatibleWith(crac.getNetworkAction("close-switch-2").getElementaryActions().iterator().next())); + + assertTrue(pstSetpoint.isCompatibleWith(crac.getNetworkAction("generator-1-75-mw").getElementaryActions().iterator().next())); + assertTrue(pstSetpoint.isCompatibleWith(crac.getNetworkAction("generator-1-100-mw").getElementaryActions().iterator().next())); + assertTrue(pstSetpoint.isCompatibleWith(crac.getNetworkAction("generator-2-75-mw").getElementaryActions().iterator().next())); + assertTrue(pstSetpoint.isCompatibleWith(crac.getNetworkAction("generator-2-100-mw").getElementaryActions().iterator().next())); + + assertTrue(pstSetpoint.isCompatibleWith(crac.getNetworkAction("pst-1-tap-3").getElementaryActions().iterator().next())); + assertFalse(pstSetpoint.isCompatibleWith(crac.getNetworkAction("pst-1-tap-8").getElementaryActions().iterator().next())); + assertTrue(pstSetpoint.isCompatibleWith(crac.getNetworkAction("pst-2-tap-3").getElementaryActions().iterator().next())); + assertTrue(pstSetpoint.isCompatibleWith(crac.getNetworkAction("pst-2-tap-8").getElementaryActions().iterator().next())); + + assertTrue(pstSetpoint.isCompatibleWith(crac.getNetworkAction("open-switch-1-close-switch-2").getElementaryActions().iterator().next())); + assertTrue(pstSetpoint.isCompatibleWith(crac.getNetworkAction("open-switch-2-close-switch-1").getElementaryActions().iterator().next())); + assertTrue(pstSetpoint.isCompatibleWith(crac.getNetworkAction("open-switch-3-close-switch-4").getElementaryActions().iterator().next())); + assertTrue(pstSetpoint.isCompatibleWith(crac.getNetworkAction("open-switch-1-close-switch-3").getElementaryActions().iterator().next())); + assertTrue(pstSetpoint.isCompatibleWith(crac.getNetworkAction("open-switch-3-close-switch-2").getElementaryActions().iterator().next())); + } } diff --git a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/SwitchPairImplTest.java b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/SwitchPairImplTest.java index 0541acc460..79005cb521 100644 --- a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/SwitchPairImplTest.java +++ b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/SwitchPairImplTest.java @@ -7,6 +7,7 @@ package com.powsybl.openrao.data.cracimpl; +import com.powsybl.openrao.data.cracapi.Crac; import com.powsybl.openrao.data.cracapi.NetworkElement; import com.powsybl.openrao.data.cracapi.networkaction.SwitchPair; import com.powsybl.openrao.data.cracapi.networkaction.TopologicalAction; @@ -17,6 +18,7 @@ import java.util.Set; +import static com.powsybl.openrao.data.cracimpl.utils.CommonCracCreation.createCracWithRemedialActions; import static org.junit.jupiter.api.Assertions.*; /** @@ -111,4 +113,31 @@ void testEquals() { SwitchPairImpl switchPairImpl = new SwitchPairImpl(switch1, switch2); assertEquals(switchPair, switchPairImpl); } + + @Test + void compatibility() { + Crac crac = createCracWithRemedialActions(); + SwitchPair switchPair = (SwitchPair) crac.getNetworkAction("open-switch-1-close-switch-2").getElementaryActions().iterator().next(); + + assertTrue(switchPair.isCompatibleWith(switchPair)); + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-2").getElementaryActions().iterator().next())); + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("close-switch-1").getElementaryActions().iterator().next())); + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("close-switch-2").getElementaryActions().iterator().next())); + + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("generator-1-75-mw").getElementaryActions().iterator().next())); + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("generator-1-100-mw").getElementaryActions().iterator().next())); + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("generator-2-75-mw").getElementaryActions().iterator().next())); + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("generator-2-100-mw").getElementaryActions().iterator().next())); + + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("pst-1-tap-3").getElementaryActions().iterator().next())); + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("pst-1-tap-8").getElementaryActions().iterator().next())); + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("pst-2-tap-3").getElementaryActions().iterator().next())); + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("pst-2-tap-8").getElementaryActions().iterator().next())); + + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-1-close-switch-2").getElementaryActions().iterator().next())); + assertFalse(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-2-close-switch-1").getElementaryActions().iterator().next())); + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-3-close-switch-4").getElementaryActions().iterator().next())); + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-1-close-switch-3").getElementaryActions().iterator().next())); + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-3-close-switch-2").getElementaryActions().iterator().next())); + } } diff --git a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/TopologicalActionImplTest.java b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/TopologicalActionImplTest.java index 42d7441b1f..4bbc822439 100644 --- a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/TopologicalActionImplTest.java +++ b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/TopologicalActionImplTest.java @@ -7,8 +7,10 @@ package com.powsybl.openrao.data.cracimpl; +import com.powsybl.openrao.data.cracapi.Crac; import com.powsybl.openrao.data.cracapi.networkaction.ActionType; import com.powsybl.openrao.data.cracapi.NetworkElement; +import com.powsybl.openrao.data.cracapi.networkaction.TopologicalAction; import com.powsybl.openrao.data.cracimpl.utils.NetworkImportsUtil; import com.powsybl.iidm.network.Network; import org.apache.commons.lang3.NotImplementedException; @@ -16,6 +18,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import static com.powsybl.openrao.data.cracimpl.utils.CommonCracCreation.createCracWithRemedialActions; import static org.junit.jupiter.api.Assertions.*; /** @@ -124,4 +127,31 @@ void equals() { assertEquals(topologyClose, topologyClose); assertNotEquals(topologyClose, topologyOpen); } + + @Test + void compatibility() { + Crac crac = createCracWithRemedialActions(); + TopologicalAction topologicalAction = (TopologicalAction) crac.getNetworkAction("open-switch-1").getElementaryActions().iterator().next(); + + assertTrue(topologicalAction.isCompatibleWith(topologicalAction)); + assertTrue(topologicalAction.isCompatibleWith(crac.getNetworkAction("open-switch-2").getElementaryActions().iterator().next())); + assertFalse(topologicalAction.isCompatibleWith(crac.getNetworkAction("close-switch-1").getElementaryActions().iterator().next())); + assertTrue(topologicalAction.isCompatibleWith(crac.getNetworkAction("close-switch-2").getElementaryActions().iterator().next())); + + assertTrue(topologicalAction.isCompatibleWith(crac.getNetworkAction("generator-1-75-mw").getElementaryActions().iterator().next())); + assertTrue(topologicalAction.isCompatibleWith(crac.getNetworkAction("generator-1-100-mw").getElementaryActions().iterator().next())); + assertTrue(topologicalAction.isCompatibleWith(crac.getNetworkAction("generator-2-75-mw").getElementaryActions().iterator().next())); + assertTrue(topologicalAction.isCompatibleWith(crac.getNetworkAction("generator-2-100-mw").getElementaryActions().iterator().next())); + + assertTrue(topologicalAction.isCompatibleWith(crac.getNetworkAction("pst-1-tap-3").getElementaryActions().iterator().next())); + assertTrue(topologicalAction.isCompatibleWith(crac.getNetworkAction("pst-1-tap-8").getElementaryActions().iterator().next())); + assertTrue(topologicalAction.isCompatibleWith(crac.getNetworkAction("pst-2-tap-3").getElementaryActions().iterator().next())); + assertTrue(topologicalAction.isCompatibleWith(crac.getNetworkAction("pst-2-tap-8").getElementaryActions().iterator().next())); + + assertTrue(topologicalAction.isCompatibleWith(crac.getNetworkAction("open-switch-1-close-switch-2").getElementaryActions().iterator().next())); + assertTrue(topologicalAction.isCompatibleWith(crac.getNetworkAction("open-switch-2-close-switch-1").getElementaryActions().iterator().next())); + assertTrue(topologicalAction.isCompatibleWith(crac.getNetworkAction("open-switch-3-close-switch-4").getElementaryActions().iterator().next())); + assertTrue(topologicalAction.isCompatibleWith(crac.getNetworkAction("open-switch-1-close-switch-3").getElementaryActions().iterator().next())); + assertTrue(topologicalAction.isCompatibleWith(crac.getNetworkAction("open-switch-3-close-switch-2").getElementaryActions().iterator().next())); + } } diff --git a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/utils/CommonCracCreation.java b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/utils/CommonCracCreation.java index 7afbd095af..de0f1ca153 100644 --- a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/utils/CommonCracCreation.java +++ b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/utils/CommonCracCreation.java @@ -11,6 +11,7 @@ import com.powsybl.openrao.data.cracapi.*; import com.powsybl.openrao.data.cracapi.cnec.FlowCnecAdder; import com.powsybl.openrao.data.cracapi.cnec.Side; +import com.powsybl.openrao.data.cracapi.networkaction.ActionType; import com.powsybl.openrao.data.cracapi.range.RangeType; import com.powsybl.openrao.data.cracapi.usagerule.UsageMethod; import com.powsybl.iidm.network.Network; @@ -314,4 +315,337 @@ public static Crac createWithPreventiveAndCurativePstRange() { return crac; } + + public static Crac createCracWithRemedialActions() { + Crac crac = new CracImplFactory().create("cracWithRemedialActions", "cracWithRemedialActions") + .newInstant(PREVENTIVE_INSTANT_ID, InstantKind.PREVENTIVE) + .newInstant(OUTAGE_INSTANT_ID, InstantKind.OUTAGE) + .newInstant(AUTO_INSTANT_ID, InstantKind.AUTO) + .newInstant(CURATIVE_INSTANT_ID, InstantKind.CURATIVE); + + // Simple remedial actions (only one elementary action) + + //// Topological actions + crac.newNetworkAction() + .withId("open-switch-1") + .newTopologicalAction() + .withNetworkElement("switch-1") + .withActionType(ActionType.OPEN) + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("close-switch-1") + .newTopologicalAction() + .withNetworkElement("switch-1") + .withActionType(ActionType.CLOSE) + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("open-switch-2") + .newTopologicalAction() + .withNetworkElement("switch-2") + .withActionType(ActionType.OPEN) + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("close-switch-2") + .newTopologicalAction() + .withNetworkElement("switch-2") + .withActionType(ActionType.CLOSE) + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + //// Injection setpoint actions + crac.newNetworkAction() + .withId("generator-1-75-mw") + .newInjectionSetPoint() + .withNetworkElement("generator-1") + .withSetpoint(75d) + .withUnit(Unit.MEGAWATT) + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("generator-1-100-mw") + .newInjectionSetPoint() + .withNetworkElement("generator-1") + .withSetpoint(100d) + .withUnit(Unit.MEGAWATT) + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("generator-2-75-mw") + .newInjectionSetPoint() + .withNetworkElement("generator-2") + .withSetpoint(75d) + .withUnit(Unit.MEGAWATT) + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("generator-2-100-mw") + .newInjectionSetPoint() + .withNetworkElement("generator-2") + .withSetpoint(100d) + .withUnit(Unit.MEGAWATT) + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + //// PST setpoint actions + crac.newNetworkAction() + .withId("pst-1-tap-3") + .newPstSetPoint() + .withNetworkElement("pst-1") + .withSetpoint(3) + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("pst-1-tap-8") + .newPstSetPoint() + .withNetworkElement("pst-1") + .withSetpoint(8) + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("pst-2-tap-3") + .newPstSetPoint() + .withNetworkElement("pst-2") + .withSetpoint(3) + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("pst-2-tap-8") + .newPstSetPoint() + .withNetworkElement("pst-2") + .withSetpoint(8) + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + //// Switch pairs + crac.newNetworkAction() + .withId("open-switch-1-close-switch-2") + .newSwitchPair() + .withSwitchToOpen("switch-1") + .withSwitchToClose("switch-2") + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("open-switch-2-close-switch-1") + .newSwitchPair() + .withSwitchToOpen("switch-2") + .withSwitchToClose("switch-1") + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("open-switch-3-close-switch-4") + .newSwitchPair() + .withSwitchToOpen("switch-3") + .withSwitchToClose("switch-4") + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("open-switch-1-close-switch-3") + .newSwitchPair() + .withSwitchToOpen("switch-1") + .withSwitchToClose("switch-3") + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("open-switch-3-close-switch-2") + .newSwitchPair() + .withSwitchToOpen("switch-3") + .withSwitchToClose("switch-2") + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + // Complex remedial actions (several elementary actions) + crac.newNetworkAction() + .withId("hvdc-fr-es-200-mw") + .newTopologicalAction() + .withNetworkElement("switch-fr") + .withActionType(ActionType.OPEN) + .add() + .newTopologicalAction() + .withNetworkElement("switch-es") + .withActionType(ActionType.OPEN) + .add() + .newInjectionSetPoint() + .withNetworkElement("generator-fr-1") + .withSetpoint(-100d) + .withUnit(Unit.MEGAWATT) + .add() + .newInjectionSetPoint() + .withNetworkElement("generator-fr-2") + .withSetpoint(-100d) + .withUnit(Unit.MEGAWATT) + .add() + .newInjectionSetPoint() + .withNetworkElement("generator-es-1") + .withSetpoint(100d) + .withUnit(Unit.MEGAWATT) + .add() + .newInjectionSetPoint() + .withNetworkElement("generator-es-2") + .withSetpoint(100d) + .withUnit(Unit.MEGAWATT) + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("hvdc-es-fr-200-mw") + .newTopologicalAction() + .withNetworkElement("switch-fr") + .withActionType(ActionType.OPEN) + .add() + .newTopologicalAction() + .withNetworkElement("switch-es") + .withActionType(ActionType.OPEN) + .add() + .newInjectionSetPoint() + .withNetworkElement("generator-fr-1") + .withSetpoint(100d) + .withUnit(Unit.MEGAWATT) + .add() + .newInjectionSetPoint() + .withNetworkElement("generator-fr-2") + .withSetpoint(100d) + .withUnit(Unit.MEGAWATT) + .add() + .newInjectionSetPoint() + .withNetworkElement("generator-es-1") + .withSetpoint(-100d) + .withUnit(Unit.MEGAWATT) + .add() + .newInjectionSetPoint() + .withNetworkElement("generator-es-2") + .withSetpoint(-100d) + .withUnit(Unit.MEGAWATT) + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("aligned-psts") + .newPstSetPoint() + .withNetworkElement("pst-fr-1") + .withSetpoint(4) + .add() + .newPstSetPoint() + .withNetworkElement("pst-fr-2") + .withSetpoint(4) + .add() + .newPstSetPoint() + .withNetworkElement("pst-fr-3") + .withSetpoint(4) + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + crac.newNetworkAction() + .withId("switch-pair-and-pst") + .newPstSetPoint() + .withNetworkElement("pst-fr-2") + .withSetpoint(-2) + .add() + .newSwitchPair() + .withSwitchToOpen("switch-fr") + .withSwitchToClose("switch-es") + .add() + .newOnInstantUsageRule() + .withInstant(PREVENTIVE_INSTANT_ID) + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + return crac; + } } diff --git a/util/src/main/java/com/powsybl/openrao/util/NetworkActionsCompatibilityChecker.java b/util/src/main/java/com/powsybl/openrao/util/NetworkActionsCompatibilityChecker.java index 54f6a4c3b2..01a32fa624 100644 --- a/util/src/main/java/com/powsybl/openrao/util/NetworkActionsCompatibilityChecker.java +++ b/util/src/main/java/com/powsybl/openrao/util/NetworkActionsCompatibilityChecker.java @@ -7,15 +7,7 @@ package com.powsybl.openrao.util; -import com.powsybl.openrao.commons.OpenRaoException; -import com.powsybl.openrao.data.cracapi.NetworkElement; -import com.powsybl.openrao.data.cracapi.networkaction.ActionType; -import com.powsybl.openrao.data.cracapi.networkaction.ElementaryAction; -import com.powsybl.openrao.data.cracapi.networkaction.InjectionSetpoint; import com.powsybl.openrao.data.cracapi.networkaction.NetworkAction; -import com.powsybl.openrao.data.cracapi.networkaction.PstSetpoint; -import com.powsybl.openrao.data.cracapi.networkaction.SwitchPair; -import com.powsybl.openrao.data.cracapi.networkaction.TopologicalAction; import java.util.HashSet; import java.util.Set; @@ -26,79 +18,10 @@ public final class NetworkActionsCompatibilityChecker { private NetworkActionsCompatibilityChecker() { } - public static boolean areNetworkActionsCompatible(NetworkAction networkAction1, NetworkAction networkAction2) { - for (ElementaryAction elementaryAction1 : networkAction1.getElementaryActions()) { - for (ElementaryAction elementaryAction2 : networkAction2.getElementaryActions()) { - if (!areElementaryActionsCompatible(elementaryAction1, elementaryAction2)) { - return false; - } - } - } - return true; - } - - static boolean areElementaryActionsCompatible(ElementaryAction elementaryAction1, ElementaryAction elementaryAction2) { - if (elementaryAction1 instanceof TopologicalAction && elementaryAction2 instanceof SwitchPair) { - return areTopologicalActionAndSwitchPairCompatible((TopologicalAction) elementaryAction1, (SwitchPair) elementaryAction2); - } else if (elementaryAction1 instanceof SwitchPair && elementaryAction2 instanceof TopologicalAction) { - return areTopologicalActionAndSwitchPairCompatible((TopologicalAction) elementaryAction2, (SwitchPair) elementaryAction1); - } else if (elementaryAction1.getClass() != elementaryAction2.getClass()) { - return true; - } else if (elementaryAction1 instanceof TopologicalAction) { - return areTopologicalActionsCompatible((TopologicalAction) elementaryAction1, (TopologicalAction) elementaryAction2); - } else if (elementaryAction1 instanceof PstSetpoint) { - return arePstSetpointsCompatible((PstSetpoint) elementaryAction1, (PstSetpoint) elementaryAction2); - } else if (elementaryAction1 instanceof InjectionSetpoint) { - return areInjectionSetpointsCompatible((InjectionSetpoint) elementaryAction1, (InjectionSetpoint) elementaryAction2); - } else if (elementaryAction1 instanceof SwitchPair) { - return areSwitchPairsCompatible((SwitchPair) elementaryAction1, (SwitchPair) elementaryAction2); - } else { - throw new OpenRaoException("Unsupported network action type: " + elementaryAction1.getClass().getName()); - } - } - - private static boolean areTopologicalActionAndSwitchPairCompatible(TopologicalAction topologicalAction, SwitchPair switchPair) { - return ActionType.OPEN.equals(topologicalAction.getActionType()) && topologicalAction.getNetworkElement().equals(switchPair.getSwitchToOpen()) - || ActionType.CLOSE.equals(topologicalAction.getActionType()) && topologicalAction.getNetworkElement().equals(switchPair.getSwitchToClose()); - } - - private static boolean areTopologicalActionsCompatible(TopologicalAction elementaryAction1, TopologicalAction elementaryAction2) { - NetworkElement switch1 = elementaryAction1.getNetworkElement(); - NetworkElement switch2 = elementaryAction2.getNetworkElement(); - ActionType actionType1 = elementaryAction1.getActionType(); - ActionType actionType2 = elementaryAction2.getActionType(); - return !switch1.equals(switch2) || actionType1.equals(actionType2); - } - - private static boolean arePstSetpointsCompatible(PstSetpoint elementaryAction1, PstSetpoint elementaryAction2) { - NetworkElement pst1 = elementaryAction1.getNetworkElement(); - NetworkElement pst2 = elementaryAction2.getNetworkElement(); - double setpoint1 = elementaryAction1.getSetpoint(); - double setpoint2 = elementaryAction2.getSetpoint(); - return !pst1.equals(pst2) || setpoint1 == setpoint2; - } - - private static boolean areInjectionSetpointsCompatible(InjectionSetpoint elementaryAction1, InjectionSetpoint elementaryAction2) { - NetworkElement networkElement1 = elementaryAction1.getNetworkElement(); - NetworkElement networkElement2 = elementaryAction2.getNetworkElement(); - double setpoint1 = elementaryAction1.getSetpoint(); - double setpoint2 = elementaryAction2.getSetpoint(); - return !networkElement1.equals(networkElement2) || setpoint1 == setpoint2; - } - - private static boolean areSwitchPairsCompatible(SwitchPair elementaryAction1, SwitchPair elementaryAction2) { - NetworkElement switchToOpen1 = elementaryAction1.getSwitchToOpen(); - NetworkElement switchToClose1 = elementaryAction1.getSwitchToClose(); - NetworkElement switchToOpen2 = elementaryAction2.getSwitchToOpen(); - NetworkElement switchToClose2 = elementaryAction2.getSwitchToClose(); - return !switchToOpen1.equals(switchToOpen2) && !switchToOpen1.equals(switchToClose2) && !switchToClose1.equals(switchToClose2) && !switchToClose1.equals(switchToOpen2) - || switchToOpen1.equals(switchToOpen2) && switchToClose1.equals(switchToClose2); - } - public static Set filterOutIncompatibleRemedialActions(Set appliedNetworkActions, Set availableRemedialActions) { Set compatibleNetworkActions = new HashSet<>(); for (NetworkAction availableRemedialAction : availableRemedialActions) { - if (appliedNetworkActions.stream().allMatch(networkAction -> areNetworkActionsCompatible(networkAction, availableRemedialAction))) { + if (appliedNetworkActions.stream().allMatch(networkAction -> networkAction.isCompatibleWith(availableRemedialAction))) { compatibleNetworkActions.add(availableRemedialAction); } } diff --git a/util/src/test/java/com/powsybl/openrao/util/NetworkActionsCompatibilityCheckerTest.java b/util/src/test/java/com/powsybl/openrao/util/NetworkActionsCompatibilityCheckerTest.java index 26977f5642..03c76b643f 100644 --- a/util/src/test/java/com/powsybl/openrao/util/NetworkActionsCompatibilityCheckerTest.java +++ b/util/src/test/java/com/powsybl/openrao/util/NetworkActionsCompatibilityCheckerTest.java @@ -7,268 +7,121 @@ package com.powsybl.openrao.util; -import com.powsybl.openrao.data.cracapi.NetworkElement; +import com.powsybl.openrao.commons.Unit; +import com.powsybl.openrao.data.cracapi.Crac; +import com.powsybl.openrao.data.cracapi.InstantKind; import com.powsybl.openrao.data.cracapi.networkaction.ActionType; -import com.powsybl.openrao.data.cracapi.networkaction.InjectionSetpoint; import com.powsybl.openrao.data.cracapi.networkaction.NetworkAction; -import com.powsybl.openrao.data.cracapi.networkaction.PstSetpoint; -import com.powsybl.openrao.data.cracapi.networkaction.SwitchPair; -import com.powsybl.openrao.data.cracapi.networkaction.TopologicalAction; -import org.junit.jupiter.api.BeforeEach; +import com.powsybl.openrao.data.cracapi.usagerule.UsageMethod; +import com.powsybl.openrao.data.cracimpl.CracImplFactory; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; import java.util.Set; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author Thomas Bouquet {@literal } */ class NetworkActionsCompatibilityCheckerTest { - private final NetworkElement switch1 = Mockito.mock(NetworkElement.class); - private final NetworkElement switch2 = Mockito.mock(NetworkElement.class); - private final NetworkElement switch3 = Mockito.mock(NetworkElement.class); - private final NetworkElement switch4 = Mockito.mock(NetworkElement.class); - private final NetworkElement pst1 = Mockito.mock(NetworkElement.class); - private final NetworkElement pst2 = Mockito.mock(NetworkElement.class); - private final NetworkElement generator1 = Mockito.mock(NetworkElement.class); - private final NetworkElement generator2 = Mockito.mock(NetworkElement.class); - - @BeforeEach - void setUp() { - Mockito.when(switch1.getId()).thenReturn("switch-1"); - Mockito.when(switch2.getId()).thenReturn("switch-2"); - Mockito.when(switch3.getId()).thenReturn("switch-3"); - Mockito.when(switch4.getId()).thenReturn("switch-4"); - Mockito.when(pst1.getId()).thenReturn("pst-1"); - Mockito.when(pst2.getId()).thenReturn("pst-2"); - Mockito.when(generator1.getId()).thenReturn("generator-1"); - Mockito.when(generator2.getId()).thenReturn("generator-2"); - } - - @Test - void topologicalActionsCompatibility() { - TopologicalAction topologicalAction1 = Mockito.mock(TopologicalAction.class); - TopologicalAction topologicalAction2 = Mockito.mock(TopologicalAction.class); - // Different switches - Mockito.when(topologicalAction1.getNetworkElement()).thenReturn(switch1); - Mockito.when(topologicalAction1.getActionType()).thenReturn(ActionType.OPEN); - Mockito.when(topologicalAction2.getNetworkElement()).thenReturn(switch2); - Mockito.when(topologicalAction2.getActionType()).thenReturn(ActionType.CLOSE); - assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(topologicalAction1, topologicalAction2)); - // Same switch, different action - Mockito.when(topologicalAction1.getNetworkElement()).thenReturn(switch1); - Mockito.when(topologicalAction1.getActionType()).thenReturn(ActionType.OPEN); - Mockito.when(topologicalAction2.getNetworkElement()).thenReturn(switch1); - Mockito.when(topologicalAction2.getActionType()).thenReturn(ActionType.CLOSE); - assertFalse(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(topologicalAction1, topologicalAction2)); - // Same switch, same action type - Mockito.when(topologicalAction1.getNetworkElement()).thenReturn(switch1); - Mockito.when(topologicalAction1.getActionType()).thenReturn(ActionType.OPEN); - Mockito.when(topologicalAction2.getNetworkElement()).thenReturn(switch1); - Mockito.when(topologicalAction2.getActionType()).thenReturn(ActionType.OPEN); - assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(topologicalAction1, topologicalAction2)); - } - - @Test - void pstSetpointsCompatibility() { - PstSetpoint pstSetpoint1 = Mockito.mock(PstSetpoint.class); - PstSetpoint pstSetpoint2 = Mockito.mock(PstSetpoint.class); - // Different PSTs - Mockito.when(pstSetpoint1.getNetworkElement()).thenReturn(pst1); - Mockito.when(pstSetpoint1.getSetpoint()).thenReturn(1); - Mockito.when(pstSetpoint2.getNetworkElement()).thenReturn(pst2); - Mockito.when(pstSetpoint2.getSetpoint()).thenReturn(2); - assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(pstSetpoint1, pstSetpoint2)); - // Same PST, different setpoints - Mockito.when(pstSetpoint1.getNetworkElement()).thenReturn(pst1); - Mockito.when(pstSetpoint1.getSetpoint()).thenReturn(1); - Mockito.when(pstSetpoint2.getNetworkElement()).thenReturn(pst1); - Mockito.when(pstSetpoint2.getSetpoint()).thenReturn(2); - assertFalse(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(pstSetpoint1, pstSetpoint2)); - // Same PST, same setpoint - Mockito.when(pstSetpoint1.getNetworkElement()).thenReturn(pst1); - Mockito.when(pstSetpoint1.getSetpoint()).thenReturn(1); - Mockito.when(pstSetpoint2.getNetworkElement()).thenReturn(pst1); - Mockito.when(pstSetpoint2.getSetpoint()).thenReturn(1); - assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(pstSetpoint1, pstSetpoint2)); - } - - @Test - void injectionSetpointsCompatibility() { - InjectionSetpoint injectionSetpoint1 = Mockito.mock(InjectionSetpoint.class); - InjectionSetpoint injectionSetpoint2 = Mockito.mock(InjectionSetpoint.class); - // Different generators - Mockito.when(injectionSetpoint1.getNetworkElement()).thenReturn(generator1); - Mockito.when(injectionSetpoint1.getSetpoint()).thenReturn(100d); - Mockito.when(injectionSetpoint2.getNetworkElement()).thenReturn(generator2); - Mockito.when(injectionSetpoint2.getSetpoint()).thenReturn(75d); - assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(injectionSetpoint1, injectionSetpoint2)); - // Same generator, different setpoints - Mockito.when(injectionSetpoint1.getNetworkElement()).thenReturn(generator1); - Mockito.when(injectionSetpoint1.getSetpoint()).thenReturn(100d); - Mockito.when(injectionSetpoint2.getNetworkElement()).thenReturn(generator1); - Mockito.when(injectionSetpoint2.getSetpoint()).thenReturn(75d); - assertFalse(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(injectionSetpoint1, injectionSetpoint2)); - // Same generator, same setpoint - Mockito.when(injectionSetpoint1.getNetworkElement()).thenReturn(generator1); - Mockito.when(injectionSetpoint1.getSetpoint()).thenReturn(100d); - Mockito.when(injectionSetpoint2.getNetworkElement()).thenReturn(generator1); - Mockito.when(injectionSetpoint2.getSetpoint()).thenReturn(100d); - assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(injectionSetpoint1, injectionSetpoint2)); - } - - @Test - void switchPairsCompatibility() { - SwitchPair switchPair1 = Mockito.mock(SwitchPair.class); - SwitchPair switchPair2 = Mockito.mock(SwitchPair.class); - // Completely different switches - Mockito.when(switchPair1.getSwitchToOpen()).thenReturn(switch1); - Mockito.when(switchPair1.getSwitchToClose()).thenReturn(switch2); - Mockito.when(switchPair2.getSwitchToOpen()).thenReturn(switch3); - Mockito.when(switchPair2.getSwitchToClose()).thenReturn(switch4); - assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(switchPair1, switchPair2)); - // Common switches, different roles - Mockito.when(switchPair1.getSwitchToOpen()).thenReturn(switch1); - Mockito.when(switchPair1.getSwitchToClose()).thenReturn(switch2); - Mockito.when(switchPair2.getSwitchToOpen()).thenReturn(switch3); - Mockito.when(switchPair2.getSwitchToClose()).thenReturn(switch1); - assertFalse(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(switchPair1, switchPair2)); - // Same switches, same roles - Mockito.when(switchPair1.getSwitchToOpen()).thenReturn(switch1); - Mockito.when(switchPair1.getSwitchToClose()).thenReturn(switch2); - Mockito.when(switchPair2.getSwitchToOpen()).thenReturn(switch1); - Mockito.when(switchPair2.getSwitchToClose()).thenReturn(switch2); - assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(switchPair1, switchPair2)); - } - - @Test - void topologicalActionAndSwitchCompatibility() { - TopologicalAction topologicalAction = Mockito.mock(TopologicalAction.class); - SwitchPair switchPair = Mockito.mock(SwitchPair.class); - // Compatible closing switches - Mockito.when(topologicalAction.getNetworkElement()).thenReturn(switch2); - Mockito.when(topologicalAction.getActionType()).thenReturn(ActionType.CLOSE); - Mockito.when(switchPair.getSwitchToOpen()).thenReturn(switch1); - Mockito.when(switchPair.getSwitchToClose()).thenReturn(switch2); - assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(topologicalAction, switchPair)); - // Incompatible closing switches - Mockito.when(topologicalAction.getNetworkElement()).thenReturn(switch1); - Mockito.when(topologicalAction.getActionType()).thenReturn(ActionType.CLOSE); - Mockito.when(switchPair.getSwitchToOpen()).thenReturn(switch1); - Mockito.when(switchPair.getSwitchToClose()).thenReturn(switch2); - assertFalse(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(topologicalAction, switchPair)); - // Compatible opening switches - Mockito.when(topologicalAction.getNetworkElement()).thenReturn(switch1); - Mockito.when(topologicalAction.getActionType()).thenReturn(ActionType.OPEN); - Mockito.when(switchPair.getSwitchToOpen()).thenReturn(switch1); - Mockito.when(switchPair.getSwitchToClose()).thenReturn(switch2); - assertTrue(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(topologicalAction, switchPair)); - // Incompatible opening switches - Mockito.when(topologicalAction.getNetworkElement()).thenReturn(switch1); - Mockito.when(topologicalAction.getActionType()).thenReturn(ActionType.OPEN); - Mockito.when(switchPair.getSwitchToOpen()).thenReturn(switch2); - Mockito.when(switchPair.getSwitchToClose()).thenReturn(switch1); - assertFalse(NetworkActionsCompatibilityChecker.areElementaryActionsCompatible(topologicalAction, switchPair)); - } - - @Test - void compatibleNetworkActions() { - NetworkAction networkAction1 = Mockito.mock(NetworkAction.class); - NetworkAction networkAction2 = Mockito.mock(NetworkAction.class); - - TopologicalAction topologicalAction1 = Mockito.mock(TopologicalAction.class); - Mockito.when(topologicalAction1.getNetworkElement()).thenReturn(switch1); - Mockito.when(topologicalAction1.getActionType()).thenReturn(ActionType.OPEN); - - TopologicalAction topologicalAction2 = Mockito.mock(TopologicalAction.class); - Mockito.when(topologicalAction2.getNetworkElement()).thenReturn(switch2); - Mockito.when(topologicalAction2.getActionType()).thenReturn(ActionType.CLOSE); - - TopologicalAction topologicalAction3 = Mockito.mock(TopologicalAction.class); - Mockito.when(topologicalAction3.getNetworkElement()).thenReturn(switch2); - Mockito.when(topologicalAction3.getActionType()).thenReturn(ActionType.OPEN); - - InjectionSetpoint injectionSetpoint1 = Mockito.mock(InjectionSetpoint.class); - Mockito.when(injectionSetpoint1.getNetworkElement()).thenReturn(generator1); - Mockito.when(injectionSetpoint1.getSetpoint()).thenReturn(100d); - - InjectionSetpoint injectionSetpoint2 = Mockito.mock(InjectionSetpoint.class); - Mockito.when(injectionSetpoint2.getNetworkElement()).thenReturn(generator2); - Mockito.when(injectionSetpoint2.getSetpoint()).thenReturn(75d); - - // Completely separated network actions - Mockito.when(networkAction1.getElementaryActions()).thenReturn(Set.of(topologicalAction1, injectionSetpoint1)); - Mockito.when(networkAction2.getElementaryActions()).thenReturn(Set.of(topologicalAction2, injectionSetpoint2)); - assertTrue(NetworkActionsCompatibilityChecker.areNetworkActionsCompatible(networkAction1, networkAction2)); - // One common elementary action - Mockito.when(networkAction1.getElementaryActions()).thenReturn(Set.of(topologicalAction1, topologicalAction2, injectionSetpoint1)); - Mockito.when(networkAction2.getElementaryActions()).thenReturn(Set.of(topologicalAction2, injectionSetpoint2)); - assertTrue(NetworkActionsCompatibilityChecker.areNetworkActionsCompatible(networkAction1, networkAction2)); - // Conflictual elementary actions - Mockito.when(networkAction1.getElementaryActions()).thenReturn(Set.of(injectionSetpoint1, topologicalAction2)); - Mockito.when(networkAction2.getElementaryActions()).thenReturn(Set.of(topologicalAction3, injectionSetpoint2)); - assertFalse(NetworkActionsCompatibilityChecker.areNetworkActionsCompatible(networkAction1, networkAction2)); - } - @Test void filterOutIncompatibleRemedialActions() { - TopologicalAction topologicalAction1 = Mockito.mock(TopologicalAction.class); - Mockito.when(topologicalAction1.getNetworkElement()).thenReturn(switch1); - Mockito.when(topologicalAction1.getActionType()).thenReturn(ActionType.OPEN); - - TopologicalAction topologicalAction2 = Mockito.mock(TopologicalAction.class); - Mockito.when(topologicalAction2.getNetworkElement()).thenReturn(switch2); - Mockito.when(topologicalAction2.getActionType()).thenReturn(ActionType.CLOSE); - - TopologicalAction topologicalAction3 = Mockito.mock(TopologicalAction.class); - Mockito.when(topologicalAction3.getNetworkElement()).thenReturn(switch2); - Mockito.when(topologicalAction3.getActionType()).thenReturn(ActionType.OPEN); - - TopologicalAction topologicalAction4 = Mockito.mock(TopologicalAction.class); - Mockito.when(topologicalAction4.getNetworkElement()).thenReturn(switch3); - Mockito.when(topologicalAction4.getActionType()).thenReturn(ActionType.CLOSE); - - InjectionSetpoint injectionSetpoint1 = Mockito.mock(InjectionSetpoint.class); - Mockito.when(injectionSetpoint1.getNetworkElement()).thenReturn(generator1); - Mockito.when(injectionSetpoint1.getSetpoint()).thenReturn(100d); - - InjectionSetpoint injectionSetpoint2 = Mockito.mock(InjectionSetpoint.class); - Mockito.when(injectionSetpoint2.getNetworkElement()).thenReturn(generator2); - Mockito.when(injectionSetpoint2.getSetpoint()).thenReturn(75d); - - PstSetpoint pstSetpoint = Mockito.mock(PstSetpoint.class); - Mockito.when(pstSetpoint.getNetworkElement()).thenReturn(pst1); - Mockito.when(pstSetpoint.getSetpoint()).thenReturn(1); - - SwitchPair switchPair = Mockito.mock(SwitchPair.class); - Mockito.when(switchPair.getSwitchToOpen()).thenReturn(switch2); - Mockito.when(switchPair.getSwitchToClose()).thenReturn(switch1); - - NetworkAction appliedRemedialAction1 = Mockito.mock(NetworkAction.class); - Mockito.when(appliedRemedialAction1.getElementaryActions()).thenReturn(Set.of(topologicalAction1)); - - NetworkAction appliedRemedialAction2 = Mockito.mock(NetworkAction.class); - Mockito.when(appliedRemedialAction2.getElementaryActions()).thenReturn(Set.of(topologicalAction2, injectionSetpoint1)); - - NetworkAction availableRemedialAction1 = Mockito.mock(NetworkAction.class); - Mockito.when(availableRemedialAction1.getElementaryActions()).thenReturn(Set.of(topologicalAction3, pstSetpoint)); - - NetworkAction availableRemedialAction2 = Mockito.mock(NetworkAction.class); - Mockito.when(availableRemedialAction2.getElementaryActions()).thenReturn(Set.of(injectionSetpoint2)); - - NetworkAction availableRemedialAction3 = Mockito.mock(NetworkAction.class); - Mockito.when(availableRemedialAction3.getElementaryActions()).thenReturn(Set.of(injectionSetpoint1, topologicalAction4)); - - NetworkAction availableRemedialAction4 = Mockito.mock(NetworkAction.class); - Mockito.when(availableRemedialAction4.getElementaryActions()).thenReturn(Set.of(switchPair)); + Crac crac = new CracImplFactory().create("crac", "crac") + .newInstant("preventive", InstantKind.PREVENTIVE) + .newInstant("outage", InstantKind.OUTAGE) + .newInstant("auto", InstantKind.AUTO) + .newInstant("curative", InstantKind.CURATIVE); + + NetworkAction appliedRemedialAction1 = crac.newNetworkAction() + .withId("applied-remedial-action-1") + .newTopologicalAction() + .withNetworkElement("switch-1") + .withActionType(ActionType.OPEN) + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + NetworkAction appliedRemedialAction2 = crac.newNetworkAction() + .withId("applied-remedial-action-2") + .newTopologicalAction() + .withNetworkElement("switch-2") + .withActionType(ActionType.CLOSE) + .add() + .newInjectionSetPoint() + .withNetworkElement("generator-1") + .withSetpoint(100d) + .withUnit(Unit.MEGAWATT) + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + NetworkAction availableRemedialAction1 = crac.newNetworkAction() + .withId("available-remedial-action-1") + .newTopologicalAction() + .withNetworkElement("switch-2") + .withActionType(ActionType.OPEN) + .add() + .newPstSetPoint() + .withNetworkElement("pst-1") + .withSetpoint(1) + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + NetworkAction availableRemedialAction2 = crac.newNetworkAction() + .withId("available-remedial-action-2") + .newInjectionSetPoint() + .withNetworkElement("generator-2") + .withSetpoint(75d) + .withUnit(Unit.MEGAWATT) + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + NetworkAction availableRemedialAction3 = crac.newNetworkAction() + .withId("available-remedial-action-3") + .newInjectionSetPoint() + .withNetworkElement("generator-1") + .withSetpoint(100d) + .withUnit(Unit.MEGAWATT) + .add() + .newTopologicalAction() + .withNetworkElement("switch-3") + .withActionType(ActionType.CLOSE) + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + NetworkAction availableRemedialAction4 = crac.newNetworkAction() + .withId("available-remedial-action-4") + .newSwitchPair() + .withSwitchToOpen("switch-2") + .withSwitchToClose("switch-1") + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); assertEquals( - Set.of(availableRemedialAction2, availableRemedialAction3), + Set.of(availableRemedialAction2, availableRemedialAction3, availableRemedialAction4), NetworkActionsCompatibilityChecker.filterOutIncompatibleRemedialActions( Set.of(appliedRemedialAction1, appliedRemedialAction2), Set.of(availableRemedialAction1, availableRemedialAction2, availableRemedialAction3, availableRemedialAction4) From 38e691f1cefd25df93a0a84406de09a7ed54c7ce Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Wed, 6 Mar 2024 12:12:52 +0100 Subject: [PATCH 04/10] Remove RA if equal to an already applied RA Signed-off-by: Thomas Bouquet --- .../util/NetworkActionsCompatibilityChecker.java | 13 +++++-------- .../NetworkActionsCompatibilityCheckerTest.java | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/util/src/main/java/com/powsybl/openrao/util/NetworkActionsCompatibilityChecker.java b/util/src/main/java/com/powsybl/openrao/util/NetworkActionsCompatibilityChecker.java index 01a32fa624..5a9492510a 100644 --- a/util/src/main/java/com/powsybl/openrao/util/NetworkActionsCompatibilityChecker.java +++ b/util/src/main/java/com/powsybl/openrao/util/NetworkActionsCompatibilityChecker.java @@ -9,8 +9,8 @@ import com.powsybl.openrao.data.cracapi.networkaction.NetworkAction; -import java.util.HashSet; import java.util.Set; +import java.util.stream.Collectors; /** * @author Thomas Bouquet {@literal } @@ -19,12 +19,9 @@ public final class NetworkActionsCompatibilityChecker { private NetworkActionsCompatibilityChecker() { } public static Set filterOutIncompatibleRemedialActions(Set appliedNetworkActions, Set availableRemedialActions) { - Set compatibleNetworkActions = new HashSet<>(); - for (NetworkAction availableRemedialAction : availableRemedialActions) { - if (appliedNetworkActions.stream().allMatch(networkAction -> networkAction.isCompatibleWith(availableRemedialAction))) { - compatibleNetworkActions.add(availableRemedialAction); - } - } - return compatibleNetworkActions; + return availableRemedialActions.stream() + .filter(availableRemedialAction -> appliedNetworkActions.stream().allMatch(availableRemedialAction::isCompatibleWith)) + .filter(availableRemedialAction -> appliedNetworkActions.stream().noneMatch(appliedNetworkAction -> availableRemedialAction.getElementaryActions().equals(appliedNetworkAction.getElementaryActions()))) + .collect(Collectors.toSet()); } } diff --git a/util/src/test/java/com/powsybl/openrao/util/NetworkActionsCompatibilityCheckerTest.java b/util/src/test/java/com/powsybl/openrao/util/NetworkActionsCompatibilityCheckerTest.java index 03c76b643f..08c2d13bb4 100644 --- a/util/src/test/java/com/powsybl/openrao/util/NetworkActionsCompatibilityCheckerTest.java +++ b/util/src/test/java/com/powsybl/openrao/util/NetworkActionsCompatibilityCheckerTest.java @@ -124,7 +124,7 @@ void filterOutIncompatibleRemedialActions() { Set.of(availableRemedialAction2, availableRemedialAction3, availableRemedialAction4), NetworkActionsCompatibilityChecker.filterOutIncompatibleRemedialActions( Set.of(appliedRemedialAction1, appliedRemedialAction2), - Set.of(availableRemedialAction1, availableRemedialAction2, availableRemedialAction3, availableRemedialAction4) + Set.of(appliedRemedialAction1, appliedRemedialAction2, availableRemedialAction1, availableRemedialAction2, availableRemedialAction3, availableRemedialAction4) ) ); } From ca8e675b5570320c269ee24c02d31169eeaca687 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Wed, 6 Mar 2024 15:10:40 +0100 Subject: [PATCH 05/10] Remove checker and add method in bloomer directly Signed-off-by: Thomas Bouquet --- .../algorithms/SearchTreeBloomer.java | 7 +- .../algorithms/SearchTreeBloomerTest.java | 179 +++++++++++------- .../NetworkActionsCompatibilityChecker.java | 27 --- ...etworkActionsCompatibilityCheckerTest.java | 131 ------------- 4 files changed, 116 insertions(+), 228 deletions(-) delete mode 100644 util/src/main/java/com/powsybl/openrao/util/NetworkActionsCompatibilityChecker.java delete mode 100644 util/src/test/java/com/powsybl/openrao/util/NetworkActionsCompatibilityCheckerTest.java diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java index 10fb08ff73..5f3f2c21bb 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java @@ -14,7 +14,6 @@ import com.powsybl.openrao.searchtreerao.commons.NetworkActionCombination; import com.powsybl.iidm.network.Country; import com.powsybl.iidm.network.Network; -import com.powsybl.openrao.util.NetworkActionsCompatibilityChecker; import java.util.*; import java.util.stream.Collectors; @@ -272,8 +271,12 @@ Map removeCombinationsFarFromMostLimitingElem */ Map removeIncompatibleCombinations(Map naCombinations, Leaf fromLeaf) { return naCombinations.keySet().stream() - .filter(naCombination -> NetworkActionsCompatibilityChecker.filterOutIncompatibleRemedialActions(fromLeaf.getActivatedNetworkActions(), naCombination.getNetworkActionSet()).size() == naCombination.getNetworkActionSet().size()) + .filter(naCombination -> naCombination.getNetworkActionSet().stream().allMatch(networkAction -> fromLeaf.getActivatedNetworkActions().stream().allMatch(networkAction::isCompatibleWith))) + .filter(naCombination -> naCombination.getNetworkActionSet().stream().anyMatch(networkAction -> fromLeaf.getActivatedNetworkActions().stream().noneMatch(appliedNetworkAction -> networkAction.getElementaryActions().equals(appliedNetworkAction.getElementaryActions())))) .collect(Collectors.toMap(naCombination -> naCombination, naCombinations::get)); + // return naCombinations.keySet().stream() + // .filter(naCombination -> NetworkActionsCompatibilityChecker.filterOutIncompatibleRemedialActions(fromLeaf.getActivatedNetworkActions(), naCombination.getNetworkActionSet()).size() == naCombination.getNetworkActionSet().size()) + // .collect(Collectors.toMap(naCombination -> naCombination, naCombinations::get)); } /** diff --git a/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomerTest.java b/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomerTest.java index f723a7f4ac..baa577e4a8 100644 --- a/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomerTest.java +++ b/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomerTest.java @@ -10,19 +10,16 @@ import com.powsybl.openrao.commons.CountryGraph; import com.powsybl.openrao.commons.Unit; import com.powsybl.openrao.data.cracapi.Crac; -import com.powsybl.openrao.data.cracapi.NetworkElement; +import com.powsybl.openrao.data.cracapi.InstantKind; import com.powsybl.openrao.data.cracapi.State; import com.powsybl.openrao.data.cracapi.cnec.Side; import com.powsybl.openrao.data.cracapi.networkaction.ActionType; -import com.powsybl.openrao.data.cracapi.networkaction.InjectionSetpoint; import com.powsybl.openrao.data.cracapi.networkaction.NetworkAction; -import com.powsybl.openrao.data.cracapi.networkaction.PstSetpoint; -import com.powsybl.openrao.data.cracapi.networkaction.SwitchPair; -import com.powsybl.openrao.data.cracapi.networkaction.TopologicalAction; import com.powsybl.openrao.data.cracapi.rangeaction.PstRangeAction; import com.powsybl.openrao.data.cracapi.rangeaction.RangeAction; import com.powsybl.openrao.data.cracapi.range.RangeType; import com.powsybl.openrao.data.cracapi.usagerule.UsageMethod; +import com.powsybl.openrao.data.cracimpl.CracImplFactory; import com.powsybl.openrao.data.cracimpl.utils.CommonCracCreation; import com.powsybl.openrao.data.cracimpl.utils.NetworkImportsUtil; import com.powsybl.openrao.searchtreerao.commons.NetworkActionCombination; @@ -577,85 +574,131 @@ void testDontFilterNullOperator() { @Test void removeIncompatibleCombinations() { - NetworkElement switch1 = Mockito.mock(NetworkElement.class); - NetworkElement switch2 = Mockito.mock(NetworkElement.class); - NetworkElement switch3 = Mockito.mock(NetworkElement.class); - NetworkElement pst1 = Mockito.mock(NetworkElement.class); - NetworkElement generator1 = Mockito.mock(NetworkElement.class); - NetworkElement generator2 = Mockito.mock(NetworkElement.class); - - Mockito.when(switch1.getId()).thenReturn("switch-1"); - Mockito.when(switch2.getId()).thenReturn("switch-2"); - Mockito.when(switch3.getId()).thenReturn("switch-3"); - Mockito.when(pst1.getId()).thenReturn("pst-1"); - Mockito.when(generator1.getId()).thenReturn("generator-1"); - Mockito.when(generator2.getId()).thenReturn("generator-2"); - - TopologicalAction topologicalAction1 = Mockito.mock(TopologicalAction.class); - Mockito.when(topologicalAction1.getNetworkElement()).thenReturn(switch1); - Mockito.when(topologicalAction1.getActionType()).thenReturn(ActionType.OPEN); - - TopologicalAction topologicalAction2 = Mockito.mock(TopologicalAction.class); - Mockito.when(topologicalAction2.getNetworkElement()).thenReturn(switch2); - Mockito.when(topologicalAction2.getActionType()).thenReturn(ActionType.CLOSE); - - TopologicalAction topologicalAction3 = Mockito.mock(TopologicalAction.class); - Mockito.when(topologicalAction3.getNetworkElement()).thenReturn(switch2); - Mockito.when(topologicalAction3.getActionType()).thenReturn(ActionType.OPEN); - - TopologicalAction topologicalAction4 = Mockito.mock(TopologicalAction.class); - Mockito.when(topologicalAction4.getNetworkElement()).thenReturn(switch3); - Mockito.when(topologicalAction4.getActionType()).thenReturn(ActionType.CLOSE); - - InjectionSetpoint injectionSetpoint1 = Mockito.mock(InjectionSetpoint.class); - Mockito.when(injectionSetpoint1.getNetworkElement()).thenReturn(generator1); - Mockito.when(injectionSetpoint1.getSetpoint()).thenReturn(100d); - - InjectionSetpoint injectionSetpoint2 = Mockito.mock(InjectionSetpoint.class); - Mockito.when(injectionSetpoint2.getNetworkElement()).thenReturn(generator2); - Mockito.when(injectionSetpoint2.getSetpoint()).thenReturn(75d); - - PstSetpoint pstSetpoint = Mockito.mock(PstSetpoint.class); - Mockito.when(pstSetpoint.getNetworkElement()).thenReturn(pst1); - Mockito.when(pstSetpoint.getSetpoint()).thenReturn(1); - - SwitchPair switchPair = Mockito.mock(SwitchPair.class); - Mockito.when(switchPair.getSwitchToOpen()).thenReturn(switch2); - Mockito.when(switchPair.getSwitchToClose()).thenReturn(switch1); - - NetworkAction appliedRemedialAction1 = Mockito.mock(NetworkAction.class); - Mockito.when(appliedRemedialAction1.getElementaryActions()).thenReturn(Set.of(topologicalAction1)); - - NetworkAction appliedRemedialAction2 = Mockito.mock(NetworkAction.class); - Mockito.when(appliedRemedialAction2.getElementaryActions()).thenReturn(Set.of(topologicalAction2, injectionSetpoint1)); + Crac crac = new CracImplFactory().create("crac", "crac") + .newInstant("preventive", InstantKind.PREVENTIVE) + .newInstant("outage", InstantKind.OUTAGE) + .newInstant("auto", InstantKind.AUTO) + .newInstant("curative", InstantKind.CURATIVE); + + NetworkAction appliedRemedialAction1 = crac.newNetworkAction() + .withId("applied-remedial-action-1") + .withOperator("FR") + .newTopologicalAction() + .withNetworkElement("switch-1") + .withActionType(ActionType.OPEN) + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); - NetworkAction availableRemedialAction1 = Mockito.mock(NetworkAction.class); - Mockito.when(availableRemedialAction1.getElementaryActions()).thenReturn(Set.of(topologicalAction3, pstSetpoint)); + NetworkAction appliedRemedialAction2 = crac.newNetworkAction() + .withId("applied-remedial-action-2") + .withOperator("FR") + .newTopologicalAction() + .withNetworkElement("switch-2") + .withActionType(ActionType.CLOSE) + .add() + .newInjectionSetPoint() + .withNetworkElement("generator-1") + .withSetpoint(100d) + .withUnit(Unit.MEGAWATT) + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); - NetworkAction availableRemedialAction2 = Mockito.mock(NetworkAction.class); - Mockito.when(availableRemedialAction2.getElementaryActions()).thenReturn(Set.of(injectionSetpoint2)); + NetworkAction availableRemedialAction1 = crac.newNetworkAction() + .withId("available-remedial-action-1") + .withOperator("FR") + .newTopologicalAction() + .withNetworkElement("switch-2") + .withActionType(ActionType.OPEN) + .add() + .newPstSetPoint() + .withNetworkElement("pst-1") + .withSetpoint(1) + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); - NetworkAction availableRemedialAction3 = Mockito.mock(NetworkAction.class); - Mockito.when(availableRemedialAction3.getElementaryActions()).thenReturn(Set.of(injectionSetpoint1, topologicalAction4)); + NetworkAction availableRemedialAction2 = crac.newNetworkAction() + .withId("available-remedial-action-2") + .withOperator("FR") + .newInjectionSetPoint() + .withNetworkElement("generator-2") + .withSetpoint(75d) + .withUnit(Unit.MEGAWATT) + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); - NetworkAction availableRemedialAction4 = Mockito.mock(NetworkAction.class); - Mockito.when(availableRemedialAction4.getElementaryActions()).thenReturn(Set.of(switchPair)); + NetworkAction availableRemedialAction3 = crac.newNetworkAction() + .withId("available-remedial-action-3") + .withOperator("FR") + .newInjectionSetPoint() + .withNetworkElement("generator-1") + .withSetpoint(100d) + .withUnit(Unit.MEGAWATT) + .add() + .newTopologicalAction() + .withNetworkElement("switch-3") + .withActionType(ActionType.CLOSE) + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); - Leaf previousLeaf = Mockito.mock(Leaf.class); - Mockito.when(previousLeaf.getActivatedNetworkActions()).thenReturn(Set.of(appliedRemedialAction1, appliedRemedialAction2)); + NetworkAction availableRemedialAction4 = crac.newNetworkAction() + .withId("available-remedial-action-4") + .withOperator("FR") + .newSwitchPair() + .withSwitchToOpen("switch-2") + .withSwitchToClose("switch-1") + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); NetworkActionCombination networkActionCombination1 = new NetworkActionCombination(Set.of(availableRemedialAction1, availableRemedialAction2)); NetworkActionCombination networkActionCombination2 = new NetworkActionCombination(Set.of(availableRemedialAction3)); NetworkActionCombination networkActionCombination3 = new NetworkActionCombination(Set.of(availableRemedialAction4)); + NetworkActionCombination networkActionCombination4 = new NetworkActionCombination(Set.of(appliedRemedialAction1, availableRemedialAction4)); + NetworkActionCombination networkActionCombination5 = new NetworkActionCombination(Set.of(appliedRemedialAction1, appliedRemedialAction2)); + NetworkActionCombination networkActionCombination6 = new NetworkActionCombination(Set.of(availableRemedialAction3, appliedRemedialAction2)); + NetworkActionCombination networkActionCombination7 = new NetworkActionCombination(Set.of(availableRemedialAction2, availableRemedialAction3)); Map naCombinations = Map.of( networkActionCombination1, false, networkActionCombination2, false, - networkActionCombination3, true + networkActionCombination3, true, + networkActionCombination4, false, + networkActionCombination5, false, + networkActionCombination6, true, + networkActionCombination7, true ); + Leaf previousLeaf = Mockito.mock(Leaf.class); + Mockito.when(previousLeaf.getActivatedNetworkActions()).thenReturn(Set.of(appliedRemedialAction1, appliedRemedialAction2)); + SearchTreeBloomer bloomer = new SearchTreeBloomer(network, Integer.MAX_VALUE, 2, null, null, false, 0, new ArrayList<>(), pState); - assertEquals(Map.of(networkActionCombination2, false), bloomer.removeIncompatibleCombinations(naCombinations, previousLeaf)); + assertEquals( + Map.of(networkActionCombination2, false, networkActionCombination3, true, networkActionCombination4, false, networkActionCombination6, true, networkActionCombination7, true), + bloomer.removeIncompatibleCombinations(naCombinations, previousLeaf) + ); } } diff --git a/util/src/main/java/com/powsybl/openrao/util/NetworkActionsCompatibilityChecker.java b/util/src/main/java/com/powsybl/openrao/util/NetworkActionsCompatibilityChecker.java deleted file mode 100644 index 5a9492510a..0000000000 --- a/util/src/main/java/com/powsybl/openrao/util/NetworkActionsCompatibilityChecker.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2024, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -package com.powsybl.openrao.util; - -import com.powsybl.openrao.data.cracapi.networkaction.NetworkAction; - -import java.util.Set; -import java.util.stream.Collectors; - -/** - * @author Thomas Bouquet {@literal } - */ -public final class NetworkActionsCompatibilityChecker { - private NetworkActionsCompatibilityChecker() { } - - public static Set filterOutIncompatibleRemedialActions(Set appliedNetworkActions, Set availableRemedialActions) { - return availableRemedialActions.stream() - .filter(availableRemedialAction -> appliedNetworkActions.stream().allMatch(availableRemedialAction::isCompatibleWith)) - .filter(availableRemedialAction -> appliedNetworkActions.stream().noneMatch(appliedNetworkAction -> availableRemedialAction.getElementaryActions().equals(appliedNetworkAction.getElementaryActions()))) - .collect(Collectors.toSet()); - } -} diff --git a/util/src/test/java/com/powsybl/openrao/util/NetworkActionsCompatibilityCheckerTest.java b/util/src/test/java/com/powsybl/openrao/util/NetworkActionsCompatibilityCheckerTest.java deleted file mode 100644 index 08c2d13bb4..0000000000 --- a/util/src/test/java/com/powsybl/openrao/util/NetworkActionsCompatibilityCheckerTest.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2024, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -package com.powsybl.openrao.util; - -import com.powsybl.openrao.commons.Unit; -import com.powsybl.openrao.data.cracapi.Crac; -import com.powsybl.openrao.data.cracapi.InstantKind; -import com.powsybl.openrao.data.cracapi.networkaction.ActionType; -import com.powsybl.openrao.data.cracapi.networkaction.NetworkAction; -import com.powsybl.openrao.data.cracapi.usagerule.UsageMethod; -import com.powsybl.openrao.data.cracimpl.CracImplFactory; -import org.junit.jupiter.api.Test; - -import java.util.Set; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * @author Thomas Bouquet {@literal } - */ -class NetworkActionsCompatibilityCheckerTest { - - @Test - void filterOutIncompatibleRemedialActions() { - Crac crac = new CracImplFactory().create("crac", "crac") - .newInstant("preventive", InstantKind.PREVENTIVE) - .newInstant("outage", InstantKind.OUTAGE) - .newInstant("auto", InstantKind.AUTO) - .newInstant("curative", InstantKind.CURATIVE); - - NetworkAction appliedRemedialAction1 = crac.newNetworkAction() - .withId("applied-remedial-action-1") - .newTopologicalAction() - .withNetworkElement("switch-1") - .withActionType(ActionType.OPEN) - .add() - .newOnInstantUsageRule() - .withInstant("preventive") - .withUsageMethod(UsageMethod.AVAILABLE) - .add() - .add(); - - NetworkAction appliedRemedialAction2 = crac.newNetworkAction() - .withId("applied-remedial-action-2") - .newTopologicalAction() - .withNetworkElement("switch-2") - .withActionType(ActionType.CLOSE) - .add() - .newInjectionSetPoint() - .withNetworkElement("generator-1") - .withSetpoint(100d) - .withUnit(Unit.MEGAWATT) - .add() - .newOnInstantUsageRule() - .withInstant("preventive") - .withUsageMethod(UsageMethod.AVAILABLE) - .add() - .add(); - - NetworkAction availableRemedialAction1 = crac.newNetworkAction() - .withId("available-remedial-action-1") - .newTopologicalAction() - .withNetworkElement("switch-2") - .withActionType(ActionType.OPEN) - .add() - .newPstSetPoint() - .withNetworkElement("pst-1") - .withSetpoint(1) - .add() - .newOnInstantUsageRule() - .withInstant("preventive") - .withUsageMethod(UsageMethod.AVAILABLE) - .add() - .add(); - - NetworkAction availableRemedialAction2 = crac.newNetworkAction() - .withId("available-remedial-action-2") - .newInjectionSetPoint() - .withNetworkElement("generator-2") - .withSetpoint(75d) - .withUnit(Unit.MEGAWATT) - .add() - .newOnInstantUsageRule() - .withInstant("preventive") - .withUsageMethod(UsageMethod.AVAILABLE) - .add() - .add(); - - NetworkAction availableRemedialAction3 = crac.newNetworkAction() - .withId("available-remedial-action-3") - .newInjectionSetPoint() - .withNetworkElement("generator-1") - .withSetpoint(100d) - .withUnit(Unit.MEGAWATT) - .add() - .newTopologicalAction() - .withNetworkElement("switch-3") - .withActionType(ActionType.CLOSE) - .add() - .newOnInstantUsageRule() - .withInstant("preventive") - .withUsageMethod(UsageMethod.AVAILABLE) - .add() - .add(); - - NetworkAction availableRemedialAction4 = crac.newNetworkAction() - .withId("available-remedial-action-4") - .newSwitchPair() - .withSwitchToOpen("switch-2") - .withSwitchToClose("switch-1") - .add() - .newOnInstantUsageRule() - .withInstant("preventive") - .withUsageMethod(UsageMethod.AVAILABLE) - .add() - .add(); - - assertEquals( - Set.of(availableRemedialAction2, availableRemedialAction3, availableRemedialAction4), - NetworkActionsCompatibilityChecker.filterOutIncompatibleRemedialActions( - Set.of(appliedRemedialAction1, appliedRemedialAction2), - Set.of(appliedRemedialAction1, appliedRemedialAction2, availableRemedialAction1, availableRemedialAction2, availableRemedialAction3, availableRemedialAction4) - ) - ); - } -} From 67ca1d7daf7aaad1a3ee7d1099356fd8698f43e5 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Wed, 6 Mar 2024 15:12:59 +0100 Subject: [PATCH 06/10] Declare function in interface Signed-off-by: Thomas Bouquet Signed-off-by: Thomas Bouquet --- .../data/cracapi/networkaction/NetworkAction.java | 11 ++++++++++- .../openrao/data/cracimpl/NetworkActionImpl.java | 12 ------------ 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/NetworkAction.java b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/NetworkAction.java index 878951cd46..32ba162ebb 100644 --- a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/NetworkAction.java +++ b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/NetworkAction.java @@ -50,5 +50,14 @@ public interface NetworkAction extends RemedialAction { * @param otherNetworkAction the other network action to check compatibility with * @return true if both network actions can be applied without any conflictual behaviour */ - boolean isCompatibleWith(NetworkAction otherNetworkAction); + default boolean isCompatibleWith(NetworkAction otherNetworkAction) { + for (ElementaryAction elementaryAction1 : getElementaryActions()) { + for (ElementaryAction elementaryAction2 : otherNetworkAction.getElementaryActions()) { + if (!elementaryAction1.isCompatibleWith(elementaryAction2)) { + return false; + } + } + } + return true; + } } diff --git a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/NetworkActionImpl.java b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/NetworkActionImpl.java index 4b2db9cd52..3915a6e676 100644 --- a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/NetworkActionImpl.java +++ b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/NetworkActionImpl.java @@ -58,18 +58,6 @@ public Set getNetworkElements() { return networkElements; } - @Override - public boolean isCompatibleWith(NetworkAction otherNetworkAction) { - for (ElementaryAction elementaryAction1 : elementaryActions) { - for (ElementaryAction elementaryAction2 : otherNetworkAction.getElementaryActions()) { - if (!elementaryAction1.isCompatibleWith(elementaryAction2)) { - return false; - } - } - } - return true; - } - @Override public boolean equals(Object o) { if (this == o) { From bc23dd9d336682b2a1cd8bc4a7816742830eb23e Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Wed, 6 Mar 2024 17:09:23 +0100 Subject: [PATCH 07/10] Simplify filter in bloomer Signed-off-by: Thomas Bouquet --- .../searchtree/algorithms/SearchTreeBloomer.java | 4 ---- .../searchtree/algorithms/SearchTreeBloomerTest.java | 12 +++--------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java index 5f3f2c21bb..0598b71b20 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java @@ -272,11 +272,7 @@ Map removeCombinationsFarFromMostLimitingElem Map removeIncompatibleCombinations(Map naCombinations, Leaf fromLeaf) { return naCombinations.keySet().stream() .filter(naCombination -> naCombination.getNetworkActionSet().stream().allMatch(networkAction -> fromLeaf.getActivatedNetworkActions().stream().allMatch(networkAction::isCompatibleWith))) - .filter(naCombination -> naCombination.getNetworkActionSet().stream().anyMatch(networkAction -> fromLeaf.getActivatedNetworkActions().stream().noneMatch(appliedNetworkAction -> networkAction.getElementaryActions().equals(appliedNetworkAction.getElementaryActions())))) .collect(Collectors.toMap(naCombination -> naCombination, naCombinations::get)); - // return naCombinations.keySet().stream() - // .filter(naCombination -> NetworkActionsCompatibilityChecker.filterOutIncompatibleRemedialActions(fromLeaf.getActivatedNetworkActions(), naCombination.getNetworkActionSet()).size() == naCombination.getNetworkActionSet().size()) - // .collect(Collectors.toMap(naCombination -> naCombination, naCombinations::get)); } /** diff --git a/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomerTest.java b/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomerTest.java index baa577e4a8..e49f7fa9e7 100644 --- a/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomerTest.java +++ b/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomerTest.java @@ -676,19 +676,13 @@ void removeIncompatibleCombinations() { NetworkActionCombination networkActionCombination1 = new NetworkActionCombination(Set.of(availableRemedialAction1, availableRemedialAction2)); NetworkActionCombination networkActionCombination2 = new NetworkActionCombination(Set.of(availableRemedialAction3)); NetworkActionCombination networkActionCombination3 = new NetworkActionCombination(Set.of(availableRemedialAction4)); - NetworkActionCombination networkActionCombination4 = new NetworkActionCombination(Set.of(appliedRemedialAction1, availableRemedialAction4)); - NetworkActionCombination networkActionCombination5 = new NetworkActionCombination(Set.of(appliedRemedialAction1, appliedRemedialAction2)); - NetworkActionCombination networkActionCombination6 = new NetworkActionCombination(Set.of(availableRemedialAction3, appliedRemedialAction2)); - NetworkActionCombination networkActionCombination7 = new NetworkActionCombination(Set.of(availableRemedialAction2, availableRemedialAction3)); + NetworkActionCombination networkActionCombination4 = new NetworkActionCombination(Set.of(availableRemedialAction2, availableRemedialAction3)); Map naCombinations = Map.of( networkActionCombination1, false, networkActionCombination2, false, networkActionCombination3, true, - networkActionCombination4, false, - networkActionCombination5, false, - networkActionCombination6, true, - networkActionCombination7, true + networkActionCombination4, false ); Leaf previousLeaf = Mockito.mock(Leaf.class); @@ -697,7 +691,7 @@ void removeIncompatibleCombinations() { SearchTreeBloomer bloomer = new SearchTreeBloomer(network, Integer.MAX_VALUE, 2, null, null, false, 0, new ArrayList<>(), pState); assertEquals( - Map.of(networkActionCombination2, false, networkActionCombination3, true, networkActionCombination4, false, networkActionCombination6, true, networkActionCombination7, true), + Map.of(networkActionCombination2, false, networkActionCombination3, true, networkActionCombination4, false), bloomer.removeIncompatibleCombinations(naCombinations, previousLeaf) ); } From 386a4a28d9c7d31fa187752306071d9cf8dea714 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Mon, 25 Mar 2024 16:37:58 +0100 Subject: [PATCH 08/10] Change compatibility rule for switch pairs Signed-off-by: Thomas Bouquet --- .../com/powsybl/openrao/data/cracimpl/SwitchPairImpl.java | 3 +-- .../openrao/data/cracimpl/NetworkActionImplTest.java | 2 +- .../powsybl/openrao/data/cracimpl/SwitchPairImplTest.java | 8 ++++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/SwitchPairImpl.java b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/SwitchPairImpl.java index 5626bf65da..91f996f671 100644 --- a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/SwitchPairImpl.java +++ b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/SwitchPairImpl.java @@ -61,8 +61,7 @@ public NetworkElement getSwitchToClose() { @Override public boolean isCompatibleWith(ElementaryAction otherElementaryAction) { if (otherElementaryAction instanceof SwitchPair switchPair) { - return !switchToOpen.equals(switchPair.getSwitchToOpen()) && !switchToOpen.equals(switchPair.getSwitchToClose()) && !switchToClose.equals(switchPair.getSwitchToClose()) && !switchToClose.equals(switchPair.getSwitchToOpen()) - || switchToOpen.equals(switchPair.getSwitchToOpen()) || switchToClose.equals(switchPair.getSwitchToClose()); + return !switchToOpen.equals(switchPair.getSwitchToOpen()) && !switchToOpen.equals(switchPair.getSwitchToClose()) && !switchToClose.equals(switchPair.getSwitchToClose()) && !switchToClose.equals(switchPair.getSwitchToOpen()); } return true; } diff --git a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/NetworkActionImplTest.java b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/NetworkActionImplTest.java index c7e5584d9e..8a612c4666 100644 --- a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/NetworkActionImplTest.java +++ b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/NetworkActionImplTest.java @@ -137,6 +137,6 @@ void compatibility() { assertTrue(crac.getNetworkAction("hvdc-es-fr-200-mw").isCompatibleWith(crac.getNetworkAction("switch-pair-and-pst"))); assertTrue(crac.getNetworkAction("aligned-psts").isCompatibleWith(crac.getNetworkAction("aligned-psts"))); assertFalse(crac.getNetworkAction("aligned-psts").isCompatibleWith(crac.getNetworkAction("switch-pair-and-pst"))); - assertTrue(crac.getNetworkAction("switch-pair-and-pst").isCompatibleWith(crac.getNetworkAction("switch-pair-and-pst"))); + assertFalse(crac.getNetworkAction("switch-pair-and-pst").isCompatibleWith(crac.getNetworkAction("switch-pair-and-pst"))); } } diff --git a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/SwitchPairImplTest.java b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/SwitchPairImplTest.java index 79005cb521..d8104f688b 100644 --- a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/SwitchPairImplTest.java +++ b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/SwitchPairImplTest.java @@ -119,7 +119,7 @@ void compatibility() { Crac crac = createCracWithRemedialActions(); SwitchPair switchPair = (SwitchPair) crac.getNetworkAction("open-switch-1-close-switch-2").getElementaryActions().iterator().next(); - assertTrue(switchPair.isCompatibleWith(switchPair)); + assertFalse(switchPair.isCompatibleWith(switchPair)); assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-2").getElementaryActions().iterator().next())); assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("close-switch-1").getElementaryActions().iterator().next())); assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("close-switch-2").getElementaryActions().iterator().next())); @@ -134,10 +134,10 @@ void compatibility() { assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("pst-2-tap-3").getElementaryActions().iterator().next())); assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("pst-2-tap-8").getElementaryActions().iterator().next())); - assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-1-close-switch-2").getElementaryActions().iterator().next())); + assertFalse(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-1-close-switch-2").getElementaryActions().iterator().next())); assertFalse(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-2-close-switch-1").getElementaryActions().iterator().next())); assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-3-close-switch-4").getElementaryActions().iterator().next())); - assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-1-close-switch-3").getElementaryActions().iterator().next())); - assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-3-close-switch-2").getElementaryActions().iterator().next())); + assertFalse(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-1-close-switch-3").getElementaryActions().iterator().next())); + assertFalse(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-3-close-switch-2").getElementaryActions().iterator().next())); } } From 55b777c214bf729f229046cf0a23c2053a5f010e Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Wed, 24 Apr 2024 15:03:53 +0200 Subject: [PATCH 09/10] Duplicate isCompatibleWith tests in NetworkActionTest Signed-off-by: Thomas Bouquet --- data/crac/crac-api/pom.xml | 6 ++ .../data/cracapi/NetworkActionTest.java | 95 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/NetworkActionTest.java diff --git a/data/crac/crac-api/pom.xml b/data/crac/crac-api/pom.xml index e1aabf0b33..1360f414c2 100644 --- a/data/crac/crac-api/pom.xml +++ b/data/crac/crac-api/pom.xml @@ -48,5 +48,11 @@ com.powsybl powsybl-contingency-api + + org.mockito + mockito-core + 5.2.0 + test + diff --git a/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/NetworkActionTest.java b/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/NetworkActionTest.java new file mode 100644 index 0000000000..5b5d16db59 --- /dev/null +++ b/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/NetworkActionTest.java @@ -0,0 +1,95 @@ +package com.powsybl.openrao.data.cracapi; + +import com.powsybl.openrao.data.cracapi.networkaction.ActionType; +import com.powsybl.openrao.data.cracapi.networkaction.InjectionSetpoint; +import com.powsybl.openrao.data.cracapi.networkaction.NetworkAction; +import com.powsybl.openrao.data.cracapi.networkaction.PstSetpoint; +import com.powsybl.openrao.data.cracapi.networkaction.SwitchPair; +import com.powsybl.openrao.data.cracapi.networkaction.TopologicalAction; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class NetworkActionTest { + @Test + void compatibility() { + NetworkAction hvdcFrEs200Mw = mockHvdcAction(-200d); + NetworkAction hvdcEsFr200Mw = mockHvdcAction(200d); + NetworkAction alignedPsts = Mockito.mock(NetworkAction.class); + PstSetpoint pstSetpoint1 = mockPstSetpoint("pst-fr-1", 4); + PstSetpoint pstSetpoint2 = mockPstSetpoint("pst-fr-2", 4); + PstSetpoint pstSetpoint3 = mockPstSetpoint("pst-fr-3", 4); + Mockito.when(alignedPsts.getElementaryActions()).thenReturn(Set.of(pstSetpoint1, pstSetpoint2, pstSetpoint3)); + NetworkAction switchPairAndPst = Mockito.mock(NetworkAction.class); + PstSetpoint pstSetpoint4 = mockPstSetpoint("pst-fr-2", -2); + SwitchPair switchPair = mockSwitchPair(); + Mockito.when(switchPairAndPst.getElementaryActions()).thenReturn(Set.of(pstSetpoint4, switchPair)); + + assertTrue(hvdcFrEs200Mw.isCompatibleWith(hvdcFrEs200Mw)); + assertFalse(hvdcFrEs200Mw.isCompatibleWith(hvdcEsFr200Mw)); + assertTrue(hvdcFrEs200Mw.isCompatibleWith(alignedPsts)); + assertTrue(hvdcFrEs200Mw.isCompatibleWith(switchPairAndPst)); + assertTrue(hvdcEsFr200Mw.isCompatibleWith(hvdcEsFr200Mw)); + assertTrue(hvdcEsFr200Mw.isCompatibleWith(alignedPsts)); + assertTrue(hvdcEsFr200Mw.isCompatibleWith(switchPairAndPst)); + assertTrue(alignedPsts.isCompatibleWith(alignedPsts)); + assertFalse(alignedPsts.isCompatibleWith(switchPairAndPst)); + assertFalse(switchPairAndPst.isCompatibleWith(switchPairAndPst)); + } + + private NetworkAction mockHvdcAction(double setpoint) { + NetworkAction hvdcAction = Mockito.mock(NetworkAction.class); + TopologicalAction topologicalAction1 = mockTopologicalAction("switch-fr"); + TopologicalAction topologicalAction2 = mockTopologicalAction("switch-es"); + InjectionSetpoint generatorAction11 = mockInjectionSetpoint("generator-fr-1", setpoint / 2d); + InjectionSetpoint generatorAction12 = mockInjectionSetpoint("generator-fr-2", setpoint / 2d); + InjectionSetpoint generatorAction21 = mockInjectionSetpoint("generator-es-1", -setpoint / 2d); + InjectionSetpoint generatorAction22 = mockInjectionSetpoint("generator-es-2", -setpoint / 2d); + Mockito.when(hvdcAction.getElementaryActions()).thenReturn(Set.of(topologicalAction1, topologicalAction2, generatorAction11, generatorAction12, generatorAction21, generatorAction22)); + Mockito.when(hvdcAction.isCompatibleWith(Mockito.any())).thenCallRealMethod(); + return hvdcAction; + } + + private TopologicalAction mockTopologicalAction(String switchId) { + TopologicalAction topologicalAction = Mockito.mock(TopologicalAction.class); + NetworkElement networkElement = mockNetworkElement(switchId); + Mockito.when(topologicalAction.getNetworkElement()).thenReturn(networkElement); + Mockito.when(topologicalAction.getActionType()).thenReturn(ActionType.OPEN); + return topologicalAction; + } + + private InjectionSetpoint mockInjectionSetpoint(String networkElementId, double setpoint) { + InjectionSetpoint injectionSetpoint = Mockito.mock(InjectionSetpoint.class); + NetworkElement networkElement = mockNetworkElement(networkElementId); + Mockito.when(injectionSetpoint.getSetpoint()).thenReturn(setpoint); + Mockito.when(injectionSetpoint.getNetworkElement()).thenReturn(networkElement); + return injectionSetpoint; + } + + private PstSetpoint mockPstSetpoint(String pstId, int setpoint) { + PstSetpoint pstSetpoint = Mockito.mock(PstSetpoint.class); + NetworkElement networkElement = mockNetworkElement(pstId); + Mockito.when(pstSetpoint.getSetpoint()).thenReturn(setpoint); + Mockito.when(pstSetpoint.getNetworkElement()).thenReturn(networkElement); + return pstSetpoint; + } + + private SwitchPair mockSwitchPair() { + SwitchPair switchPair = Mockito.mock(SwitchPair.class); + NetworkElement switchToOpen = mockNetworkElement("switch-fr"); + NetworkElement switchToClose = mockNetworkElement("switch-es"); + Mockito.when(switchPair.getSwitchToOpen()).thenReturn(switchToOpen); + Mockito.when(switchPair.getSwitchToClose()).thenReturn(switchToClose); + return switchPair; + } + + private NetworkElement mockNetworkElement(String networkElementId) { + NetworkElement networkElement = Mockito.mock(NetworkElement.class); + Mockito.when(networkElement.getId()).thenReturn(networkElementId); + return networkElement; + } +} From 01a35b012a8ddc6facc12c2b23e0023ec84d85a2 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Mon, 17 Jun 2024 14:32:10 +0200 Subject: [PATCH 10/10] Update filter on EA + better tests coverage Signed-off-by: Thomas Bouquet --- data/crac/crac-api/pom.xml | 6 - .../networkaction/InjectionSetpoint.java | 8 + .../cracapi/networkaction/NetworkAction.java | 4 +- .../cracapi/networkaction/PstSetpoint.java | 8 + .../cracapi/networkaction/SwitchPair.java | 13 +- .../networkaction/TopologicalAction.java | 8 + .../ElementaryActionCompatibilityTest.java | 110 +++++ .../data/cracapi/NetworkActionTest.java | 74 ++-- .../data/cracapi/NetworkActionUtils.java | 390 ++++++++++++++++++ .../data/cracimpl/InjectionSetpointImpl.java | 9 - .../data/cracimpl/PstSetpointImpl.java | 9 - .../openrao/data/cracimpl/SwitchPairImpl.java | 9 - .../data/cracimpl/TopologicalActionImpl.java | 9 - .../data/cracimpl/NetworkActionImplTest.java | 2 +- .../data/cracimpl/SwitchPairImplTest.java | 4 +- .../ElementaryActionsCompatibilityFilter.java | 26 ++ .../algorithms/SearchTreeBloomer.java | 3 +- ...mentaryActionsCompatibilityFilterTest.java | 146 +++++++ 18 files changed, 741 insertions(+), 97 deletions(-) create mode 100644 data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/ElementaryActionCompatibilityTest.java create mode 100644 data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/NetworkActionUtils.java create mode 100644 ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/ElementaryActionsCompatibilityFilter.java create mode 100644 ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/ElementaryActionsCompatibilityFilterTest.java diff --git a/data/crac/crac-api/pom.xml b/data/crac/crac-api/pom.xml index abe878fdff..f0aca66532 100644 --- a/data/crac/crac-api/pom.xml +++ b/data/crac/crac-api/pom.xml @@ -48,11 +48,5 @@ com.powsybl powsybl-contingency-api - - org.mockito - mockito-core - 5.2.0 - test - diff --git a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/InjectionSetpoint.java b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/InjectionSetpoint.java index fa46ad6da3..6a9f92e444 100644 --- a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/InjectionSetpoint.java +++ b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/InjectionSetpoint.java @@ -31,4 +31,12 @@ public interface InjectionSetpoint extends ElementaryAction { * Get the unit of the injection setpoint */ Unit getUnit(); + + @Override + default boolean isCompatibleWith(ElementaryAction otherElementaryAction) { + if (otherElementaryAction instanceof InjectionSetpoint injectionSetpoint) { + return !getNetworkElement().equals(injectionSetpoint.getNetworkElement()) || getSetpoint() == injectionSetpoint.getSetpoint() && getUnit() == injectionSetpoint.getUnit(); + } + return true; + } } diff --git a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/NetworkAction.java b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/NetworkAction.java index 32ba162ebb..acf8456dd2 100644 --- a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/NetworkAction.java +++ b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/NetworkAction.java @@ -14,7 +14,7 @@ /** * Remedial action interface specifying a direct action on the network. - * + *

* The Network Action is completely defined by itself. * It involves a Set of {@link ElementaryAction}. * When the apply method is called, an action is triggered on each of these Elementary @@ -35,6 +35,7 @@ public interface NetworkAction extends RemedialAction { /** * Apply the action on a given network. + * * @param network the Network to apply the network action upon * @return true if the network action was applied, false if not (eg if it was already applied) */ @@ -47,6 +48,7 @@ public interface NetworkAction extends RemedialAction { /** * States if the network action can be applied without infringing on another network action's scope. + * * @param otherNetworkAction the other network action to check compatibility with * @return true if both network actions can be applied without any conflictual behaviour */ diff --git a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/PstSetpoint.java b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/PstSetpoint.java index fcbdd4c9f6..a158e52128 100644 --- a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/PstSetpoint.java +++ b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/PstSetpoint.java @@ -25,4 +25,12 @@ public interface PstSetpoint extends ElementaryAction { * Get the Network Element associated to the elementary action */ NetworkElement getNetworkElement(); + + @Override + default boolean isCompatibleWith(ElementaryAction otherElementaryAction) { + if (otherElementaryAction instanceof PstSetpoint pstSetpoint) { + return !getNetworkElement().equals(pstSetpoint.getNetworkElement()) || getSetpoint() == pstSetpoint.getSetpoint(); + } + return true; + } } diff --git a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/SwitchPair.java b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/SwitchPair.java index e0715e7e82..baee9a27ee 100644 --- a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/SwitchPair.java +++ b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/SwitchPair.java @@ -19,10 +19,19 @@ public interface SwitchPair extends ElementaryAction { /** * Get the switch that should be opened by the elementary action */ - public NetworkElement getSwitchToOpen(); + NetworkElement getSwitchToOpen(); /** * Get the switch that should be closed by the elementary action */ - public NetworkElement getSwitchToClose(); + NetworkElement getSwitchToClose(); + + @Override + default boolean isCompatibleWith(ElementaryAction otherElementaryAction) { + if (otherElementaryAction instanceof SwitchPair switchPair) { + return getSwitchToOpen().equals(switchPair.getSwitchToOpen()) && getSwitchToClose().equals(switchPair.getSwitchToClose()) + || !getSwitchToOpen().equals(switchPair.getSwitchToOpen()) && !getSwitchToOpen().equals(switchPair.getSwitchToClose()) && !getSwitchToClose().equals(switchPair.getSwitchToClose()) && !getSwitchToClose().equals(switchPair.getSwitchToOpen()); + } + return true; + } } diff --git a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/TopologicalAction.java b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/TopologicalAction.java index b339c729f8..29729170c4 100644 --- a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/TopologicalAction.java +++ b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/networkaction/TopologicalAction.java @@ -25,4 +25,12 @@ public interface TopologicalAction extends ElementaryAction { * Get the Network Element associated to the elementary action */ NetworkElement getNetworkElement(); + + @Override + default boolean isCompatibleWith(ElementaryAction otherElementaryAction) { + if (otherElementaryAction instanceof TopologicalAction topologicalAction) { + return !getNetworkElement().equals(topologicalAction.getNetworkElement()) || getActionType().equals(topologicalAction.getActionType()); + } + return true; + } } diff --git a/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/ElementaryActionCompatibilityTest.java b/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/ElementaryActionCompatibilityTest.java new file mode 100644 index 0000000000..ca7defe7ff --- /dev/null +++ b/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/ElementaryActionCompatibilityTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package com.powsybl.openrao.data.cracapi; + +import com.powsybl.openrao.commons.Unit; +import com.powsybl.openrao.data.cracapi.networkaction.ActionType; +import com.powsybl.openrao.data.cracapi.networkaction.ElementaryAction; +import com.powsybl.openrao.data.cracapi.networkaction.InjectionSetpoint; +import com.powsybl.openrao.data.cracapi.networkaction.PstSetpoint; +import com.powsybl.openrao.data.cracapi.networkaction.SwitchPair; +import com.powsybl.openrao.data.cracapi.networkaction.TopologicalAction; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * @author Thomas Bouquet {@literal } + */ +class ElementaryActionCompatibilityTest { + private final NetworkElement switchFr = NetworkActionUtils.createNetworkElement("switch-fr"); + private final NetworkElement switchBe = NetworkActionUtils.createNetworkElement("switch-be"); + private final NetworkElement pstFr = NetworkActionUtils.createNetworkElement("pst-fr"); + private final NetworkElement pstBe = NetworkActionUtils.createNetworkElement("pst-be"); + private final NetworkElement generatorFr = NetworkActionUtils.createNetworkElement("generator-fr"); + private final NetworkElement generatorBe = NetworkActionUtils.createNetworkElement("generator-be"); + private final TopologicalAction openSwitchFr = NetworkActionUtils.createTopologyAction(switchFr, ActionType.OPEN); + private final TopologicalAction closeSwitchFr = NetworkActionUtils.createTopologyAction(switchFr, ActionType.CLOSE); + private final TopologicalAction openSwitchBe = NetworkActionUtils.createTopologyAction(switchBe, ActionType.OPEN); + private final TopologicalAction closeSwitchBe = NetworkActionUtils.createTopologyAction(switchBe, ActionType.CLOSE); + private final SwitchPair openSwitchFrCloseSwitchBe = NetworkActionUtils.createSwitchPair(switchFr, switchBe); + private final SwitchPair openSwitchBeCloseSwitchFr = NetworkActionUtils.createSwitchPair(switchBe, switchFr); + private final PstSetpoint pstFr0 = NetworkActionUtils.createPstSetpoint(pstFr, 0); + private final PstSetpoint pstFr5 = NetworkActionUtils.createPstSetpoint(pstFr, 5); + private final PstSetpoint pstBe0 = NetworkActionUtils.createPstSetpoint(pstBe, 0); + private final PstSetpoint pstBeMinus5 = NetworkActionUtils.createPstSetpoint(pstBe, -5); + private final InjectionSetpoint generatorFr0Mw = NetworkActionUtils.createInjectionSetpoint(generatorFr, 0d, Unit.MEGAWATT); + private final InjectionSetpoint generatorFr100Mw = NetworkActionUtils.createInjectionSetpoint(generatorFr, 100d, Unit.MEGAWATT); + private final InjectionSetpoint generatorFr0A = NetworkActionUtils.createInjectionSetpoint(generatorFr, 0d, Unit.AMPERE); + private final InjectionSetpoint generatorFr1000A = NetworkActionUtils.createInjectionSetpoint(generatorFr, 1000d, Unit.AMPERE); + private final InjectionSetpoint generatorBe0Mw = NetworkActionUtils.createInjectionSetpoint(generatorBe, 0d, Unit.MEGAWATT); + private final InjectionSetpoint generatorBe100Mw = NetworkActionUtils.createInjectionSetpoint(generatorBe, 100d, Unit.MEGAWATT); + private final InjectionSetpoint generatorBe0A = NetworkActionUtils.createInjectionSetpoint(generatorBe, 0d, Unit.AMPERE); + private final InjectionSetpoint generatorBe1000A = NetworkActionUtils.createInjectionSetpoint(generatorBe, 1000d, Unit.AMPERE); + private final List elementaryActions = gatherElementaryActions(); + + @Test + void testElementaryActionsCompatibility() { + assertIncompatibility(openSwitchFr, closeSwitchFr); + assertIncompatibility(closeSwitchFr, openSwitchFr); + assertIncompatibility(openSwitchBe, closeSwitchBe); + assertIncompatibility(closeSwitchBe, openSwitchBe); + assertIncompatibility(openSwitchFrCloseSwitchBe, openSwitchBeCloseSwitchFr); + assertIncompatibility(openSwitchBeCloseSwitchFr, openSwitchFrCloseSwitchBe); + assertIncompatibility(pstFr0, pstFr5); + assertIncompatibility(pstFr5, pstFr0); + assertIncompatibility(pstBe0, pstBeMinus5); + assertIncompatibility(pstBeMinus5, pstBe0); + assertIncompatibility(generatorFr0Mw, generatorFr100Mw, generatorFr0A, generatorFr1000A); + assertIncompatibility(generatorFr100Mw, generatorFr0Mw, generatorFr0A, generatorFr1000A); + assertIncompatibility(generatorFr0A, generatorFr100Mw, generatorFr0Mw, generatorFr1000A); + assertIncompatibility(generatorFr1000A, generatorFr0Mw, generatorFr100Mw, generatorFr0A); + assertIncompatibility(generatorBe0Mw, generatorBe100Mw, generatorBe0A, generatorBe1000A); + assertIncompatibility(generatorBe100Mw, generatorBe0Mw, generatorBe0A, generatorBe1000A); + assertIncompatibility(generatorBe0A, generatorBe0Mw, generatorBe100Mw, generatorBe1000A); + assertIncompatibility(generatorBe1000A, generatorBe0Mw, generatorBe100Mw, generatorBe0A); + } + + private List gatherElementaryActions() { + List elementaryActions = new ArrayList<>(); + elementaryActions.add(openSwitchFr); + elementaryActions.add(closeSwitchFr); + elementaryActions.add(openSwitchBe); + elementaryActions.add(closeSwitchBe); + elementaryActions.add(openSwitchFrCloseSwitchBe); + elementaryActions.add(openSwitchBeCloseSwitchFr); + elementaryActions.add(pstFr0); + elementaryActions.add(pstFr5); + elementaryActions.add(pstBe0); + elementaryActions.add(pstBeMinus5); + elementaryActions.add(generatorFr0Mw); + elementaryActions.add(generatorFr100Mw); + elementaryActions.add(generatorFr0A); + elementaryActions.add(generatorFr1000A); + elementaryActions.add(generatorBe0Mw); + elementaryActions.add(generatorBe100Mw); + elementaryActions.add(generatorBe0A); + elementaryActions.add(generatorBe1000A); + return elementaryActions; + } + + private void assertIncompatibility(ElementaryAction elementaryAction, ElementaryAction... incompatibleElementaryActions) { + List incompatibleElementaryActionsList = List.of(incompatibleElementaryActions); + for (ElementaryAction ea : elementaryActions) { + if (incompatibleElementaryActionsList.contains(ea)) { + assertFalse(elementaryAction.isCompatibleWith(ea)); + } else { + assertTrue(elementaryAction.isCompatibleWith(ea)); + } + } + } +} diff --git a/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/NetworkActionTest.java b/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/NetworkActionTest.java index 5b5d16db59..e52f171f4b 100644 --- a/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/NetworkActionTest.java +++ b/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/NetworkActionTest.java @@ -1,33 +1,39 @@ +/* + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + package com.powsybl.openrao.data.cracapi; +import com.powsybl.openrao.commons.Unit; import com.powsybl.openrao.data.cracapi.networkaction.ActionType; +import com.powsybl.openrao.data.cracapi.networkaction.ElementaryAction; import com.powsybl.openrao.data.cracapi.networkaction.InjectionSetpoint; import com.powsybl.openrao.data.cracapi.networkaction.NetworkAction; import com.powsybl.openrao.data.cracapi.networkaction.PstSetpoint; import com.powsybl.openrao.data.cracapi.networkaction.SwitchPair; import com.powsybl.openrao.data.cracapi.networkaction.TopologicalAction; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; +import java.util.HashSet; +import java.util.List; import java.util.Set; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +/** + * @author Thomas Bouquet {@literal } + */ class NetworkActionTest { @Test void compatibility() { NetworkAction hvdcFrEs200Mw = mockHvdcAction(-200d); NetworkAction hvdcEsFr200Mw = mockHvdcAction(200d); - NetworkAction alignedPsts = Mockito.mock(NetworkAction.class); - PstSetpoint pstSetpoint1 = mockPstSetpoint("pst-fr-1", 4); - PstSetpoint pstSetpoint2 = mockPstSetpoint("pst-fr-2", 4); - PstSetpoint pstSetpoint3 = mockPstSetpoint("pst-fr-3", 4); - Mockito.when(alignedPsts.getElementaryActions()).thenReturn(Set.of(pstSetpoint1, pstSetpoint2, pstSetpoint3)); - NetworkAction switchPairAndPst = Mockito.mock(NetworkAction.class); - PstSetpoint pstSetpoint4 = mockPstSetpoint("pst-fr-2", -2); - SwitchPair switchPair = mockSwitchPair(); - Mockito.when(switchPairAndPst.getElementaryActions()).thenReturn(Set.of(pstSetpoint4, switchPair)); + NetworkAction alignedPsts = mockNetworkAction(mockPstSetpoint("pst-fr-1", 4), mockPstSetpoint("pst-fr-2", 4), mockPstSetpoint("pst-fr-3", 4)); + NetworkAction switchPairAndPst = mockNetworkAction(mockPstSetpoint("pst-fr-2", -2), mockSwitchPair()); assertTrue(hvdcFrEs200Mw.isCompatibleWith(hvdcFrEs200Mw)); assertFalse(hvdcFrEs200Mw.isCompatibleWith(hvdcEsFr200Mw)); @@ -38,58 +44,30 @@ void compatibility() { assertTrue(hvdcEsFr200Mw.isCompatibleWith(switchPairAndPst)); assertTrue(alignedPsts.isCompatibleWith(alignedPsts)); assertFalse(alignedPsts.isCompatibleWith(switchPairAndPst)); - assertFalse(switchPairAndPst.isCompatibleWith(switchPairAndPst)); + assertTrue(switchPairAndPst.isCompatibleWith(switchPairAndPst)); } private NetworkAction mockHvdcAction(double setpoint) { - NetworkAction hvdcAction = Mockito.mock(NetworkAction.class); - TopologicalAction topologicalAction1 = mockTopologicalAction("switch-fr"); - TopologicalAction topologicalAction2 = mockTopologicalAction("switch-es"); - InjectionSetpoint generatorAction11 = mockInjectionSetpoint("generator-fr-1", setpoint / 2d); - InjectionSetpoint generatorAction12 = mockInjectionSetpoint("generator-fr-2", setpoint / 2d); - InjectionSetpoint generatorAction21 = mockInjectionSetpoint("generator-es-1", -setpoint / 2d); - InjectionSetpoint generatorAction22 = mockInjectionSetpoint("generator-es-2", -setpoint / 2d); - Mockito.when(hvdcAction.getElementaryActions()).thenReturn(Set.of(topologicalAction1, topologicalAction2, generatorAction11, generatorAction12, generatorAction21, generatorAction22)); - Mockito.when(hvdcAction.isCompatibleWith(Mockito.any())).thenCallRealMethod(); - return hvdcAction; + return new NetworkActionUtils.NetworkActionImplTest(Set.of(mockTopologicalAction("switch-fr"), mockTopologicalAction("switch-es"), mockInjectionSetpoint("generator-fr-1", setpoint / 2d), mockInjectionSetpoint("generator-fr-2", setpoint / 2d), mockInjectionSetpoint("generator-es-1", -setpoint / 2d), mockInjectionSetpoint("generator-es-2", -setpoint / 2d))); + } + + private NetworkAction mockNetworkAction(ElementaryAction... elementaryActions) { + return new NetworkActionUtils.NetworkActionImplTest(new HashSet<>(List.of(elementaryActions))); } private TopologicalAction mockTopologicalAction(String switchId) { - TopologicalAction topologicalAction = Mockito.mock(TopologicalAction.class); - NetworkElement networkElement = mockNetworkElement(switchId); - Mockito.when(topologicalAction.getNetworkElement()).thenReturn(networkElement); - Mockito.when(topologicalAction.getActionType()).thenReturn(ActionType.OPEN); - return topologicalAction; + return new NetworkActionUtils.TopologicalActionImplTest(NetworkActionUtils.createNetworkElement(switchId), ActionType.OPEN); } private InjectionSetpoint mockInjectionSetpoint(String networkElementId, double setpoint) { - InjectionSetpoint injectionSetpoint = Mockito.mock(InjectionSetpoint.class); - NetworkElement networkElement = mockNetworkElement(networkElementId); - Mockito.when(injectionSetpoint.getSetpoint()).thenReturn(setpoint); - Mockito.when(injectionSetpoint.getNetworkElement()).thenReturn(networkElement); - return injectionSetpoint; + return new NetworkActionUtils.InjectionSetpointImplTest(NetworkActionUtils.createNetworkElement(networkElementId), setpoint, Unit.MEGAWATT); } private PstSetpoint mockPstSetpoint(String pstId, int setpoint) { - PstSetpoint pstSetpoint = Mockito.mock(PstSetpoint.class); - NetworkElement networkElement = mockNetworkElement(pstId); - Mockito.when(pstSetpoint.getSetpoint()).thenReturn(setpoint); - Mockito.when(pstSetpoint.getNetworkElement()).thenReturn(networkElement); - return pstSetpoint; + return new NetworkActionUtils.PstSetpointImplTest(NetworkActionUtils.createNetworkElement(pstId), setpoint); } private SwitchPair mockSwitchPair() { - SwitchPair switchPair = Mockito.mock(SwitchPair.class); - NetworkElement switchToOpen = mockNetworkElement("switch-fr"); - NetworkElement switchToClose = mockNetworkElement("switch-es"); - Mockito.when(switchPair.getSwitchToOpen()).thenReturn(switchToOpen); - Mockito.when(switchPair.getSwitchToClose()).thenReturn(switchToClose); - return switchPair; - } - - private NetworkElement mockNetworkElement(String networkElementId) { - NetworkElement networkElement = Mockito.mock(NetworkElement.class); - Mockito.when(networkElement.getId()).thenReturn(networkElementId); - return networkElement; + return new NetworkActionUtils.SwitchPairImplTest(NetworkActionUtils.createNetworkElement("switch-fr"), NetworkActionUtils.createNetworkElement("switch-es")); } } diff --git a/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/NetworkActionUtils.java b/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/NetworkActionUtils.java new file mode 100644 index 0000000000..1c60e23bbc --- /dev/null +++ b/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/NetworkActionUtils.java @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package com.powsybl.openrao.data.cracapi; + +import com.powsybl.commons.extensions.Extension; +import com.powsybl.iidm.network.Country; +import com.powsybl.iidm.network.Network; +import com.powsybl.openrao.commons.Unit; +import com.powsybl.openrao.data.cracapi.cnec.FlowCnec; +import com.powsybl.openrao.data.cracapi.networkaction.ActionType; +import com.powsybl.openrao.data.cracapi.networkaction.ElementaryAction; +import com.powsybl.openrao.data.cracapi.networkaction.InjectionSetpoint; +import com.powsybl.openrao.data.cracapi.networkaction.NetworkAction; +import com.powsybl.openrao.data.cracapi.networkaction.PstSetpoint; +import com.powsybl.openrao.data.cracapi.networkaction.SwitchPair; +import com.powsybl.openrao.data.cracapi.networkaction.TopologicalAction; +import com.powsybl.openrao.data.cracapi.usagerule.OnContingencyStateAdderToRemedialAction; +import com.powsybl.openrao.data.cracapi.usagerule.UsageMethod; +import com.powsybl.openrao.data.cracapi.usagerule.UsageRule; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; + +/** + * @author Thomas Bouquet {@literal } + */ +public final class NetworkActionUtils { + + private NetworkActionUtils() { + } + + public static class TopologicalActionImplTest implements TopologicalAction { + + private final NetworkElement networkElement; + private final ActionType actionType; + + public TopologicalActionImplTest(NetworkElement networkElement, ActionType actionType) { + this.networkElement = networkElement; + this.actionType = actionType; + } + + @Override + public boolean hasImpactOnNetwork(Network network) { + return false; + } + + @Override + public boolean canBeApplied(Network network) { + return false; + } + + @Override + public void apply(Network network) { + + } + + @Override + public Set getNetworkElements() { + return null; + } + + @Override + public ActionType getActionType() { + return actionType; + } + + @Override + public NetworkElement getNetworkElement() { + return networkElement; + } + } + + public static class InjectionSetpointImplTest implements InjectionSetpoint { + + private final NetworkElement networkElement; + private final double setpoint; + private final Unit unit; + + public InjectionSetpointImplTest(NetworkElement networkElement, double setpoint, Unit unit) { + this.networkElement = networkElement; + this.setpoint = setpoint; + this.unit = unit; + } + + @Override + public boolean hasImpactOnNetwork(Network network) { + return false; + } + + @Override + public boolean canBeApplied(Network network) { + return false; + } + + @Override + public void apply(Network network) { + + } + + @Override + public Set getNetworkElements() { + return null; + } + + @Override + public double getSetpoint() { + return setpoint; + } + + @Override + public NetworkElement getNetworkElement() { + return networkElement; + } + + @Override + public Unit getUnit() { + return unit; + } + } + + public static class SwitchPairImplTest implements SwitchPair { + + private final NetworkElement switchToOpen; + private final NetworkElement switchToClose; + + public SwitchPairImplTest(NetworkElement switchToOpen, NetworkElement switchToClose) { + this.switchToOpen = switchToOpen; + this.switchToClose = switchToClose; + } + + @Override + public boolean hasImpactOnNetwork(Network network) { + return false; + } + + @Override + public boolean canBeApplied(Network network) { + return false; + } + + @Override + public void apply(Network network) { + + } + + @Override + public Set getNetworkElements() { + return null; + } + + @Override + public NetworkElement getSwitchToOpen() { + return switchToOpen; + } + + @Override + public NetworkElement getSwitchToClose() { + return switchToClose; + } + } + + public static class PstSetpointImplTest implements PstSetpoint { + + private final NetworkElement networkElement; + private final int setpoint; + + public PstSetpointImplTest(NetworkElement networkElement, int setpoint) { + this.networkElement = networkElement; + this.setpoint = setpoint; + } + + @Override + public boolean hasImpactOnNetwork(Network network) { + return false; + } + + @Override + public boolean canBeApplied(Network network) { + return false; + } + + @Override + public void apply(Network network) { + + } + + @Override + public Set getNetworkElements() { + return null; + } + + @Override + public int getSetpoint() { + return setpoint; + } + + @Override + public NetworkElement getNetworkElement() { + return networkElement; + } + } + + public static class NetworkActionImplTest implements NetworkAction { + + private final Set elementaryActions; + + public NetworkActionImplTest(Set elementaryActions) { + this.elementaryActions = new HashSet<>(elementaryActions); + } + + @Override + public String getId() { + return null; + } + + @Override + public String getName() { + return null; + } + + @Override + public String getOperator() { + return null; + } + + @Override + public Set getUsageRules() { + return null; + } + + @Override + public UsageMethod getUsageMethod(State state) { + return null; + } + + @Override + public Optional getSpeed() { + return Optional.empty(); + } + + @Override + public Set getFlowCnecsConstrainingUsageRules(Set perimeterCnecs, Network network, State optimizedState) { + return null; + } + + @Override + public Set getFlowCnecsConstrainingForOneUsageRule(UsageRule usageRule, Set perimeterCnecs, Network network) { + return null; + } + + @Override + public Set getNetworkElements() { + return null; + } + + @Override + public OnContingencyStateAdderToRemedialAction newOnStateUsageRule() { + return null; + } + + @Override + public boolean hasImpactOnNetwork(Network network) { + return false; + } + + @Override + public boolean apply(Network network) { + return false; + } + + @Override + public Set getElementaryActions() { + return elementaryActions; + } + + @Override + public > void addExtension(Class aClass, E e) { + + } + + @Override + public > E getExtension(Class aClass) { + return null; + } + + @Override + public > E getExtensionByName(String s) { + return null; + } + + @Override + public > boolean removeExtension(Class aClass) { + return false; + } + + @Override + public > Collection getExtensions() { + return null; + } + } + + public static class NetworkElementImplTest implements NetworkElement { + + private final String id; + + public NetworkElementImplTest(String id) { + this.id = id; + } + + @Override + public String getId() { + return id; + } + + @Override + public String getName() { + return null; + } + + @Override + public Set> getLocation(Network network) { + return null; + } + + @Override + public > void addExtension(Class aClass, E e) { + + } + + @Override + public > E getExtension(Class aClass) { + return null; + } + + @Override + public > E getExtensionByName(String s) { + return null; + } + + @Override + public > boolean removeExtension(Class aClass) { + return false; + } + + @Override + public > Collection getExtensions() { + return null; + } + + @Override + public boolean equals(Object object) { + if (object instanceof NetworkElement networkElement) { + return getId().equals(networkElement.getId()); + } + return false; + } + + @Override + public int hashCode() { + return 0; + } + } + + public static NetworkElement createNetworkElement(String networkElementId) { + return new NetworkElementImplTest(networkElementId); + } + + public static TopologicalAction createTopologyAction(NetworkElement networkElement, ActionType actionType) { + return new TopologicalActionImplTest(networkElement, actionType); + } + + public static SwitchPair createSwitchPair(NetworkElement switchToOpen, NetworkElement switchToClose) { + return new SwitchPairImplTest(switchToOpen, switchToClose); + } + + public static PstSetpoint createPstSetpoint(NetworkElement pst, int setpoint) { + return new PstSetpointImplTest(pst, setpoint); + } + + public static InjectionSetpoint createInjectionSetpoint(NetworkElement networkElement, double setpoint, Unit unit) { + return new InjectionSetpointImplTest(networkElement, setpoint, unit); + } +} diff --git a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InjectionSetpointImpl.java b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InjectionSetpointImpl.java index cab6b03326..8815c44827 100644 --- a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InjectionSetpointImpl.java +++ b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InjectionSetpointImpl.java @@ -8,7 +8,6 @@ package com.powsybl.openrao.data.cracimpl; import com.powsybl.openrao.commons.Unit; -import com.powsybl.openrao.data.cracapi.networkaction.ElementaryAction; import com.powsybl.openrao.data.cracapi.networkaction.InjectionSetpoint; import com.powsybl.openrao.data.cracapi.NetworkElement; import com.powsybl.iidm.network.*; @@ -96,14 +95,6 @@ public Set getNetworkElements() { return Collections.singleton(networkElement); } - @Override - public boolean isCompatibleWith(ElementaryAction otherElementaryAction) { - if (otherElementaryAction instanceof InjectionSetpoint injectionSetpoint) { - return !networkElement.equals(injectionSetpoint.getNetworkElement()) || setpoint == injectionSetpoint.getSetpoint(); - } - return true; - } - @Override public boolean equals(Object o) { if (this == o) { diff --git a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/PstSetpointImpl.java b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/PstSetpointImpl.java index 81989798b8..c6f544e56c 100644 --- a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/PstSetpointImpl.java +++ b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/PstSetpointImpl.java @@ -9,7 +9,6 @@ import com.powsybl.openrao.commons.OpenRaoException; import com.powsybl.openrao.data.cracapi.NetworkElement; -import com.powsybl.openrao.data.cracapi.networkaction.ElementaryAction; import com.powsybl.openrao.data.cracapi.networkaction.PstSetpoint; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.PhaseTapChanger; @@ -99,14 +98,6 @@ public boolean canBeApplied(Network network) { return true; } - @Override - public boolean isCompatibleWith(ElementaryAction otherElementaryAction) { - if (otherElementaryAction instanceof PstSetpoint pstSetpoint) { - return !networkElement.equals(pstSetpoint.getNetworkElement()) || setpoint == pstSetpoint.getSetpoint(); - } - return true; - } - @Override public int hashCode() { return networkElement.hashCode() + 7 * Double.valueOf(setpoint).hashCode(); diff --git a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/SwitchPairImpl.java b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/SwitchPairImpl.java index 91f996f671..05f36b99b9 100644 --- a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/SwitchPairImpl.java +++ b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/SwitchPairImpl.java @@ -8,7 +8,6 @@ package com.powsybl.openrao.data.cracimpl; import com.powsybl.openrao.data.cracapi.NetworkElement; -import com.powsybl.openrao.data.cracapi.networkaction.ElementaryAction; import com.powsybl.openrao.data.cracapi.networkaction.SwitchPair; import com.powsybl.iidm.network.Network; @@ -58,14 +57,6 @@ public NetworkElement getSwitchToClose() { return switchToClose; } - @Override - public boolean isCompatibleWith(ElementaryAction otherElementaryAction) { - if (otherElementaryAction instanceof SwitchPair switchPair) { - return !switchToOpen.equals(switchPair.getSwitchToOpen()) && !switchToOpen.equals(switchPair.getSwitchToClose()) && !switchToClose.equals(switchPair.getSwitchToClose()) && !switchToClose.equals(switchPair.getSwitchToOpen()); - } - return true; - } - @Override public boolean equals(Object o) { if (this == o) { diff --git a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/TopologicalActionImpl.java b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/TopologicalActionImpl.java index da3b1b2bb9..781ec550a8 100644 --- a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/TopologicalActionImpl.java +++ b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/TopologicalActionImpl.java @@ -9,7 +9,6 @@ import com.powsybl.openrao.data.cracapi.networkaction.ActionType; import com.powsybl.openrao.data.cracapi.NetworkElement; -import com.powsybl.openrao.data.cracapi.networkaction.ElementaryAction; import com.powsybl.openrao.data.cracapi.networkaction.TopologicalAction; import com.powsybl.iidm.network.Branch; import com.powsybl.iidm.network.Identifiable; @@ -105,14 +104,6 @@ public Set getNetworkElements() { return Collections.singleton(networkElement); } - @Override - public boolean isCompatibleWith(ElementaryAction otherElementaryAction) { - if (otherElementaryAction instanceof TopologicalAction topologicalAction) { - return !networkElement.equals(topologicalAction.getNetworkElement()) || actionType.equals(topologicalAction.getActionType()); - } - return true; - } - @Override public int hashCode() { return networkElement.hashCode() + 37 * actionType.hashCode(); diff --git a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/NetworkActionImplTest.java b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/NetworkActionImplTest.java index 8a612c4666..c7e5584d9e 100644 --- a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/NetworkActionImplTest.java +++ b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/NetworkActionImplTest.java @@ -137,6 +137,6 @@ void compatibility() { assertTrue(crac.getNetworkAction("hvdc-es-fr-200-mw").isCompatibleWith(crac.getNetworkAction("switch-pair-and-pst"))); assertTrue(crac.getNetworkAction("aligned-psts").isCompatibleWith(crac.getNetworkAction("aligned-psts"))); assertFalse(crac.getNetworkAction("aligned-psts").isCompatibleWith(crac.getNetworkAction("switch-pair-and-pst"))); - assertFalse(crac.getNetworkAction("switch-pair-and-pst").isCompatibleWith(crac.getNetworkAction("switch-pair-and-pst"))); + assertTrue(crac.getNetworkAction("switch-pair-and-pst").isCompatibleWith(crac.getNetworkAction("switch-pair-and-pst"))); } } diff --git a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/SwitchPairImplTest.java b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/SwitchPairImplTest.java index d8104f688b..54a23c751d 100644 --- a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/SwitchPairImplTest.java +++ b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/SwitchPairImplTest.java @@ -119,7 +119,7 @@ void compatibility() { Crac crac = createCracWithRemedialActions(); SwitchPair switchPair = (SwitchPair) crac.getNetworkAction("open-switch-1-close-switch-2").getElementaryActions().iterator().next(); - assertFalse(switchPair.isCompatibleWith(switchPair)); + assertTrue(switchPair.isCompatibleWith(switchPair)); assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-2").getElementaryActions().iterator().next())); assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("close-switch-1").getElementaryActions().iterator().next())); assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("close-switch-2").getElementaryActions().iterator().next())); @@ -134,7 +134,7 @@ void compatibility() { assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("pst-2-tap-3").getElementaryActions().iterator().next())); assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("pst-2-tap-8").getElementaryActions().iterator().next())); - assertFalse(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-1-close-switch-2").getElementaryActions().iterator().next())); + assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-1-close-switch-2").getElementaryActions().iterator().next())); assertFalse(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-2-close-switch-1").getElementaryActions().iterator().next())); assertTrue(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-3-close-switch-4").getElementaryActions().iterator().next())); assertFalse(switchPair.isCompatibleWith(crac.getNetworkAction("open-switch-1-close-switch-3").getElementaryActions().iterator().next())); diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/ElementaryActionsCompatibilityFilter.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/ElementaryActionsCompatibilityFilter.java new file mode 100644 index 0000000000..7869d2e930 --- /dev/null +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/ElementaryActionsCompatibilityFilter.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package com.powsybl.openrao.searchtreerao.searchtree.algorithms; + +import com.powsybl.openrao.searchtreerao.commons.NetworkActionCombination; +import com.powsybl.openrao.searchtreerao.result.api.OptimizationResult; + +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author Thomas Bouquet {@literal } + */ +public class ElementaryActionsCompatibilityFilter implements NetworkActionCombinationFilter { + @Override + public Set filter(Set naCombinations, OptimizationResult optimizationResult) { + return naCombinations.stream() + .filter(naCombination -> naCombination.getNetworkActionSet().stream().allMatch(networkAction -> optimizationResult.getActivatedNetworkActions().stream().allMatch(networkAction::isCompatibleWith))) + .collect(Collectors.toSet()); + } +} diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java index 07d0f4a050..9259a1a8df 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/SearchTreeBloomer.java @@ -38,7 +38,8 @@ public SearchTreeBloomer(SearchTreeInput input, SearchTreeParameters parameters) new MaximumNumberOfRemedialActionsFilter(raUsageLimits.getMaxRa()), new MaximumNumberOfRemedialActionPerTsoFilter(raUsageLimits.getMaxTopoPerTso(), raUsageLimits.getMaxRaPerTso()), new MaximumNumberOfTsosFilter(raUsageLimits.getMaxTso()), - new FarFromMostLimitingElementFilter(input.getNetwork(), parameters.getNetworkActionParameters().skipNetworkActionFarFromMostLimitingElements(), parameters.getNetworkActionParameters().getMaxNumberOfBoundariesForSkippingNetworkActions()) + new FarFromMostLimitingElementFilter(input.getNetwork(), parameters.getNetworkActionParameters().skipNetworkActionFarFromMostLimitingElements(), parameters.getNetworkActionParameters().getMaxNumberOfBoundariesForSkippingNetworkActions()), + new ElementaryActionsCompatibilityFilter() ); this.input = input; this.parameters = parameters; diff --git a/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/ElementaryActionsCompatibilityFilterTest.java b/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/ElementaryActionsCompatibilityFilterTest.java new file mode 100644 index 0000000000..121bc283f6 --- /dev/null +++ b/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/searchtree/algorithms/ElementaryActionsCompatibilityFilterTest.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package com.powsybl.openrao.searchtreerao.searchtree.algorithms; + +import com.powsybl.openrao.commons.Unit; +import com.powsybl.openrao.data.cracapi.Crac; +import com.powsybl.openrao.data.cracapi.InstantKind; +import com.powsybl.openrao.data.cracapi.networkaction.ActionType; +import com.powsybl.openrao.data.cracapi.networkaction.NetworkAction; +import com.powsybl.openrao.data.cracapi.usagerule.UsageMethod; +import com.powsybl.openrao.data.cracimpl.CracImplFactory; +import com.powsybl.openrao.searchtreerao.commons.NetworkActionCombination; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * @author Thomas Bouquet {@literal } + */ +class ElementaryActionsCompatibilityFilterTest { + @Test + void removeIncompatibleCombinations() { + Crac crac = new CracImplFactory().create("crac", "crac") + .newInstant("preventive", InstantKind.PREVENTIVE) + .newInstant("outage", InstantKind.OUTAGE) + .newInstant("auto", InstantKind.AUTO) + .newInstant("curative", InstantKind.CURATIVE); + + NetworkAction appliedRemedialAction1 = crac.newNetworkAction() + .withId("applied-remedial-action-1") + .withOperator("FR") + .newTopologicalAction() + .withNetworkElement("switch-1") + .withActionType(ActionType.OPEN) + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + NetworkAction appliedRemedialAction2 = crac.newNetworkAction() + .withId("applied-remedial-action-2") + .withOperator("FR") + .newTopologicalAction() + .withNetworkElement("switch-2") + .withActionType(ActionType.CLOSE) + .add() + .newInjectionSetPoint() + .withNetworkElement("generator-1") + .withSetpoint(100d) + .withUnit(Unit.MEGAWATT) + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + NetworkAction availableRemedialAction1 = crac.newNetworkAction() + .withId("available-remedial-action-1") + .withOperator("FR") + .newTopologicalAction() + .withNetworkElement("switch-2") + .withActionType(ActionType.OPEN) + .add() + .newPstSetPoint() + .withNetworkElement("pst-1") + .withSetpoint(1) + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + NetworkAction availableRemedialAction2 = crac.newNetworkAction() + .withId("available-remedial-action-2") + .withOperator("FR") + .newInjectionSetPoint() + .withNetworkElement("generator-2") + .withSetpoint(75d) + .withUnit(Unit.MEGAWATT) + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + NetworkAction availableRemedialAction3 = crac.newNetworkAction() + .withId("available-remedial-action-3") + .withOperator("FR") + .newInjectionSetPoint() + .withNetworkElement("generator-1") + .withSetpoint(100d) + .withUnit(Unit.MEGAWATT) + .add() + .newTopologicalAction() + .withNetworkElement("switch-3") + .withActionType(ActionType.CLOSE) + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + NetworkAction availableRemedialAction4 = crac.newNetworkAction() + .withId("available-remedial-action-4") + .withOperator("FR") + .newSwitchPair() + .withSwitchToOpen("switch-2") + .withSwitchToClose("switch-1") + .add() + .newOnInstantUsageRule() + .withInstant("preventive") + .withUsageMethod(UsageMethod.AVAILABLE) + .add() + .add(); + + NetworkActionCombination networkActionCombination1 = new NetworkActionCombination(Set.of(availableRemedialAction1, availableRemedialAction2)); + NetworkActionCombination networkActionCombination2 = new NetworkActionCombination(Set.of(availableRemedialAction3)); + NetworkActionCombination networkActionCombination3 = new NetworkActionCombination(Set.of(availableRemedialAction4)); + NetworkActionCombination networkActionCombination4 = new NetworkActionCombination(Set.of(availableRemedialAction2, availableRemedialAction3)); + + ElementaryActionsCompatibilityFilter naFilter = new ElementaryActionsCompatibilityFilter(); + Set naCombinations = Set.of(networkActionCombination1, networkActionCombination2, networkActionCombination3, networkActionCombination4); + + Leaf previousLeaf = Mockito.mock(Leaf.class); + Mockito.when(previousLeaf.getActivatedNetworkActions()).thenReturn(Set.of(appliedRemedialAction1, appliedRemedialAction2)); + + assertEquals( + Set.of(networkActionCombination2, networkActionCombination3, networkActionCombination4), + naFilter.filter(naCombinations, previousLeaf) + ); + } +}