Skip to content

Commit

Permalink
Add possibility to optimize curative perimeter if preventive perimete…
Browse files Browse the repository at this point in the history
…r is unsecure and preventive stop criterion is SECURE (#988)

Signed-off-by: belthlemar <martin.belthle@rte-france.com>
  • Loading branch information
murgeyseb authored and MartinBelthle committed May 28, 2024
1 parent 0980ac0 commit 904887f
Show file tree
Hide file tree
Showing 124 changed files with 440 additions and 130 deletions.
16 changes: 14 additions & 2 deletions docs/parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ These parameters (objective-function) configure the remedial action optimisation
- **Usage**: used as a minimum improvement of the preventive RAO objective value for the curative RAO stop criterion,
when it is set to PREVENTIVE_OBJECTIVE or PREVENTIVE_OBJECTIVE_AND_SECURE.

#### optimize-curative-if-preventive-unsecure
- **Expected value**: true/false
- **Default value**: false
- **Usage**: if this parameter is set to true, OpenRAO will continue optimizing curative states even if preventive state
is unsecure.
If this parameter is set to false, OpenRAO will stop after preventive if preventive state is unsecure and won't try to
improve curative states.

*Note: Only applied when ["preventive-stop-criterion"](#preventive-stop-criterion) is set to SECURE. In this case, if preventive was unsecure,
second preventive won't be run, even if curative cost is higher, in order to save computation time*

### Range actions optimisation parameters
These parameters (range-actions-optimization) tune the [linear optimiser](/castor/linear-problem/linear-rao.md) used to optimise range actions.
(See [Modelling CNECs and range actions](/castor/linear-problem/core-problem-filler.md))
Expand Down Expand Up @@ -585,13 +596,14 @@ Zones are seperated by + or -.
:::{group-tab} JSON
~~~json
{
"version" : "2.3",
"version" : "2.4",
"objective-function" : {
"type" : "MAX_MIN_RELATIVE_MARGIN_IN_AMPERE",
"forbid-cost-increase" : false,
"curative-min-obj-improvement" : 0.0,
"preventive-stop-criterion" : "SECURE",
"curative-stop-criterion" : "PREVENTIVE_OBJECTIVE"
"curative-stop-criterion" : "PREVENTIVE_OBJECTIVE",
"optimize-curative-if-preventive-unsecure" : true
},
"range-actions-optimization" : {
"max-mip-iterations" : 5,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public final class RaoParametersCommons {
private RaoParametersCommons() {
}

public static final String RAO_PARAMETERS_VERSION = "2.3";
public static final String RAO_PARAMETERS_VERSION = "2.4";

// header
public static final String VERSION = "version";
Expand All @@ -29,6 +29,7 @@ private RaoParametersCommons() {
public static final String CURATIVE_MIN_OBJ_IMPROVEMENT = "curative-min-obj-improvement";
public static final String PREVENTIVE_STOP_CRITERION = "preventive-stop-criterion";
public static final String CURATIVE_STOP_CRITERION = "curative-stop-criterion";
public static final String OPTIMIZE_CURATIVE_IF_PREVENTIVE_UNSECURE = "optimize-curative-if-preventive-unsecure";

// range actions optimization parameters
public static final String RANGE_ACTIONS_OPTIMIZATION = "range-actions-optimization";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ static void serialize(RaoParameters parameters, JsonGenerator jsonGenerator) thr
jsonGenerator.writeObjectField(PREVENTIVE_STOP_CRITERION, parameters.getObjectiveFunctionParameters().getPreventiveStopCriterion());
jsonGenerator.writeObjectField(CURATIVE_STOP_CRITERION, parameters.getObjectiveFunctionParameters().getCurativeStopCriterion());
jsonGenerator.writeNumberField(CURATIVE_MIN_OBJ_IMPROVEMENT, parameters.getObjectiveFunctionParameters().getCurativeMinObjImprovement());
jsonGenerator.writeBooleanField(OPTIMIZE_CURATIVE_IF_PREVENTIVE_UNSECURE, parameters.getObjectiveFunctionParameters().getOptimizeCurativeIfPreventiveUnsecure());
jsonGenerator.writeEndObject();
}

Expand All @@ -54,6 +55,10 @@ static void deserialize(JsonParser jsonParser, RaoParameters raoParameters) thro
jsonParser.nextToken();
raoParameters.getObjectiveFunctionParameters().setCurativeMinObjImprovement(jsonParser.getValueAsDouble());
break;
case OPTIMIZE_CURATIVE_IF_PREVENTIVE_UNSECURE:
jsonParser.nextToken();
raoParameters.getObjectiveFunctionParameters().setOptimizeCurativeIfPreventiveUnsecure(jsonParser.getBooleanValue());
break;
default:
throw new OpenRaoException(String.format("Cannot deserialize objective function parameters: unexpected field in %s (%s)", OBJECTIVE_FUNCTION, jsonParser.getCurrentName()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ public class ObjectiveFunctionParameters {
private static final double DEFAULT_CURATIVE_MIN_OBJ_IMPROVEMENT = 0;
private static final PreventiveStopCriterion DEFAULT_PREVENTIVE_STOP_CRITERION = PreventiveStopCriterion.SECURE;
private static final CurativeStopCriterion DEFAULT_CURATIVE_STOP_CRITERION = CurativeStopCriterion.MIN_OBJECTIVE;
private static final boolean DEFAULT_OPTIMIZE_CURATIVE_IF_PREVENTIVE_UNSECURE = false;
// Attributes
private ObjectiveFunctionType type = DEFAULT_OBJECTIVE_FUNCTION;
private boolean forbidCostIncrease = DEFAULT_FORBID_COST_INCREASE;
private double curativeMinObjImprovement = DEFAULT_CURATIVE_MIN_OBJ_IMPROVEMENT;
private PreventiveStopCriterion preventiveStopCriterion = DEFAULT_PREVENTIVE_STOP_CRITERION;
private CurativeStopCriterion curativeStopCriterion = DEFAULT_CURATIVE_STOP_CRITERION;
private boolean optimizeCurativeIfPreventiveUnsecure = DEFAULT_OPTIMIZE_CURATIVE_IF_PREVENTIVE_UNSECURE;

// Enum
public enum ObjectiveFunctionType {
Expand Down Expand Up @@ -104,6 +106,14 @@ public void setCurativeStopCriterion(CurativeStopCriterion curativeStopCriterion
this.curativeStopCriterion = curativeStopCriterion;
}

public boolean getOptimizeCurativeIfPreventiveUnsecure() {
return optimizeCurativeIfPreventiveUnsecure;
}

public void setOptimizeCurativeIfPreventiveUnsecure(boolean optimizeCurativeIfPreventiveUnsecure) {
this.optimizeCurativeIfPreventiveUnsecure = optimizeCurativeIfPreventiveUnsecure;
}

public static ObjectiveFunctionParameters load(PlatformConfig platformConfig) {
Objects.requireNonNull(platformConfig);
ObjectiveFunctionParameters parameters = new ObjectiveFunctionParameters();
Expand All @@ -117,6 +127,7 @@ public static ObjectiveFunctionParameters load(PlatformConfig platformConfig) {
DEFAULT_PREVENTIVE_STOP_CRITERION));
parameters.setCurativeStopCriterion(config.getEnumProperty(CURATIVE_STOP_CRITERION, CurativeStopCriterion.class,
DEFAULT_CURATIVE_STOP_CRITERION));
parameters.setOptimizeCurativeIfPreventiveUnsecure(config.getBooleanProperty(OPTIMIZE_CURATIVE_IF_PREVENTIVE_UNSECURE, DEFAULT_OPTIMIZE_CURATIVE_IF_PREVENTIVE_UNSECURE));
});
return parameters;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import java.util.List;
import java.util.Map;

import static com.powsybl.openrao.raoapi.RaoParametersCommons.RAO_PARAMETERS_VERSION;
import static org.junit.jupiter.api.Assertions.*;

/**
Expand All @@ -57,6 +58,7 @@ void roundTrip() throws IOException {
parameters.getObjectiveFunctionParameters().setPreventiveStopCriterion(ObjectiveFunctionParameters.PreventiveStopCriterion.MIN_OBJECTIVE);
parameters.getObjectiveFunctionParameters().setCurativeStopCriterion(ObjectiveFunctionParameters.CurativeStopCriterion.PREVENTIVE_OBJECTIVE_AND_SECURE);
parameters.getObjectiveFunctionParameters().setCurativeMinObjImprovement(983);
parameters.getObjectiveFunctionParameters().setOptimizeCurativeIfPreventiveUnsecure(true);
// RangeActionsOptimization parameters
parameters.getRangeActionsOptimizationParameters().setMaxMipIterations(30);
parameters.getRangeActionsOptimizationParameters().setPstPenaltyCost(10);
Expand Down Expand Up @@ -174,7 +176,7 @@ void readErrorUnexpectedExtension() {
void testFailOnOldVersion() {
InputStream inputStream = getClass().getResourceAsStream("/RaoParameters_oldVersion.json");
OpenRaoException e = assertThrows(OpenRaoException.class, () -> JsonRaoParameters.read(inputStream));
assertEquals("RaoParameters version '2.0' cannot be deserialized. The only supported version currently is '2.3'.", e.getMessage());
assertEquals(String.format("RaoParameters version '2.0' cannot be deserialized. The only supported version currently is '%s'.", RAO_PARAMETERS_VERSION), e.getMessage());
}

@ParameterizedTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ void checkObjectiveFunctionConfig() {
objectiveFunctionModuleConfig.setStringProperty("curative-min-obj-improvement", Objects.toString(123.0));
objectiveFunctionModuleConfig.setStringProperty("preventive-stop-criterion", "MIN_OBJECTIVE");
objectiveFunctionModuleConfig.setStringProperty("curative-stop-criterion", "PREVENTIVE_OBJECTIVE");
objectiveFunctionModuleConfig.setStringProperty("optimize-curative-if-preventive-unsecure", "true");

RaoParameters parameters = new RaoParameters();
RaoParameters.load(parameters, platformCfg);
Expand All @@ -58,6 +59,7 @@ void checkObjectiveFunctionConfig() {
assertEquals(123, objectiveFunctionParameters.getCurativeMinObjImprovement(), DOUBLE_TOLERANCE);
assertEquals(ObjectiveFunctionParameters.PreventiveStopCriterion.MIN_OBJECTIVE, objectiveFunctionParameters.getPreventiveStopCriterion());
assertEquals(ObjectiveFunctionParameters.CurativeStopCriterion.PREVENTIVE_OBJECTIVE, objectiveFunctionParameters.getCurativeStopCriterion());
assertTrue(objectiveFunctionParameters.getOptimizeCurativeIfPreventiveUnsecure());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ void testConfigWithoutExtensions() throws IOException {
assertEquals(3, objectiveFunctionParameters.getCurativeMinObjImprovement(), DOUBLE_TOLERANCE);
assertEquals(ObjectiveFunctionParameters.PreventiveStopCriterion.MIN_OBJECTIVE, objectiveFunctionParameters.getPreventiveStopCriterion());
assertEquals(ObjectiveFunctionParameters.CurativeStopCriterion.PREVENTIVE_OBJECTIVE, objectiveFunctionParameters.getCurativeStopCriterion());
assertTrue(objectiveFunctionParameters.getOptimizeCurativeIfPreventiveUnsecure());

RangeActionsOptimizationParameters rangeActionsOptimizationParameters = parameters.getRangeActionsOptimizationParameters();
assertEquals(2, rangeActionsOptimizationParameters.getMaxMipIterations(), DOUBLE_TOLERANCE);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"version" : "2.3",
"version" : "2.4",
"unknownField" : "abcd"
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"version" : "2.3",
"version" : "2.4",
"objective-function" : {
"type" : "MAX_MIN_MARGIN_IN_AMPERE",
"forbid-cost-increase" : true,
"preventive-stop-criterion" : "MIN_OBJECTIVE",
"curative-stop-criterion" : "PREVENTIVE_OBJECTIVE_AND_SECURE",
"curative-min-obj-improvement" : 983.0
"curative-min-obj-improvement" : 983.0,
"optimize-curative-if-preventive-unsecure" : true
},
"range-actions-optimization" : {
"max-mip-iterations" : 30,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version" : "2.3",
"version" : "2.4",
"objective-function" : {
"type" : "MAX_MIN_MARGIN_IN_MEGAWATT",
"forbid-cost-increase" : false,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"version" : "2.3",
"version" : "2.4",
"objective-function" : {
"type" : "MAX_MIN_MARGIN_IN_MEGAWATT",
"forbid-cost-increase" : false,
"preventive-stop-criterion" : "SECURE",
"curative-stop-criterion" : "MIN_OBJECTIVE",
"curative-min-obj-improvement" : 0.0
"curative-min-obj-improvement" : 0.0,
"optimize-curative-if-preventive-unsecure" : false
},
"range-actions-optimization" : {
"max-mip-iterations" : 10,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version" : "2.3",
"version" : "2.4",
"objective-function" : {
"type" : "MAX_MIN_MARGIN_IN_MEGAWATT",
"forbid-cost-increase" : false,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version" : "2.3",
"version" : "2.4",
"objective-function" : {
"type" : "MAX_MIN_MARGIN_IN_MEGAWATT",
"forbid-cost-increase" : false,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version" : "2.3",
"version" : "2.4",
"objective-function" : {
"type" : "MAX_MIN_MARGIN_IN_MEGAWATT",
"forbid-cost-increase" : false,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"version" : "2.3",
"version" : "2.4",
"objective-function" : {
"type" : "MAX_MIN_MARGIN_IN_AMPERE",
"forbid-cost-increase" : true,
"preventive-stop-criterion" : "MIN_OBJECTIVE",
"curative-stop-criterion" : "PREVENTIVE_OBJECTIVE",
"curative-min-obj-improvement" : 3.0
"curative-min-obj-improvement" : 3.0,
"optimize-curative-if-preventive-unsecure" : false
},
"range-actions-optimization" : {
"max-mip-iterations" : 2,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"version" : "2.3",
"version" : "2.4",
"objective-function" : {
"type" : "MAX_MIN_MARGIN_IN_MEGAWATT",
"forbid-cost-increase" : false,
"preventive-stop-criterion" : "SECURE",
"curative-stop-criterion" : "MIN_OBJECTIVE",
"curative-min-obj-improvement" : 0.0
"curative-min-obj-improvement" : 0.0,
"optimize-curative-if-preventive-unsecure" : false
},
"range-actions-optimization" : {
"max-mip-iterations" : 10,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"version" : "2.3",
"version" : "2.4",
"objective-function" : {
"type" : "MAX_MIN_MARGIN_IN_MEGAWATT",
"forbid-cost-increase" : true,
"preventive-stop-criterion" : "MIN_OBJECTIVE",
"curative-stop-criterion" : "PREVENTIVE_OBJECTIVE",
"curative-min-obj-improvement" : 3.0
"curative-min-obj-improvement" : 3.0,
"optimize-curative-if-preventive-unsecure" : false
},
"range-actions-optimization" : {
"max-mip-iterations" : 10,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"version" : "2.3",
"version" : "2.4",
"objective-function" : {
"type" : "MAX_MIN_MARGIN_IN_AMPERE",
"forbid-cost-increase" : true,
"preventive-stop-criterion" : "MIN_OBJECTIVE",
"curative-stop-criterion" : "PREVENTIVE_OBJECTIVE",
"curative-min-obj-improvement" : 3.0
"curative-min-obj-improvement" : 3.0,
"optimize-curative-if-preventive-unsecure" : true
},
"range-actions-optimization" : {
"max-mip-iterations" : 2,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version" : "2.3",
"version" : "2.4",
"objective-function" : {
"type" : "MAX_MIN_MARGIN_IN_MEGAWATT",
"preventive-stop-criterion" : "SECURE"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version" : "2.3",
"version" : "2.4",
"objective-function" : {
"type" : "MAX_MIN_MARGIN_IN_MEGAWATT",
"preventive-stop-criterion" : "MIN_OBJECTIVE"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"version" : "2.3",
"version" : "2.4",
"objective-function" : {
"type" : "MAX_MIN_MARGIN_IN_MEGAWATT",
"forbid-cost-increase" : false,
"preventive-stop-criterion" : "SECURE",
"curative-stop-criterion" : "MIN_OBJECTIVE",
"curative-min-obj-improvement" : 0.0
"curative-min-obj-improvement" : 0.0,
"optimize-curative-if-preventive-unsecure" : false
},
"range-actions-optimization" : {
"max-mip-iterations" : 10,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ rao-objective-function:
preventive-stop-criterion: MIN_OBJECTIVE
curative-stop-criterion: PREVENTIVE_OBJECTIVE
curative-min-obj-improvement: 3.0
optimize-curative-if-preventive-unsecure: true

rao-range-actions-optimization:
max-mip-iterations: 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ public CompletableFuture<RaoResult> run() {
// optimize contingency scenarios (auto + curative instants)

// If stop criterion is SECURE and preventive perimeter was not secure, do not run post-contingency RAOs
if (raoParameters.getObjectiveFunctionParameters().getPreventiveStopCriterion().equals(ObjectiveFunctionParameters.PreventiveStopCriterion.SECURE)
&& preventiveOptimalCost > 0) {
// (however RAO could continue depending on parameter optimize-curative-if-basecase-unsecure)
if (shouldStopOptimisationIfPreventiveUnsecure(preventiveOptimalCost)) {
BUSINESS_LOGS.info("Preventive perimeter could not be secured; there is no point in optimizing post-contingency perimeters. The RAO will be interrupted here.");
mergedRaoResults = new PreventiveAndCurativesRaoResultImpl(raoInput.getCrac().getPreventiveState(), initialOutput, preventiveResult, preCurativeSensitivityAnalysisOutput, raoInput.getCrac());
// log results
Expand Down Expand Up @@ -192,6 +192,12 @@ public CompletableFuture<RaoResult> run() {
return postCheckResults(mergedRaoResults, initialOutput, raoParameters.getObjectiveFunctionParameters());
}

private boolean shouldStopOptimisationIfPreventiveUnsecure(double preventiveOptimalCost) {
return raoParameters.getObjectiveFunctionParameters().getPreventiveStopCriterion().equals(ObjectiveFunctionParameters.PreventiveStopCriterion.SECURE)
&& preventiveOptimalCost > 0
&& !raoParameters.getObjectiveFunctionParameters().getOptimizeCurativeIfPreventiveUnsecure();
}

/**
* Return true if 2P has decreased cost
*/
Expand Down Expand Up @@ -446,6 +452,13 @@ static boolean shouldRunSecondPreventiveRao(RaoParameters raoParameters, Optimiz
// only compare initial cost with the curative costs
return false;
}
if (raoParameters.getObjectiveFunctionParameters().getPreventiveStopCriterion().equals(ObjectiveFunctionParameters.PreventiveStopCriterion.SECURE)
&& firstPreventiveResult.getCost() > 0) {
// in case of curative optimization even if preventive unsecure (see parameter optimize-curative-if-preventive-unsecure)
// we do not want to run a second preventive that would not be able to fix the situation, to save time
BUSINESS_LOGS.info("First preventive RAO was not able to fix all preventive constraints, second preventive RAO cancelled to save computation time.");
return false;
}
ObjectiveFunctionParameters.CurativeStopCriterion curativeStopCriterion = raoParameters.getObjectiveFunctionParameters().getCurativeStopCriterion();
switch (curativeStopCriterion) {
case MIN_OBJECTIVE:
Expand Down
Loading

0 comments on commit 904887f

Please sign in to comment.