Skip to content

Commit

Permalink
Experiment/objective function result (#1199)
Browse files Browse the repository at this point in the history
* simplify objective function

Signed-off-by: Thomas Bouquet <[email protected]>

* define cost evaluator results

Signed-off-by: Thomas Bouquet <[email protected]>

* split modules

Signed-off-by: Thomas Bouquet <[email protected]>

* remove useless method

Signed-off-by: Thomas Bouquet <[email protected]>

* refactor evaluator results

Signed-off-by: Thomas Bouquet <[email protected]>

* refactor evaluators based on ranking of cnecs

Signed-off-by: Thomas Bouquet <[email protected]>

* linter

Signed-off-by: Thomas Bouquet <[email protected]>

* fix sensi test mocks

Signed-off-by: Thomas Bouquet <[email protected]>

---------

Signed-off-by: Thomas Bouquet <[email protected]>
  • Loading branch information
bqth29 committed Nov 26, 2024
1 parent 6638d98 commit 845d838
Show file tree
Hide file tree
Showing 42 changed files with 638 additions and 353 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import com.powsybl.openrao.searchtreerao.commons.RaoUtil;
import com.powsybl.openrao.searchtreerao.commons.ToolProvider;
import com.powsybl.openrao.searchtreerao.commons.objectivefunction.ObjectiveFunction;
import com.powsybl.openrao.searchtreerao.commons.objectivefunction.ObjectiveFunctionResultImpl;
import com.powsybl.openrao.searchtreerao.commons.optimizationperimeters.AutoOptimizationPerimeter;
import com.powsybl.openrao.searchtreerao.commons.optimizationperimeters.OptimizationPerimeter;
import com.powsybl.openrao.searchtreerao.commons.parameters.TreeParameters;
Expand Down Expand Up @@ -150,7 +149,7 @@ AutomatonPerimeterResultImpl simulateAutomatonState(State automatonState, Set<St
}
// Build and return optimization result
RemedialActionActivationResult remedialActionActivationResult = buildRemedialActionActivationResult(topoSimulationResult, autoSearchTreeResult, rangeAutomatonSimulationResult, automatonState);
PrePerimeterResult prePerimeterResultForOptimizedState = buildPrePerimeterResultForOptimizedState(rangeAutomatonSimulationResult.perimeterResult(), automatonState, remedialActionActivationResult);
PrePerimeterResult prePerimeterResultForOptimizedState = buildPrePerimeterResultForOptimizedState(rangeAutomatonSimulationResult, automatonState, remedialActionActivationResult);
Map<RangeAction<?>, Double> rangeActionsWithSetpoint = rangeAutomatonSimulationResult.rangeActionsWithSetpoint();
prePerimeterResultForOptimizedState.getRangeActionSetpointResult().getRangeActions().forEach(ra -> rangeActionsWithSetpoint.putIfAbsent(ra, prePerimeterResultForOptimizedState.getSetpoint(ra)));
AutomatonPerimeterResultImpl automatonPerimeterResultImpl = new AutomatonPerimeterResultImpl(
Expand Down Expand Up @@ -281,7 +280,8 @@ TopoAutomatonSimulationResult simulateTopologicalAutomatons(State automatonState
*/
record RangeAutomatonSimulationResult(PrePerimeterResult perimeterResult, Set<RangeAction<?>> activatedRangeActions,
Map<RangeAction<?>, Double> rangeActionsWithInitialSetpoint,
Map<RangeAction<?>, Double> rangeActionsWithSetpoint) {
Map<RangeAction<?>, Double> rangeActionsWithSetpoint
) {
}

RangeAutomatonSimulationResult simulateRangeAutomatons(State automatonState, Set<State> curativeStates, Network network, PrePerimeterSensitivityAnalysis preAutoPerimeterSensitivityAnalysis, PrePerimeterResult postAutoTopoResult) {
Expand Down Expand Up @@ -771,17 +771,17 @@ static Double roundUpAngleToTapWrtInitialSetpoint(PstRangeAction rangeAction, do
return rangeAction.getTapToAngleConversionMap().get(rangeAction.convertAngleToTap(angleToBeRounded));
}

private PrePerimeterResult buildPrePerimeterResultForOptimizedState(PrePerimeterResult postAutoResult, State optimizedState, RemedialActionActivationResult remedialActionActivationResult) {
private PrePerimeterResult buildPrePerimeterResultForOptimizedState(RangeAutomatonSimulationResult rangeAutomatonSimulationResult, State optimizedState, RemedialActionActivationResult remedialActionActivationResult) {
// Gather variables necessary for PrePerimeterResult construction
PrePerimeterResult postAutoResult = rangeAutomatonSimulationResult.perimeterResult();
FlowResult flowResult = postAutoResult.getFlowResult();
SensitivityResult sensitivityResult = postAutoResult.getSensitivityResult();
RangeActionSetpointResult rangeActionSetpointResult = postAutoResult.getRangeActionSetpointResult();
// Gather flowCnecs defined on optimizedState
Set<FlowCnec> cnecsForOptimizedState = postAutoResult.getObjectiveFunction().getFlowCnecs().stream()
.filter(flowCnec -> flowCnec.getState().equals(optimizedState)).collect(Collectors.toSet());
Set<FlowCnec> cnecsForOptimizedState = crac.getFlowCnecs(optimizedState);
// Build ObjectiveFunctionResult based on cnecsForOptimizedState
ObjectiveFunction objectiveFunction = ObjectiveFunction.build(cnecsForOptimizedState, toolProvider.getLoopFlowCnecs(cnecsForOptimizedState), initialFlowResult, prePerimeterSensitivityOutput, operatorsNotSharingCras, raoParameters, Set.of(optimizedState));
ObjectiveFunctionResult objectiveFunctionResult = new ObjectiveFunctionResultImpl(objectiveFunction, flowResult, remedialActionActivationResult);
ObjectiveFunctionResult objectiveFunctionResult = objectiveFunction.evaluate(flowResult, remedialActionActivationResult);
return new PrePerimeterSensitivityResultImpl(flowResult, sensitivityResult, rangeActionSetpointResult, objectiveFunctionResult);

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

package com.powsybl.openrao.searchtreerao.commons;

import com.powsybl.contingency.Contingency;
import com.powsybl.openrao.commons.Unit;
import com.powsybl.openrao.data.cracapi.cnec.Cnec;
import com.powsybl.openrao.data.cracapi.cnec.FlowCnec;
Expand All @@ -18,7 +17,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

/**
Expand All @@ -29,19 +27,13 @@ public final class FlowCnecSorting {
private FlowCnecSorting() {
}

public static List<FlowCnec> sortByMargin(Set<FlowCnec> flowCnecs, Unit unit, MarginEvaluator marginEvaluator, FlowResult flowResult, Set<String> contingenciesToExclude) {
public static List<FlowCnec> sortByMargin(Set<FlowCnec> flowCnecs, Unit unit, MarginEvaluator marginEvaluator, FlowResult flowResult) {
Map<FlowCnec, Double> margins = new HashMap<>();

flowCnecs.stream()
.filter(flowCnec -> mustFilterCnecBasedOnContingency(flowCnec, contingenciesToExclude))
.filter(Cnec::isOptimized)
.forEach(flowCnec -> margins.put(flowCnec, marginEvaluator.getMargin(flowResult, flowCnec, unit)));

return margins.keySet().stream().sorted(Comparator.comparing(margins::get)).toList();
}

public static boolean mustFilterCnecBasedOnContingency(FlowCnec flowCnec, Set<String> contingenciesToExclude) {
Optional<Contingency> contingency = flowCnec.getState().getContingency();
return contingency.isEmpty() || !contingenciesToExclude.contains(contingency.get().getId());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2024, 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.commons.costevaluatorresult;

import com.powsybl.openrao.data.cracapi.cnec.FlowCnec;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
* @author Thomas Bouquet {@literal <thomas.bouquet at rte-france.com>}
*/
public class AbsoluteCostEvaluatorResult implements CostEvaluatorResult {
private final double cost;

public AbsoluteCostEvaluatorResult(double cost) {
this.cost = cost;
}

@Override
public double getCost(Set<String> contingenciesToExclude) {
return cost;
}

@Override
public List<FlowCnec> getCostlyElements(Set<String> contingenciesToExclude) {
return new ArrayList<>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2024, 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.commons.costevaluatorresult;

import com.powsybl.contingency.Contingency;
import com.powsybl.openrao.data.cracapi.State;
import com.powsybl.openrao.data.cracapi.cnec.FlowCnec;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.DoubleStream;

/**
* @author Thomas Bouquet {@literal <thomas.bouquet at rte-france.com>}
*/
public abstract class AbstractStateWiseCostEvaluatorResult implements CostEvaluatorResult {
private final Map<State, Double> costPerState;
private final List<FlowCnec> costlyElements;

protected AbstractStateWiseCostEvaluatorResult(Map<State, Double> costPerState, List<FlowCnec> costlyElements) {
this.costPerState = costPerState;
this.costlyElements = costlyElements;
}

private DoubleStream filterCostsOnContingency(Set<String> contingenciesToExclude) {
return costPerState.entrySet().stream().filter(entry -> filterStateOnContingency(entry.getKey(), contingenciesToExclude)).mapToDouble(Map.Entry::getValue);
}

@Override
public double getCost(Set<String> contingenciesToExclude) {
return evaluateResultsWithSpecificStrategy(filterCostsOnContingency(contingenciesToExclude));
}

protected abstract double evaluateResultsWithSpecificStrategy(DoubleStream filteredCostsStream);

@Override
public List<FlowCnec> getCostlyElements(Set<String> contingenciesToExclude) {
return costlyElements.stream().filter(flowCnec -> filterFlowCnecOnContingency(flowCnec, contingenciesToExclude)).toList();
}

private static boolean filterStateOnContingency(State state, Set<String> contingenciesToExclude) {
Optional<Contingency> contingency = state.getContingency();
return contingency.isEmpty() || !contingenciesToExclude.contains(contingency.get().getId());
}

private static boolean filterFlowCnecOnContingency(FlowCnec flowCnec, Set<String> contingenciesToExclude) {
return filterStateOnContingency(flowCnec.getState(), contingenciesToExclude);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

package com.powsybl.openrao.searchtreerao.commons.objectivefunctionevaluator;
package com.powsybl.openrao.searchtreerao.commons.costevaluatorresult;

import com.powsybl.openrao.data.cracapi.cnec.FlowCnec;
import com.powsybl.openrao.searchtreerao.result.api.FlowResult;

import java.util.List;
import java.util.Set;

/**
* @author Thomas Bouquet {@literal <thomas.bouquet at rte-france.com>}
*/
public interface CnecViolationCostEvaluator extends CostEvaluator {
List<FlowCnec> getElementsInViolation(FlowResult flowResult, Set<String> contingenciesToExclude);
public interface CostEvaluatorResult {
double getCost(Set<String> contingenciesToExclude);

List<FlowCnec> getCostlyElements(Set<String> contingenciesToExclude);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2024, 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.commons.costevaluatorresult;

import com.powsybl.openrao.data.cracapi.State;
import com.powsybl.openrao.data.cracapi.cnec.FlowCnec;

import java.util.List;
import java.util.Map;
import java.util.stream.DoubleStream;

/**
* @author Thomas Bouquet {@literal <thomas.bouquet at rte-france.com>}
*/
public class MaxCostEvaluatorResult extends AbstractStateWiseCostEvaluatorResult {
public MaxCostEvaluatorResult(Map<State, Double> costPerState, List<FlowCnec> costlyElements) {
super(costPerState, costlyElements);
}

@Override
protected double evaluateResultsWithSpecificStrategy(DoubleStream filteredCostsStream) {
return filteredCostsStream.max().orElse(-Double.MAX_VALUE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2024, 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.commons.costevaluatorresult;

import com.powsybl.openrao.data.cracapi.State;
import com.powsybl.openrao.data.cracapi.cnec.FlowCnec;

import java.util.List;
import java.util.Map;
import java.util.stream.DoubleStream;

/**
* @author Thomas Bouquet {@literal <thomas.bouquet at rte-france.com>}
*/
public class SumCostEvaluatorResult extends AbstractStateWiseCostEvaluatorResult {
public SumCostEvaluatorResult(Map<State, Double> costPerState, List<FlowCnec> costlyElements) {
super(costPerState, costlyElements);
}

@Override
protected double evaluateResultsWithSpecificStrategy(DoubleStream filteredCostsStream) {
return filteredCostsStream.sum();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@
import com.powsybl.openrao.raoapi.parameters.RaoParameters;
import com.powsybl.openrao.searchtreerao.commons.FlowCnecSorting;
import com.powsybl.openrao.searchtreerao.commons.marginevaluator.MarginEvaluator;
import com.powsybl.openrao.searchtreerao.commons.objectivefunctionevaluator.CnecViolationCostEvaluator;
import com.powsybl.openrao.searchtreerao.commons.objectivefunctionevaluator.CostEvaluator;
import com.powsybl.openrao.searchtreerao.result.api.*;
import org.apache.commons.lang3.tuple.Pair;

import java.util.*;
import java.util.stream.Collectors;
Expand All @@ -42,37 +40,16 @@ public final class ObjectiveFunction {
}

public ObjectiveFunctionResult evaluate(FlowResult flowResult, RemedialActionActivationResult remedialActionActivationResult) {
return new ObjectiveFunctionResultImpl(this, flowResult, remedialActionActivationResult);
}

public Set<FlowCnec> getFlowCnecs() {
return flowCnecs;
}

public Pair<Double, List<FlowCnec>> getFunctionalCostAndLimitingElements(FlowResult flowResult, RemedialActionActivationResult remedialActionActivationResult) {
return getFunctionalCostAndLimitingElements(flowResult, remedialActionActivationResult, Set.of());
}

public Pair<Double, List<FlowCnec>> getFunctionalCostAndLimitingElements(FlowResult flowResult, RemedialActionActivationResult remedialActionActivationResult, Set<String> contingenciesToExclude) {
return Pair.of(functionalCostEvaluator.evaluate(flowResult, remedialActionActivationResult, contingenciesToExclude), FlowCnecSorting.sortByMargin(flowCnecs, unit, marginEvaluator, flowResult, contingenciesToExclude));
return new ObjectiveFunctionResultImpl(
functionalCostEvaluator.evaluate(flowResult, remedialActionActivationResult),
virtualCostEvaluators.stream().collect(Collectors.toMap(CostEvaluator::getName, virtualCost -> virtualCost.evaluate(flowResult, remedialActionActivationResult))),
FlowCnecSorting.sortByMargin(flowCnecs, unit, marginEvaluator, flowResult));
}

public Set<String> getVirtualCostNames() {
return virtualCostEvaluators.stream().map(CostEvaluator::getName).collect(Collectors.toSet());
}

public Pair<Double, List<FlowCnec>> getVirtualCostAndCostlyElements(FlowResult flowResult, RemedialActionActivationResult remedialActionActivationResult, String virtualCostName, Set<String> contingenciesToExclude) {
return virtualCostEvaluators.stream()
.filter(costEvaluator -> costEvaluator.getName().equals(virtualCostName))
.findAny()
.map(costEvaluator -> Pair.of(costEvaluator.evaluate(flowResult, remedialActionActivationResult, contingenciesToExclude), getVirtualCostCostlyElements(costEvaluator, flowResult, contingenciesToExclude)))
.orElse(Pair.of(Double.NaN, new ArrayList<>()));
}

private static List<FlowCnec> getVirtualCostCostlyElements(CostEvaluator virtualCostEvaluator, FlowResult flowResult, Set<String> contingenciesToExclude) {
return virtualCostEvaluator instanceof CnecViolationCostEvaluator violationCostEvaluator ? violationCostEvaluator.getElementsInViolation(flowResult, contingenciesToExclude) : new ArrayList<>();
}

public static ObjectiveFunction buildForInitialSensitivityComputation(Set<FlowCnec> flowCnecs, RaoParameters raoParameters, Set<State> optimizedStates) {
return new InitialSensitivityAnalysisObjectiveFunctionCreator(flowCnecs, optimizedStates, raoParameters).create();
}
Expand Down
Loading

0 comments on commit 845d838

Please sign in to comment.