Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add possibility to optimize curative perimeter if preventive perimeter is unsecure and preventive stop criterion is SECURE #988

Merged
merged 3 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading