RaoParametersConfigTest.java
/*
* Copyright (c) 2023, 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.raoapi.parameters;
import com.powsybl.openrao.commons.OpenRaoException;
import com.powsybl.openrao.commons.Unit;
import com.powsybl.openrao.raoapi.parameters.extensions.*;
import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import com.powsybl.commons.config.*;
import com.powsybl.iidm.network.Country;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.nio.file.FileSystem;
import java.util.*;
import static com.powsybl.openrao.raoapi.parameters.extensions.SearchTreeRaoObjectiveFunctionParameters.getCurativeMinObjImprovement;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
/**
* @author Godelaine de Montmorillon {@literal <godelaine.demontmorillon at rte-france.com>}
*/
class RaoParametersConfigTest {
private PlatformConfig mockedPlatformConfig;
private InMemoryPlatformConfig platformCfg;
static final double DOUBLE_TOLERANCE = 1e-6;
@BeforeEach
public void setUp() {
mockedPlatformConfig = Mockito.mock(PlatformConfig.class);
FileSystem fileSystem = Jimfs.newFileSystem(Configuration.unix());
platformCfg = new InMemoryPlatformConfig(fileSystem);
}
@Test
void checkObjectiveFunctionConfig() {
MapModuleConfig objectiveFunctionModuleConfig = platformCfg.createModuleConfig("rao-objective-function");
objectiveFunctionModuleConfig.setStringProperty("type", "MAX_MIN_RELATIVE_MARGIN");
objectiveFunctionModuleConfig.setStringProperty("unit", "AMPERE");
objectiveFunctionModuleConfig.setStringProperty("enforce-curative-security", "false");
MapModuleConfig objectiveFunctionModuleConfigExt = platformCfg.createModuleConfig("search-tree-objective-function");
objectiveFunctionModuleConfigExt.setStringProperty("curative-min-obj-improvement", Objects.toString(123.0));
RaoParameters parameters = RaoParameters.load(platformCfg);
ObjectiveFunctionParameters objectiveFunctionParameters = parameters.getObjectiveFunctionParameters();
assertEquals(ObjectiveFunctionParameters.ObjectiveFunctionType.MAX_MIN_RELATIVE_MARGIN, objectiveFunctionParameters.getType());
assertEquals(Unit.AMPERE, objectiveFunctionParameters.getUnit());
assertEquals(123, getCurativeMinObjImprovement(parameters), DOUBLE_TOLERANCE);
assertFalse(objectiveFunctionParameters.getEnforceCurativeSecurity());
}
@Test
void checkRangeActionsOptimizationConfig() {
MapModuleConfig rangeActionsOptimizationModuleConfig = platformCfg.createModuleConfig("rao-range-actions-optimization");
rangeActionsOptimizationModuleConfig.setStringProperty("pst-ra-min-impact-threshold", Objects.toString(44));
rangeActionsOptimizationModuleConfig.setStringProperty("hvdc-ra-min-impact-threshold", Objects.toString(33));
rangeActionsOptimizationModuleConfig.setStringProperty("injection-ra-min-impact-threshold", Objects.toString(22));
MapModuleConfig rangeActionsOptimizationModuleConfigExt = platformCfg.createModuleConfig("search-tree-range-actions-optimization");
rangeActionsOptimizationModuleConfigExt.setStringProperty("max-mip-iterations", Objects.toString(4));
rangeActionsOptimizationModuleConfigExt.setStringProperty("pst-sensitivity-threshold", Objects.toString(7));
rangeActionsOptimizationModuleConfigExt.setStringProperty("pst-model", "APPROXIMATED_INTEGERS");
rangeActionsOptimizationModuleConfigExt.setStringProperty("hvdc-sensitivity-threshold", Objects.toString(8));
rangeActionsOptimizationModuleConfigExt.setStringProperty("injection-ra-sensitivity-threshold", Objects.toString(9));
MapModuleConfig linearOptimizationSolverModuleConfig = platformCfg.createModuleConfig("search-tree-linear-optimization-solver");
linearOptimizationSolverModuleConfig.setStringProperty("solver", "XPRESS");
linearOptimizationSolverModuleConfig.setStringProperty("relative-mip-gap", Objects.toString(22));
linearOptimizationSolverModuleConfig.setStringProperty("solver-specific-parameters", "blabla");
RaoParameters parameters = RaoParameters.load(platformCfg);
RangeActionsOptimizationParameters params = parameters.getRangeActionsOptimizationParameters();
SearchTreeRaoRangeActionsOptimizationParameters paramsExt = parameters.getExtension(OpenRaoSearchTreeParameters.class).getRangeActionsOptimizationParameters();
assertEquals(4, paramsExt.getMaxMipIterations(), DOUBLE_TOLERANCE);
assertEquals(44, params.getPstRAMinImpactThreshold(), DOUBLE_TOLERANCE);
assertEquals(7, paramsExt.getPstSensitivityThreshold(), DOUBLE_TOLERANCE);
assertEquals(SearchTreeRaoRangeActionsOptimizationParameters.PstModel.APPROXIMATED_INTEGERS, paramsExt.getPstModel());
assertEquals(SearchTreeRaoRangeActionsOptimizationParameters.RaRangeShrinking.DISABLED, paramsExt.getRaRangeShrinking());
assertEquals(33, params.getHvdcRAMinImpactThreshold(), DOUBLE_TOLERANCE);
assertEquals(8, paramsExt.getHvdcSensitivityThreshold(), DOUBLE_TOLERANCE);
assertEquals(22, params.getInjectionRAMinImpactThreshold(), DOUBLE_TOLERANCE);
assertEquals(9, paramsExt.getInjectionRaSensitivityThreshold(), DOUBLE_TOLERANCE);
assertEquals(SearchTreeRaoRangeActionsOptimizationParameters.Solver.XPRESS, paramsExt.getLinearOptimizationSolver().getSolver());
assertEquals(22, paramsExt.getLinearOptimizationSolver().getRelativeMipGap(), DOUBLE_TOLERANCE);
assertEquals("blabla", paramsExt.getLinearOptimizationSolver().getSolverSpecificParameters());
}
@Test
void checkTopoActionsOptimizationConfig() {
MapModuleConfig topoActionsModuleConfig = platformCfg.createModuleConfig("rao-topological-actions-optimization");
topoActionsModuleConfig.setStringProperty("relative-minimum-impact-threshold", Objects.toString(0.9));
topoActionsModuleConfig.setStringProperty("absolute-minimum-impact-threshold", Objects.toString(22));
MapModuleConfig topoActionsModuleConfigExt = platformCfg.createModuleConfig("search-tree-topological-actions-optimization");
topoActionsModuleConfigExt.setStringProperty("max-preventive-search-tree-depth", Objects.toString(3));
topoActionsModuleConfigExt.setStringProperty("max-curative-search-tree-depth", Objects.toString(3));
topoActionsModuleConfigExt.setStringListProperty("predefined-combinations", List.of("{na12} + {na22}", "{na41} + {na5} + {na6}"));
topoActionsModuleConfigExt.setStringProperty("skip-actions-far-from-most-limiting-element", Objects.toString(true));
topoActionsModuleConfigExt.setStringProperty("max-number-of-boundaries-for-skipping-actions", Objects.toString(3333));
RaoParameters parameters = RaoParameters.load(platformCfg);
TopoOptimizationParameters params = parameters.getTopoOptimizationParameters();
SearchTreeRaoTopoOptimizationParameters paramsExt = parameters.getExtension(OpenRaoSearchTreeParameters.class).getTopoOptimizationParameters();
assertEquals(3, paramsExt.getMaxPreventiveSearchTreeDepth(), DOUBLE_TOLERANCE);
assertEquals(3, paramsExt.getMaxCurativeSearchTreeDepth(), DOUBLE_TOLERANCE);
assertEquals(List.of(List.of("na12", "na22"), List.of("na41", "na5", "na6")), paramsExt.getPredefinedCombinations());
assertEquals(0.9, params.getRelativeMinImpactThreshold(), DOUBLE_TOLERANCE);
assertEquals(22, params.getAbsoluteMinImpactThreshold(), DOUBLE_TOLERANCE);
assertTrue(paramsExt.getSkipActionsFarFromMostLimitingElement());
assertEquals(3333, paramsExt.getMaxNumberOfBoundariesForSkippingActions(), DOUBLE_TOLERANCE);
}
@Test
void checkMultiThreadingConfig() {
MapModuleConfig multiThreadingModuleConfig = platformCfg.createModuleConfig("search-tree-multi-threading");
multiThreadingModuleConfig.setStringProperty("available-cpus", Objects.toString(43));
RaoParameters parameters = RaoParameters.load(platformCfg);
MultithreadingParameters params = parameters.getExtension(OpenRaoSearchTreeParameters.class).getMultithreadingParameters();
assertEquals(43, params.getAvailableCPUs(), DOUBLE_TOLERANCE);
}
@Test
void checkSecondPreventiveRaoConfig() {
MapModuleConfig secondPreventiveRaoModuleConfig = platformCfg.createModuleConfig("search-tree-second-preventive-rao");
secondPreventiveRaoModuleConfig.setStringProperty("execution-condition", "POSSIBLE_CURATIVE_IMPROVEMENT");
secondPreventiveRaoModuleConfig.setStringProperty("re-optimize-curative-range-actions", Objects.toString(false));
secondPreventiveRaoModuleConfig.setStringProperty("hint-from-first-preventive-rao", Objects.toString(true));
RaoParameters parameters = RaoParameters.load(platformCfg);
SecondPreventiveRaoParameters params = parameters.getExtension(OpenRaoSearchTreeParameters.class).getSecondPreventiveRaoParameters();
assertEquals(SecondPreventiveRaoParameters.ExecutionCondition.POSSIBLE_CURATIVE_IMPROVEMENT, params.getExecutionCondition());
assertFalse(params.getReOptimizeCurativeRangeActions());
assertTrue(params.getHintFromFirstPreventiveRao());
}
@Test
void checkNotOptimizedCnecsConfig() {
MapModuleConfig notOptimizedModuleConfig = platformCfg.createModuleConfig("rao-not-optimized-cnecs");
notOptimizedModuleConfig.setStringProperty("do-not-optimize-curative-cnecs-for-tsos-without-cras", Objects.toString(false));
RaoParameters parameters = RaoParameters.load(platformCfg);
NotOptimizedCnecsParameters params = parameters.getNotOptimizedCnecsParameters();
assertFalse(params.getDoNotOptimizeCurativeCnecsForTsosWithoutCras());
}
@Test
void checkLoadFlowParametersConfig() {
MapModuleConfig loadFlowModuleConfig = platformCfg.createModuleConfig("search-tree-load-flow-and-sensitivity-computation");
loadFlowModuleConfig.setStringProperty("load-flow-provider", "Bonjour");
loadFlowModuleConfig.setStringProperty("sensitivity-provider", "Au revoir");
loadFlowModuleConfig.setStringProperty("sensitivity-failure-overcost", Objects.toString(32));
RaoParameters parameters = RaoParameters.load(platformCfg);
LoadFlowAndSensitivityParameters paramsExt = parameters.getExtension(OpenRaoSearchTreeParameters.class).getLoadFlowAndSensitivityParameters();
assertEquals("Bonjour", paramsExt.getLoadFlowProvider());
assertEquals("Au revoir", paramsExt.getSensitivityProvider());
assertEquals(32, paramsExt.getSensitivityFailureOvercost(), DOUBLE_TOLERANCE);
}
@Test
void checkLoopFlowParametersConfig() {
ModuleConfig loopFlowModuleConfig = Mockito.mock(ModuleConfig.class);
Mockito.when(loopFlowModuleConfig.getDoubleProperty(eq("acceptable-increase"), anyDouble())).thenReturn(32.);
Mockito.when(loopFlowModuleConfig.getStringListProperty(eq("countries"), anyList())).thenReturn(List.of("FR", "ES", "PT"));
Mockito.when(mockedPlatformConfig.getOptionalModuleConfig("rao-loop-flow-parameters")).thenReturn(Optional.of(loopFlowModuleConfig));
LoopFlowParameters parameters = RaoParameters.load(mockedPlatformConfig).getLoopFlowParameters().get();
assertEquals(32, parameters.getAcceptableIncrease(), DOUBLE_TOLERANCE);
Set<Country> expectedCountries = Set.of(Country.FR, Country.ES, Country.PT);
assertEquals(expectedCountries, parameters.getCountries());
}
@Test
void checkLoopFlowParametersConfigExtension() {
ModuleConfig loopFlowModuleConfig = Mockito.mock(ModuleConfig.class);
Mockito.when(loopFlowModuleConfig.getEnumProperty(eq("ptdf-approximation"), eq(PtdfApproximation.class), any())).thenReturn(PtdfApproximation.UPDATE_PTDF_WITH_TOPO);
Mockito.when(loopFlowModuleConfig.getDoubleProperty(eq("violation-cost"), anyDouble())).thenReturn(43.);
Mockito.when(loopFlowModuleConfig.getDoubleProperty(eq("constraint-adjustment-coefficient"), anyDouble())).thenReturn(45.);
Mockito.when(mockedPlatformConfig.getOptionalModuleConfig("search-tree-loop-flow-parameters")).thenReturn(Optional.of(loopFlowModuleConfig));
OpenRaoSearchTreeParametersConfigLoader configLoader = new OpenRaoSearchTreeParametersConfigLoader();
SearchTreeRaoLoopFlowParameters parameters = configLoader.load(mockedPlatformConfig).getLoopFlowParameters().get();
assertEquals(PtdfApproximation.UPDATE_PTDF_WITH_TOPO, parameters.getPtdfApproximation());
assertEquals(45, parameters.getConstraintAdjustmentCoefficient(), DOUBLE_TOLERANCE);
assertEquals(43, parameters.getViolationCost(), DOUBLE_TOLERANCE);
Set<Country> expectedCountries = Set.of(Country.FR, Country.ES, Country.PT);
}
@Test
void checkMnecParametersConfig() {
ModuleConfig mnecModuleConfig = Mockito.mock(ModuleConfig.class);
Mockito.when(mnecModuleConfig.getDoubleProperty(eq("acceptable-margin-decrease"), anyDouble())).thenReturn(32.);
Mockito.when(mockedPlatformConfig.getOptionalModuleConfig("rao-mnec-parameters")).thenReturn(Optional.of(mnecModuleConfig));
MnecParameters parameters = RaoParameters.load(mockedPlatformConfig).getMnecParameters().get();
assertEquals(32, parameters.getAcceptableMarginDecrease(), DOUBLE_TOLERANCE);
}
@Test
void checkMnecParametersConfigExtension() {
ModuleConfig mnecModuleConfig = Mockito.mock(ModuleConfig.class);
Mockito.when(mnecModuleConfig.getDoubleProperty(eq("violation-cost"), anyDouble())).thenReturn(43.);
Mockito.when(mnecModuleConfig.getDoubleProperty(eq("constraint-adjustment-coefficient"), anyDouble())).thenReturn(45.);
Mockito.when(mockedPlatformConfig.getOptionalModuleConfig("search-tree-mnec-parameters")).thenReturn(Optional.of(mnecModuleConfig));
OpenRaoSearchTreeParametersConfigLoader configLoader = new OpenRaoSearchTreeParametersConfigLoader();
SearchTreeRaoMnecParameters parameters = configLoader.load(mockedPlatformConfig).getMnecParameters().get();
assertEquals(43, parameters.getViolationCost(), DOUBLE_TOLERANCE);
assertEquals(45, parameters.getConstraintAdjustmentCoefficient(), DOUBLE_TOLERANCE);
}
@Test
void checkCostlyMinMarginParametersConfig() {
ModuleConfig minMarginsModuleConfig = Mockito.mock(ModuleConfig.class);
Mockito.when(minMarginsModuleConfig.getDoubleProperty(eq("shifted-violation-penalty"), anyDouble())).thenReturn(43.);
Mockito.when(mockedPlatformConfig.getOptionalModuleConfig("search-tree-costly-min-margin-parameters")).thenReturn(Optional.of(minMarginsModuleConfig));
OpenRaoSearchTreeParametersConfigLoader configLoader = new OpenRaoSearchTreeParametersConfigLoader();
SearchTreeRaoCostlyMinMarginParameters parameters = configLoader.load(mockedPlatformConfig).getMinMarginsParameters().get();
assertEquals(43, parameters.getShiftedViolationPenalty(), DOUBLE_TOLERANCE);
}
@Test
void checkRelativeMarginsConfig() {
ModuleConfig relativeMarginsModuleConfig = Mockito.mock(ModuleConfig.class);
Mockito.when(relativeMarginsModuleConfig.getStringListProperty(eq("ptdf-boundaries"), anyList())).thenReturn(List.of("{FR}-{BE}", "{FR}-{DE}", "{BE}-{22Y201903144---9}-{DE}+{22Y201903145---4}"));
Mockito.when(mockedPlatformConfig.getOptionalModuleConfig("rao-relative-margins-parameters")).thenReturn(Optional.of(relativeMarginsModuleConfig));
RelativeMarginsParameters parameters = RaoParameters.load(mockedPlatformConfig).getRelativeMarginsParameters().get();
List<String> expectedBoundaries = List.of("{FR}-{BE}", "{FR}-{DE}", "{BE}-{22Y201903144---9}-{DE}+{22Y201903145---4}");
assertEquals(expectedBoundaries, parameters.getPtdfBoundariesAsString());
}
@Test
void checkRelativeMarginsConfigExtension() {
ModuleConfig relativeMarginsModuleConfig = Mockito.mock(ModuleConfig.class);
Mockito.when(relativeMarginsModuleConfig.getDoubleProperty(eq("ptdf-sum-lower-bound"), anyDouble())).thenReturn(32.);
Mockito.when(mockedPlatformConfig.getOptionalModuleConfig("search-tree-relative-margins-parameters")).thenReturn(Optional.of(relativeMarginsModuleConfig));
OpenRaoSearchTreeParametersConfigLoader configLoader = new OpenRaoSearchTreeParametersConfigLoader();
SearchTreeRaoRelativeMarginsParameters parameters = configLoader.load(mockedPlatformConfig).getRelativeMarginsParameters().get();
assertEquals(32, parameters.getPtdfSumLowerBound(), DOUBLE_TOLERANCE);
}
@Test
void checkMultipleConfigs() {
MapModuleConfig objectiveFunctionModuleConfig = platformCfg.createModuleConfig("rao-objective-function");
objectiveFunctionModuleConfig.setStringProperty("type", "MAX_MIN_RELATIVE_MARGIN");
objectiveFunctionModuleConfig.setStringProperty("unit", "AMPERE");
MapModuleConfig objectiveFunctionExtModuleConfig = platformCfg.createModuleConfig("search-tree-objective-function");
objectiveFunctionExtModuleConfig.setStringProperty("curative-min-obj-improvement", Objects.toString(123.0));
MapModuleConfig rangeActionsOptimizationExtModuleConfig = platformCfg.createModuleConfig("search-tree-range-actions-optimization");
rangeActionsOptimizationExtModuleConfig.setStringProperty("max-mip-iterations", Objects.toString(32));
RaoParameters parameters = RaoParameters.load(platformCfg);
assertEquals(ObjectiveFunctionParameters.ObjectiveFunctionType.MAX_MIN_RELATIVE_MARGIN, parameters.getObjectiveFunctionParameters().getType());
assertEquals(Unit.AMPERE, parameters.getObjectiveFunctionParameters().getUnit());
OpenRaoSearchTreeParameters searchTreeParameters = parameters.getExtension(OpenRaoSearchTreeParameters.class);
assertEquals(123, searchTreeParameters.getObjectiveFunctionParameters().getCurativeMinObjImprovement(), 1e-6);
assertEquals(32, searchTreeParameters.getRangeActionsOptimizationParameters().getMaxMipIterations(), 1e-6);
assertTrue(parameters.getLoopFlowParameters().isEmpty());
assertTrue(parameters.getMnecParameters().isEmpty());
assertTrue(parameters.getRelativeMarginsParameters().isEmpty());
assertTrue(searchTreeParameters.getLoopFlowParameters().isEmpty());
assertTrue(searchTreeParameters.getMnecParameters().isEmpty());
assertTrue(searchTreeParameters.getRelativeMarginsParameters().isEmpty());
}
@Test
void inconsistentPredefinedCombinations1() {
MapModuleConfig topoActionsModuleConfig = platformCfg.createModuleConfig("search-tree-topological-actions-optimization");
topoActionsModuleConfig.setStringListProperty("predefined-combinations", List.of("{na12 + {na22}", "{na41} + {na5} + {na6}"));
assertThrows(OpenRaoException.class, () -> RaoParameters.load(platformCfg));
}
@Test
void inconsistentPredefinedCombinations2() {
MapModuleConfig topoActionsModuleConfig = platformCfg.createModuleConfig("search-tree-topological-actions-optimization");
topoActionsModuleConfig.setStringListProperty("predefined-combinations", List.of("{na12} - {na22}", "{na41} + {na5} + {na6}"));
assertThrows(OpenRaoException.class, () -> RaoParameters.load(platformCfg));
}
@Test
void inconsistentLoopFlowCountries() {
ModuleConfig loopFlowModuleConfig = Mockito.mock(ModuleConfig.class);
Mockito.when(loopFlowModuleConfig.getStringListProperty(eq("countries"), anyList())).thenReturn(List.of("France", "ES", "PT"));
Mockito.when(mockedPlatformConfig.getOptionalModuleConfig("rao-loop-flow-parameters")).thenReturn(Optional.of(loopFlowModuleConfig));
assertThrows(OpenRaoException.class, () -> RaoParameters.load(mockedPlatformConfig));
}
@Test
void inconsistentRelativeMarginsBoundaries1() {
ModuleConfig relativeMarginsModuleConfig = Mockito.mock(ModuleConfig.class);
Mockito.when(relativeMarginsModuleConfig.getStringListProperty(eq("ptdf-boundaries"), anyList())).thenReturn(List.of("{FR}{BE}"));
Mockito.when(mockedPlatformConfig.getOptionalModuleConfig("rao-relative-margins-parameters")).thenReturn(Optional.of(relativeMarginsModuleConfig));
assertThrows(OpenRaoException.class, () -> RaoParameters.load(mockedPlatformConfig));
}
@Test
void inconsistentRelativeMarginsBoundaries2() {
ModuleConfig relativeMarginsModuleConfig = Mockito.mock(ModuleConfig.class);
Mockito.when(relativeMarginsModuleConfig.getStringListProperty(eq("ptdf-boundaries"), anyList())).thenReturn(List.of("{FR-{BE}"));
Mockito.when(mockedPlatformConfig.getOptionalModuleConfig("rao-relative-margins-parameters")).thenReturn(Optional.of(relativeMarginsModuleConfig));
assertThrows(OpenRaoException.class, () -> RaoParameters.load(mockedPlatformConfig));
}
}