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

Use upward and downward variation variables in MILP for Range Actions #1205

Merged
merged 6 commits into from
Dec 6, 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
28 changes: 16 additions & 12 deletions docs/castor/linear-problem/core-problem-filler.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@

## Defined optimization variables

| Name | Symbol | Details | Type | Index | Unit | Lower bound | Upper bound |
|--------------------------------|-----------------|-------------------------------------------------------------------------------------------------------------------|---------------------|--------------------------------------------------|-----------------------------------------------------------|-----------------------|-----------------------|
| Flow | $F(c)$ | flow of FlowCnec $c$ | Real value | One variable for every element of (FlowCnecs) | MW | $-\infty$ | $+\infty$ |
| RA setpoint | $A(r,s)$ | setpoint of RangeAction $r$ on state $s$ | Real value | One variable for every element of (RangeActions) | Degrees for PST range actions; MW for other range actions | Range lower bound[^2] | Range upper bound[^2] |
| RA setpoint absolute variation | $\Delta A(r,s)$ | The absolute setpoint variation of RangeAction $r$ on state $s$, from setpoint on previous state to "RA setpoint" | Real positive value | One variable for every element of (RangeActions) | Degrees for PST range actions; MW for other range actions | 0 | $+\infty$ |
| Name | Symbol | Details | Type | Index | Unit | Lower bound | Upper bound |
|---------------------------------|-------------------|-----------------------------------------------------------------------------------------------------------------------|---------------------|--------------------------------------------------|-----------------------------------------------------------|-----------------------|-----------------------|
| Flow | $F(c)$ | flow of FlowCnec $c$ | Real value | One variable for every element of (FlowCnecs) | MW | $-\infty$ | $+\infty$ |
| RA set-point | $A(r,s)$ | set-point of RangeAction $r$ on state $s$ | Real value | One variable for every element of (RangeActions) | Degrees for PST range actions; MW for other range actions | Range lower bound[^2] | Range upper bound[^2] |
| RA set-point absolute variation | $\Delta A(r,s)$ | The absolute set-point variation of RangeAction $r$ on state $s$, from setpoint on previous state to "RA setpoint" | Real positive value | One variable for every element of (RangeActions) | Degrees for PST range actions; MW for other range actions | 0 | $+\infty$ |
| RA upward set-point variation | $\Delta^{+}(r,s)$ | The upward set-point variation of RangeAction $r$ on state $s$, from set-point on previous state to "RA set-point" | Real positive value | One variable for every element of (RangeActions) | Degrees for PST range actions; MW for other range actions | 0 | $+\infty$ |
| RA downward set-point variation | $\Delta^{-}(r,s)$ | The downward set-point variation of RangeAction $r$ on state $s$, from set-point on previous state to "RA set-point" | Real positive value | One variable for every element of (RangeActions) | Degrees for PST range actions; MW for other range actions | 0 | $+\infty$ |

