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

Inter-Temporal Skeleton (MARMOT) #1258

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
/*
* Copyright (c) 2022, 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.marmot;

import com.powsybl.openrao.commons.TemporalData;
import com.powsybl.openrao.data.crac.api.State;
import com.powsybl.openrao.data.crac.api.rangeaction.PstRangeAction;
import com.powsybl.openrao.data.crac.api.rangeaction.RangeAction;
import com.powsybl.openrao.data.intertemporalconstraint.PowerGradient;
import com.powsybl.openrao.raoapi.parameters.RangeActionsOptimizationParameters;
import com.powsybl.openrao.searchtreerao.commons.optimizationperimeters.CurativeOptimizationPerimeter;
import com.powsybl.openrao.searchtreerao.linearoptimisation.algorithms.fillers.*;
import com.powsybl.openrao.searchtreerao.linearoptimisation.algorithms.linearproblem.LinearProblem;
import com.powsybl.openrao.searchtreerao.linearoptimisation.inputs.IteratingLinearOptimizerInput;
import com.powsybl.openrao.searchtreerao.linearoptimisation.parameters.IteratingLinearOptimizerParameters;
import com.powsybl.openrao.searchtreerao.result.api.RangeActionActivationResult;

import java.time.temporal.Temporal;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author Baptiste Seguinot {@literal <baptiste.seguinot at rte-france.com>}
*/
public class IntertemporalLinearProblemBuilder {
private final List<ProblemFiller> problemFillers = new ArrayList<>();
private RangeActionsOptimizationParameters.Solver solver;
private double relativeMipGap = RangeActionsOptimizationParameters.LinearOptimizationSolver.DEFAULT_RELATIVE_MIP_GAP;
private String solverSpecificParameters = RangeActionsOptimizationParameters.LinearOptimizationSolver.DEFAULT_SOLVER_SPECIFIC_PARAMETERS;
private RangeActionActivationResult initialRangeActionActivationResult;
private IteratingLinearOptimizerInput inputs;
private IteratingLinearOptimizerParameters parameters;

public LinearProblem buildFromInputsAndParameters(TemporalData<IteratingLinearOptimizerInput> inputs, Set<PowerGradient> powerGradients, IteratingLinearOptimizerParameters parameters) {
Objects.requireNonNull(inputs);
Objects.requireNonNull(parameters);
this.inputs = inputs;
this.parameters = parameters;

this.withSolver(parameters.getSolverParameters().getSolver())
.withRelativeMipGap(parameters.getSolverParameters().getRelativeMipGap())
.withSolverSpecificParameters(parameters.getSolverParameters().getSolverSpecificParameters());

// Iterate on inputs : for each :
// For the following 2 points, try making a default method usable for non intertemporal
// -- Build core filler
// -- Build non intertemporal other fillers if necessary
// Add intertemporal fillers :
// - gradients
// - virtual : sum of minMargins
// TODO : do not handle for the moment
// (- virtual : min of minMargins in all timestamps)
// (- min margin optimization : use only min of min margins in objective)

// max.min margin, or max.min relative margin
if (parameters.getObjectiveFunction().relativePositiveMargins()) {
this.withProblemFiller(buildMaxMinRelativeMarginFiller());
} else {
this.withProblemFiller(buildMaxMinMarginFiller());
}

// MNEC
if (parameters.isRaoWithMnecLimitation()) {
this.withProblemFiller(buildMnecFiller());
}

// loop-flow limitation
if (parameters.isRaoWithLoopFlowLimitation()) {
this.withProblemFiller(buildLoopFlowFiller());
}

// unoptimized CNECs for TSOs without curative RA
if (!Objects.isNull(parameters.getUnoptimizedCnecParameters())
&& !Objects.isNull(parameters.getUnoptimizedCnecParameters().getOperatorsNotToOptimize())
&& inputs.optimizationPerimeter() instanceof CurativeOptimizationPerimeter) {
this.withProblemFiller(buildUnoptimizedCnecFiller());
}

// MIP optimization vs. CONTINUOUS optimization
if (parameters.getRangeActionParameters().getPstModel().equals(RangeActionsOptimizationParameters.PstModel.APPROXIMATED_INTEGERS)) {
Map<State, Set<PstRangeAction>> pstRangeActions = copyOnlyPstRangeActions(inputs.optimizationPerimeter().getRangeActionsPerState());
Map<State, Set<RangeAction<?>>> otherRa = copyWithoutPstRangeActions(inputs.optimizationPerimeter().getRangeActionsPerState());
this.withProblemFiller(buildIntegerPstTapFiller(pstRangeActions));
this.withProblemFiller(buildDiscretePstGroupFiller(pstRangeActions));
this.withProblemFiller(buildContinuousRangeActionGroupFiller(otherRa));
} else {
this.withProblemFiller(buildContinuousRangeActionGroupFiller(inputs.optimizationPerimeter().getRangeActionsPerState()));
}

// RA limitation
if (parameters.getRaLimitationParameters() != null
&& inputs.optimizationPerimeter().getRangeActionOptimizationStates().stream()
.anyMatch(state -> parameters.getRaLimitationParameters().areRangeActionLimitedForState(state))) {
this.withProblemFiller(buildRaUsageLimitsFiller());
}

return new LinearProblem(problemFillers, initialRangeActionActivationResult, solver, relativeMipGap, solverSpecificParameters);
}

public LinearProblem build() {
return new LinearProblem(problemFillers, initialRangeActionActivationResult, solver, relativeMipGap, solverSpecificParameters);
}

public IntertemporalLinearProblemBuilder withProblemFiller(ProblemFiller problemFiller) {
problemFillers.add(problemFiller);
return this;
}

public IntertemporalLinearProblemBuilder withSolver(RangeActionsOptimizationParameters.Solver solver) {
this.solver = solver;
return this;
}

public IntertemporalLinearProblemBuilder withRelativeMipGap(double relativeMipGap) {
this.relativeMipGap = relativeMipGap;
return this;
}

public IntertemporalLinearProblemBuilder withSolverSpecificParameters(String solverSpecificParameters) {
this.solverSpecificParameters = solverSpecificParameters;
return this;
}

public IntertemporalLinearProblemBuilder withInitialRangeActionActivationResult(RangeActionActivationResult rangeActionActivationResult) {
this.initialRangeActionActivationResult = rangeActionActivationResult;
return this;
}

private ProblemFiller buildCoreProblemFiller() {
return parameters.getObjectiveFunction().costOptimization() ? new CostCoreProblemFiller(
inputs.optimizationPerimeter(),
inputs.prePerimeterSetpoints(),
parameters.getRangeActionParameters(),
parameters.getObjectiveFunctionUnit(),
parameters.getRaRangeShrinking(),
parameters.getRangeActionParameters().getPstModel(),
null
) : new MarginCoreProblemFiller(
inputs.optimizationPerimeter(),
inputs.prePerimeterSetpoints(),
parameters.getRangeActionParameters(),
parameters.getObjectiveFunctionUnit(),
parameters.getRaRangeShrinking(),
parameters.getRangeActionParameters().getPstModel(),
null
);
}

private ProblemFiller buildMaxMinRelativeMarginFiller() {
return new MaxMinRelativeMarginFiller(
inputs.optimizationPerimeter().getOptimizedFlowCnecs(),
inputs.preOptimizationFlowResult(),
parameters.getObjectiveFunction().getUnit(),
parameters.getMaxMinRelativeMarginParameters(),
null);
}

private ProblemFiller buildMaxMinMarginFiller() {
return new MaxMinMarginFiller(
inputs.optimizationPerimeter().getOptimizedFlowCnecs(),
parameters.getObjectiveFunctionUnit(),
parameters.getObjectiveFunction().costOptimization(),
null);
}

private ProblemFiller buildMnecFiller() {
return new MnecFiller(
inputs.initialFlowResult(),
inputs.optimizationPerimeter().getMonitoredFlowCnecs(),
parameters.getObjectiveFunctionUnit(),
parameters.getMnecParameters(),
null);
}

private ProblemFiller buildLoopFlowFiller() {
return new MaxLoopFlowFiller(
inputs.optimizationPerimeter().getLoopFlowCnecs(),
inputs.initialFlowResult(),
parameters.getLoopFlowParameters(),
null);
}

private ProblemFiller buildUnoptimizedCnecFiller() {
return new UnoptimizedCnecFiller(
inputs.optimizationPerimeter().getFlowCnecs(),
inputs.prePerimeterFlowResult(),
parameters.getUnoptimizedCnecParameters(),
null
);
}

private ProblemFiller buildIntegerPstTapFiller(Map<State, Set<PstRangeAction>> pstRangeActions) {
return new DiscretePstTapFiller(
inputs.optimizationPerimeter(),
pstRangeActions,
inputs.prePerimeterSetpoints(),
parameters.getRangeActionParameters(),
parameters.getObjectiveFunction().costOptimization(),
null
);
}

private ProblemFiller buildDiscretePstGroupFiller(Map<State, Set<PstRangeAction>> pstRangeActions) {
return new DiscretePstGroupFiller(
inputs.optimizationPerimeter().getMainOptimizationState(),
pstRangeActions,
null);
}

private ProblemFiller buildContinuousRangeActionGroupFiller(Map<State, Set<RangeAction<?>>> rangeActionsPerState) {
return new ContinuousRangeActionGroupFiller(rangeActionsPerState, null);
}

private ProblemFiller buildRaUsageLimitsFiller() {
return new RaUsageLimitsFiller(
inputs.optimizationPerimeter().getRangeActionsPerState(),
inputs.prePerimeterSetpoints(),
parameters.getRaLimitationParameters(),
parameters.getRangeActionParameters().getPstModel() == RangeActionsOptimizationParameters.PstModel.APPROXIMATED_INTEGERS,
inputs.network(), parameters.getObjectiveFunction().costOptimization(), null);
}

private Map<State, Set<RangeAction<?>>> copyWithoutPstRangeActions(Map<State, Set<RangeAction<?>>> inRangeActions) {
Map<State, Set<RangeAction<?>>> outRangeActions = new HashMap<>();
inRangeActions.forEach((state, rangeActions) -> {
if (rangeActions.stream().anyMatch(ra -> !(ra instanceof PstRangeAction))) {
outRangeActions.put(state, rangeActions.stream().filter(ra -> !(ra instanceof PstRangeAction)).collect(Collectors.toCollection(
() -> new TreeSet<>(Comparator.comparing(RangeAction::getId))
)));
}
});
return outRangeActions;
}

private Map<State, Set<PstRangeAction>> copyOnlyPstRangeActions(Map<State, Set<RangeAction<?>>> inRangeActions) {
Map<State, Set<PstRangeAction>> outRangeActions = new TreeMap<>(Comparator.comparing(State::getId));
inRangeActions.forEach((state, rangeActions) -> {
if (rangeActions.stream().anyMatch(PstRangeAction.class::isInstance)) {
outRangeActions.put(state, rangeActions.stream().filter(PstRangeAction.class::isInstance).map(PstRangeAction.class::cast).collect(Collectors.toCollection(
() -> new TreeSet<>(Comparator.comparing(PstRangeAction::getId))
)));
}
});
return outRangeActions;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.powsybl.openrao.searchtreerao.marmot;

import com.powsybl.iidm.network.TwoSides;
import com.powsybl.openrao.commons.TemporalData;
import com.powsybl.openrao.commons.Unit;
import com.powsybl.openrao.data.crac.api.Instant;
import com.powsybl.openrao.data.crac.api.State;
import com.powsybl.openrao.data.crac.api.cnec.FlowCnec;
import com.powsybl.openrao.data.crac.api.rangeaction.RangeAction;
import com.powsybl.openrao.data.raoresult.api.ComputationStatus;
import com.powsybl.openrao.searchtreerao.result.api.FlowResult;
import com.powsybl.openrao.searchtreerao.result.api.PrePerimeterResult;
import com.powsybl.openrao.searchtreerao.result.api.SensitivityResult;
import com.powsybl.sensitivity.SensitivityVariableSet;

import java.util.Map;
import java.util.Set;

public class IntertemporalSensitivityResult implements SensitivityResult, FlowResult {
private TemporalData<PrePerimeterResult> systematicSensitivityResults;

public IntertemporalSensitivityResult(TemporalData<PrePerimeterResult> systematicSensitivityResults) {
this.systematicSensitivityResults = systematicSensitivityResults;
}

@Override
public ComputationStatus getSensitivityStatus() { return null;
}

@Override
public ComputationStatus getSensitivityStatus(State state) {
return null;
}

@Override
public Set<String> getContingencies() {
return null;
}

@Override
public double getSensitivityValue(FlowCnec flowCnec, TwoSides side, RangeAction<?> rangeAction, Unit unit) {
return 0;
}

@Override
public double getSensitivityValue(FlowCnec flowCnec, TwoSides side, SensitivityVariableSet linearGlsk, Unit unit) {
return 0;
}

@Override
public double getFlow(FlowCnec flowCnec, TwoSides side, Unit unit) {
return 0;
}

@Override
public double getFlow(FlowCnec flowCnec, TwoSides side, Unit unit, Instant optimizedInstant) {
return 0;
}

@Override
public double getMargin(FlowCnec flowCnec, Unit unit) {
return 0;
}

@Override
public double getCommercialFlow(FlowCnec flowCnec, TwoSides side, Unit unit) {
return 0;
}

@Override
public double getPtdfZonalSum(FlowCnec flowCnec, TwoSides side) {
return 0;
}

@Override
public Map<FlowCnec, Map<TwoSides, Double>> getPtdfZonalSums() {
return null;
}

@Override
public ComputationStatus getComputationStatus() {
return null;
}

@Override
public ComputationStatus getComputationStatus(State state) {
return null;
}
}
Loading
Loading