[^2]: Range actions' lower & upper bounds are computed using CRAC + network + previous RAO results, depending on the
types of their ranges: ABSOLUTE, RELATIVE_TO_INITIAL_NETWORK, RELATIVE_TO_PREVIOUS_INSTANT (more
Expand All @@ -54,13 +56,7 @@ with $s$ the state on $c$ which is evaluated

$$
\begin{equation}
\Delta A(r,s) \geq A(r,s) - A(r,s') , \forall (r,s) \in \mathcal{RA}
\end{equation}
$$

$$
\begin{equation}
\Delta A(r,s) \geq - A(r,s) + A(r,s') , \forall (r,s) \in \mathcal{RA}
A(r,s) = A(r,s') + \Delta^{+}(r,s) - \Delta^{-}(r,s) , \forall (r,s) \in \mathcal{RA}
\end{equation}
$$

Expand All @@ -77,6 +73,14 @@ When converting them in angle, we take the smallest angle step between two tap c
Despite artificially tightening the bounds, this is the only way to ensure we respect the tap limits as the tap to angle map is non linear.
With PST modeled as APPROXIMATED_INTEGERS, we can directly use the taps and therefore avoid this approximation.

### Definition of the absolute variations of the RangeActions

$$
\begin{equation}
\Delta A(r,s) = \Delta^{+}(r,s) + \Delta^{-}(r,s) , \forall (r,s) \in \mathcal{RA}
\end{equation}
$$

### Shrinking the allowed range

If parameter [ra-range-shrinking](/parameters.md#ra-range-shrinking) is enabled, the allowed range for range actions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ private void buildRangeActionVariables(LinearProblem linearProblem) {
rangeActions.forEach(rangeAction -> {
linearProblem.addRangeActionSetpointVariable(-linearProblem.infinity(), linearProblem.infinity(), rangeAction, state);
linearProblem.addAbsoluteRangeActionVariationVariable(0, linearProblem.infinity(), rangeAction, state);
linearProblem.addRangeActionVariationVariable(linearProblem.infinity(), rangeAction, state, LinearProblem.VariationDirectionExtension.UPWARD);
linearProblem.addRangeActionVariationVariable(linearProblem.infinity(), rangeAction, state, LinearProblem.VariationDirectionExtension.DOWNWARD);
})
);
}
Expand Down Expand Up @@ -236,28 +238,26 @@ private static void updateConstraintsForRangeAction(LinearProblem linearProblem,
}

/**
* Build two range action constraints for each RangeAction r.
* These constraints link the set point variable of the RangeAction with its absolute
* variation variable.
* AV[r] >= S[r] - initialSetPoint[r] (NEGATIVE)
* AV[r] >= initialSetPoint[r] - S[r] (POSITIVE)
* Build range action constraints for each RangeAction r.
* These constraints link the set-point variable of the RangeAction with its
* variation variables, and bounds the set-point in an admissible range.
* S[r] = initialSetPoint[r] + upwardVariation[r] - downwardVariation[r]
*/
private void buildConstraintsForRangeActionAndState(LinearProblem linearProblem, RangeAction<?> rangeAction, State state) {
OpenRaoMPVariable setPointVariable = linearProblem.getRangeActionSetpointVariable(rangeAction, state);
OpenRaoMPVariable absoluteVariationVariable = linearProblem.getAbsoluteRangeActionVariationVariable(rangeAction, state);
OpenRaoMPConstraint varConstraintNegative = linearProblem.addAbsoluteRangeActionVariationConstraint(
-linearProblem.infinity(),
linearProblem.infinity(),
rangeAction,
state,
LinearProblem.AbsExtension.NEGATIVE
);
OpenRaoMPConstraint varConstraintPositive = linearProblem.addAbsoluteRangeActionVariationConstraint(
-linearProblem.infinity(),
linearProblem.infinity(),
rangeAction,
state,
LinearProblem.AbsExtension.POSITIVE);
OpenRaoMPVariable upwardVariationVariable = linearProblem.getRangeActionVariationVariable(rangeAction, state, LinearProblem.VariationDirectionExtension.UPWARD);
OpenRaoMPVariable downwardVariationVariable = linearProblem.getRangeActionVariationVariable(rangeAction, state, LinearProblem.VariationDirectionExtension.DOWNWARD);

OpenRaoMPConstraint absoluteVariationConstraint = linearProblem.addRangeActionAbsoluteVariationConstraint(rangeAction, state);
absoluteVariationConstraint.setCoefficient(absoluteVariationVariable, 1.0);
absoluteVariationConstraint.setCoefficient(upwardVariationVariable, -1.0);
absoluteVariationConstraint.setCoefficient(downwardVariationVariable, -1.0);

OpenRaoMPConstraint setPointVariationConstraint = linearProblem.addRangeActionSetPointVariationConstraint(rangeAction, state);
setPointVariationConstraint.setCoefficient(setPointVariable, 1.0);
setPointVariationConstraint.setCoefficient(upwardVariationVariable, -1.0);
setPointVariationConstraint.setCoefficient(downwardVariationVariable, 1.0);

Pair<RangeAction<?>, State> lastAvailableRangeAction = RaoUtil.getLastAvailableRangeActionOnSameNetworkElement(optimizationContext, rangeAction, state);

Expand All @@ -273,13 +273,8 @@ private void buildConstraintsForRangeActionAndState(LinearProblem linearProblem,
setPointVariable.setLb(minSetPoint - RANGE_ACTION_SETPOINT_EPSILON);
setPointVariable.setUb(maxSetPoint + RANGE_ACTION_SETPOINT_EPSILON);

varConstraintNegative.setLb(-prePerimeterSetPoint);
varConstraintNegative.setCoefficient(absoluteVariationVariable, 1);
varConstraintNegative.setCoefficient(setPointVariable, -1);

varConstraintPositive.setLb(prePerimeterSetPoint);
varConstraintPositive.setCoefficient(absoluteVariationVariable, 1);
varConstraintPositive.setCoefficient(setPointVariable, 1);
setPointVariationConstraint.setLb(prePerimeterSetPoint);
setPointVariationConstraint.setUb(prePerimeterSetPoint);
} else {

// range action have been activated in a previous instant
Expand All @@ -303,16 +298,7 @@ private void buildConstraintsForRangeActionAndState(LinearProblem linearProblem,
setPointVariable.setLb(minAbsoluteSetpoint - RANGE_ACTION_SETPOINT_EPSILON);
setPointVariable.setUb(maxAbsoluteSetpoint + RANGE_ACTION_SETPOINT_EPSILON);

// define absolute range action variation
varConstraintNegative.setLb(0);
varConstraintNegative.setCoefficient(absoluteVariationVariable, 1);
varConstraintNegative.setCoefficient(setPointVariable, -1);
varConstraintNegative.setCoefficient(previousSetpointVariable, 1);

varConstraintPositive.setLb(0);
varConstraintPositive.setCoefficient(absoluteVariationVariable, 1);
varConstraintPositive.setCoefficient(setPointVariable, 1);
varConstraintPositive.setCoefficient(previousSetpointVariable, -1);
setPointVariationConstraint.setCoefficient(previousSetpointVariable, -1.0);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,14 +267,6 @@ public OpenRaoMPVariable getAbsoluteRangeActionVariationVariable(RangeAction<?>
return solver.getVariable(absoluteRangeActionVariationVariableId(rangeAction, state));
}

public OpenRaoMPConstraint addAbsoluteRangeActionVariationConstraint(double lb, double ub, RangeAction<?> rangeAction, State state, AbsExtension positiveOrNegative) {
return solver.makeConstraint(lb, ub, absoluteRangeActionVariationConstraintId(rangeAction, state, positiveOrNegative));
}

public OpenRaoMPConstraint getAbsoluteRangeActionVariationConstraint(RangeAction<?> rangeAction, State state, AbsExtension positiveOrNegative) {
return solver.getConstraint(absoluteRangeActionVariationConstraintId(rangeAction, state, positiveOrNegative));
}

public OpenRaoMPConstraint addMinimumMarginConstraint(double lb, double ub, FlowCnec cnec, TwoSides side, MarginExtension belowOrAboveThreshold) {
return solver.makeConstraint(lb, ub, minimumMarginConstraintId(cnec, side, belowOrAboveThreshold));
}
Expand Down Expand Up @@ -452,6 +444,30 @@ public OpenRaoMPConstraint getTsoMaxElementaryActionsConstraint(String operator,
return solver.getConstraint(maxElementaryActionsPerTsoConstraintId(operator, state));
}

public OpenRaoMPVariable addRangeActionVariationVariable(double ub, RangeAction<?> rangeAction, State state, VariationDirectionExtension variationDirection) {
return solver.makeNumVar(0.0, ub, rangeActionVariationVariableId(rangeAction, state, variationDirection));
}

public OpenRaoMPVariable getRangeActionVariationVariable(RangeAction<?> rangeAction, State state, VariationDirectionExtension variationDirection) {
return solver.getVariable(rangeActionVariationVariableId(rangeAction, state, variationDirection));
}

public OpenRaoMPConstraint addRangeActionSetPointVariationConstraint(RangeAction<?> rangeAction, State state) {
return solver.makeConstraint(0.0, 0.0, rangeActionSetPointVariationConstraintId(rangeAction, state));
}

public OpenRaoMPConstraint getRangeActionSetPointVariationConstraint(RangeAction<?> rangeAction, State state) {
return solver.getConstraint(rangeActionSetPointVariationConstraintId(rangeAction, state));
}

public OpenRaoMPConstraint addRangeActionAbsoluteVariationConstraint(RangeAction<?> rangeAction, State state) {
return solver.makeConstraint(0.0, 0.0, rangeActionAbsoluteVariationConstraintId(rangeAction, state));
}

public OpenRaoMPConstraint getRangeActionAbsoluteVariationConstraint(RangeAction<?> rangeAction, State state) {
return solver.getConstraint(rangeActionAbsoluteVariationConstraintId(rangeAction, state));
}

public double infinity() {
return solver.infinity();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ public final class LinearProblemIdGenerator {
private static final String TSO_RA_USED = "tsoraused";
private static final String PST_ABSOLUTE_VARIATION_FROM_INITIAL_TAP = "pstabsolutevariationfrominitialtap";
private static final String MAX_ELEMENTARY_ACTIONS_PER_TSO = "maxelementaryactionspertso";
private static final String RANGE_ACTION_VARIATION = "rangeactionvariation";
private static final String RANGE_ACTION_ACTIVATION = "rangeactionactivation";
private static final String RANGE_ACTION_SET_POINT_VARIATION = "rangeactionsetpointvariation";
private static final String RANGE_ACTION_ABSOLUTE_VARIATION = "rangeactionabsolutevariation";

private LinearProblemIdGenerator() {
// Should not be instantiated
Expand Down Expand Up @@ -125,10 +129,6 @@ public static String absoluteRangeActionVariationVariableId(RangeAction<?> range
return rangeAction.getId() + SEPARATOR + state.getId() + SEPARATOR + ABSOLUTE_VARIATION + SEPARATOR + VARIABLE_SUFFIX;
}

public static String absoluteRangeActionVariationConstraintId(RangeAction<?> rangeAction, State state, LinearProblem.AbsExtension positiveOrNegative) {
return rangeAction.getId() + SEPARATOR + state.getId() + SEPARATOR + ABSOLUTE_VARIATION + positiveOrNegative.toString().toLowerCase() + SEPARATOR + CONSTRAINT_SUFFIX;
}

public static String minimumMarginConstraintId(FlowCnec flowCnec, TwoSides side, LinearProblem.MarginExtension belowOrAboveThreshold) {
return String.join(SEPARATOR, flowCnec.getId(), side.toString().toLowerCase(), MIN_MARGIN, belowOrAboveThreshold.toString().toLowerCase(), CONSTRAINT_SUFFIX);
}
Expand Down Expand Up @@ -216,4 +216,16 @@ public static String pstAbsoluteVariationFromInitialTapConstraintId(PstRangeActi
public static String maxElementaryActionsPerTsoConstraintId(String operator, State state) {
return MAX_ELEMENTARY_ACTIONS_PER_TSO + SEPARATOR + operator + SEPARATOR + state.getId() + SEPARATOR + CONSTRAINT_SUFFIX;
}

public static String rangeActionVariationVariableId(RangeAction<?> rangeAction, State state, LinearProblem.VariationDirectionExtension variationDirection) {
return RANGE_ACTION_VARIATION + SEPARATOR + rangeAction.getId() + SEPARATOR + state.getId() + SEPARATOR + VARIABLE_SUFFIX + SEPARATOR + variationDirection;
}

public static String rangeActionSetPointVariationConstraintId(RangeAction<?> rangeAction, State state) {
return RANGE_ACTION_SET_POINT_VARIATION + SEPARATOR + rangeAction.getId() + SEPARATOR + state.getId() + SEPARATOR + CONSTRAINT_SUFFIX;
}

public static String rangeActionAbsoluteVariationConstraintId(RangeAction<?> rangeAction, State state) {
return RANGE_ACTION_ABSOLUTE_VARIATION + SEPARATOR + rangeAction.getId() + SEPARATOR + state.getId() + SEPARATOR + CONSTRAINT_SUFFIX;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,20 +100,6 @@ void rangeActionAbsoluteVariationVariableTest() {
assertEquals(UB, linearProblem.getAbsoluteRangeActionVariationVariable(rangeAction, state).ub(), DOUBLE_TOLERANCE);
}

@Test
void rangeActionAbsoluteVariationConstraintTest() {
Exception e = assertThrows(OpenRaoException.class, () -> linearProblem.getAbsoluteRangeActionVariationConstraint(rangeAction, state, LinearProblem.AbsExtension.NEGATIVE));
assertEquals("Constraint rangeaction_id_null_absolutevariationnegative_constraint has not been created yet", e.getMessage());
e = assertThrows(OpenRaoException.class, () -> linearProblem.getAbsoluteRangeActionVariationConstraint(rangeAction, state, LinearProblem.AbsExtension.POSITIVE));
assertEquals("Constraint rangeaction_id_null_absolutevariationpositive_constraint has not been created yet", e.getMessage());
linearProblem.addAbsoluteRangeActionVariationConstraint(LB, UB, rangeAction, state, LinearProblem.AbsExtension.NEGATIVE);
linearProblem.addAbsoluteRangeActionVariationConstraint(LB, UB, rangeAction, state, LinearProblem.AbsExtension.POSITIVE);
assertNotNull(linearProblem.getAbsoluteRangeActionVariationConstraint(rangeAction, state, LinearProblem.AbsExtension.NEGATIVE));
assertNotNull(linearProblem.getAbsoluteRangeActionVariationConstraint(rangeAction, state, LinearProblem.AbsExtension.POSITIVE));
assertEquals(LB, linearProblem.getAbsoluteRangeActionVariationConstraint(rangeAction, state, LinearProblem.AbsExtension.NEGATIVE).lb(), DOUBLE_TOLERANCE);
assertEquals(UB, linearProblem.getAbsoluteRangeActionVariationConstraint(rangeAction, state, LinearProblem.AbsExtension.POSITIVE).ub(), DOUBLE_TOLERANCE);
}

@Test
void pstTapVariationIntegerAndBinaryVariablesTest() {
Exception e = assertThrows(OpenRaoException.class, () -> linearProblem.getPstTapVariationVariable(rangeAction, state, UPWARD));
Expand Down
Loading
Loading