Skip to content

Commit

Permalink
Logs range actions activated (#734)
Browse files Browse the repository at this point in the history
* filter out pst with unmodified taps

* include ra names and taps in summary + disabled RaoLoggerTest

* remove unused import

* add virtual cost detail in sensi

* add info everywhere but with ugly method

* add method to not duplicate code

* checkstyle + some tests fixed

* remove method and include it in leaf.toString()

* fix toString() method and test

* add tests to cover new behavior

* fix several code smells

* add logRangeAction tests

* try to remove sonar bug

* merge master

---------

Co-authored-by: PHILIPPE EDWARDS <philippe.edwards@rte-france.com>
Co-authored-by: demontmorillongod <godelaine.demontmorillon@rte-france.com>
  • Loading branch information
3 people authored Mar 22, 2023
1 parent aa98b44 commit f0e0e58
Show file tree
Hide file tree
Showing 8 changed files with 235 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ AutomatonPerimeterResultImpl simulateAutomatonState(State automatonState, State
automatonState);
failedAutomatonPerimeterResultImpl.setComputationStatus(ComputationStatus.FAILURE);
TECHNICAL_LOGS.info("Automaton state {} has failed during sensitivity computation during range automaton simulation.", automatonState.getId());
RaoLogger.logFailedOptimizationSummary(BUSINESS_LOGS, automatonState, failedAutomatonPerimeterResultImpl.getActivatedNetworkActions().size(), failedAutomatonPerimeterResultImpl.getActivatedRangeActions(automatonState).size());
RaoLogger.logFailedOptimizationSummary(BUSINESS_LOGS, automatonState, failedAutomatonPerimeterResultImpl.getActivatedNetworkActions(), getRangeActionsAndTheirTapsAppliedOnState(failedAutomatonPerimeterResultImpl, automatonState));
return failedAutomatonPerimeterResultImpl;
}
// Build and return optimization result
Expand All @@ -131,7 +131,7 @@ AutomatonPerimeterResultImpl simulateAutomatonState(State automatonState, State
rangeAutomatonSimulationResult.getRangeActionsWithSetpoint(),
automatonState);
TECHNICAL_LOGS.info("Automaton state {} has been optimized.", automatonState.getId());
RaoLogger.logOptimizationSummary(BUSINESS_LOGS, automatonState, automatonPerimeterResultImpl.getActivatedNetworkActions().size(), automatonPerimeterResultImpl.getActivatedRangeActions(automatonState).size(), null, null, automatonPerimeterResultImpl);
RaoLogger.logOptimizationSummary(BUSINESS_LOGS, automatonState, automatonPerimeterResultImpl.getActivatedNetworkActions(), getRangeActionsAndTheirTapsAppliedOnState(automatonPerimeterResultImpl, automatonState), null, automatonPerimeterResultImpl);
return automatonPerimeterResultImpl;
}

Expand All @@ -144,6 +144,14 @@ private PrePerimeterSensitivityAnalysis getPreAutoPerimeterSensitivityAnalysis(S
return new PrePerimeterSensitivityAnalysis(flowCnecsInSensi, rangeActionsInSensi, raoParameters, toolProvider);
}

public static Map<RangeAction<?>, Double> getRangeActionsAndTheirTapsAppliedOnState(OptimizationResult optimizationResult, State state) {
Set< RangeAction<?>> setActivatedRangeActions = optimizationResult.getActivatedRangeActions(state);
Map<RangeAction<?>, Double> allRangeActions = new HashMap<>();
setActivatedRangeActions.stream().filter(PstRangeAction.class::isInstance).map(PstRangeAction.class::cast).forEach(pstRangeAction -> allRangeActions.put(pstRangeAction, (double) optimizationResult.getOptimizedTap(pstRangeAction, state)));
setActivatedRangeActions.stream().filter(ra -> !(ra instanceof PstRangeAction)).forEach(rangeAction -> allRangeActions.put(rangeAction, optimizationResult.getOptimizedSetpoint(rangeAction, state)));
return allRangeActions;
}

AutomatonPerimeterResultImpl createFailedAutomatonPerimeterResult(State autoState, PrePerimeterResult result, Set<NetworkAction> activatedNetworkActions, String defineMoment) {
AutomatonPerimeterResultImpl failedAutomatonPerimeterResultImpl = new AutomatonPerimeterResultImpl(
result,
Expand All @@ -153,7 +161,7 @@ AutomatonPerimeterResultImpl createFailedAutomatonPerimeterResult(State autoStat
autoState);
failedAutomatonPerimeterResultImpl.setComputationStatus(ComputationStatus.FAILURE);
TECHNICAL_LOGS.info("Automaton state {} has failed during sensitivity computation {} topological automaton simulation.", autoState.getId(), defineMoment);
RaoLogger.logFailedOptimizationSummary(BUSINESS_LOGS, autoState, failedAutomatonPerimeterResultImpl.getActivatedNetworkActions().size(), failedAutomatonPerimeterResultImpl.getActivatedRangeActions(autoState).size());
RaoLogger.logFailedOptimizationSummary(BUSINESS_LOGS, autoState, failedAutomatonPerimeterResultImpl.getActivatedNetworkActions(), getRangeActionsAndTheirTapsAppliedOnState(failedAutomatonPerimeterResultImpl, autoState));
return failedAutomatonPerimeterResultImpl;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
import com.farao_community.farao.commons.Unit;
import com.farao_community.farao.commons.logs.FaraoLogger;
import com.farao_community.farao.data.crac_api.Contingency;
import com.farao_community.farao.data.crac_api.Identifiable;
import com.farao_community.farao.data.crac_api.State;
import com.farao_community.farao.data.crac_api.cnec.FlowCnec;
import com.farao_community.farao.data.crac_api.cnec.Side;
import com.farao_community.farao.data.crac_api.network_action.NetworkAction;
import com.farao_community.farao.data.crac_api.range_action.PstRangeAction;
import com.farao_community.farao.data.crac_api.range_action.RangeAction;
import com.farao_community.farao.data.rao_result_api.OptimizationState;
import com.farao_community.farao.rao_api.parameters.ObjectiveFunctionParameters;
import com.farao_community.farao.rao_api.parameters.RaoParameters;
Expand All @@ -24,8 +27,10 @@
import com.farao_community.farao.search_tree_rao.castor.algorithm.BasecaseScenario;
import com.farao_community.farao.search_tree_rao.castor.algorithm.ContingencyScenario;
import com.farao_community.farao.search_tree_rao.search_tree.algorithms.Leaf;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.farao_community.farao.commons.logs.FaraoLoggerProvider.BUSINESS_LOGS;
Expand Down Expand Up @@ -56,43 +61,35 @@ public static void logSensitivityAnalysisResults(String prefix,
formatDouble(prePerimeterObjectiveFunctionResult.getCost()),
formatDouble(prePerimeterObjectiveFunctionResult.getFunctionalCost()),
formatDouble(prePerimeterObjectiveFunctionResult.getVirtualCost()));
Map<String, Double> virtualCosts = getVirtualCostDetailed(prePerimeterObjectiveFunctionResult);

RaoLogger.logMostLimitingElementsResults(BUSINESS_LOGS,
sensitivityAnalysisResult,
raoParameters.getObjectiveFunctionParameters().getType(),
numberOfLoggedLimitingElements);
}

public static void logRangeActions(FaraoLogger logger,
Leaf leaf,
OptimizationPerimeter optimizationContext) {
logRangeActions(logger, leaf, optimizationContext, null);
}

public static void logRangeActions(FaraoLogger logger,
Leaf leaf,
OptimizationPerimeter
optimizationContext, String prefix) {

boolean globalPstOptimization = optimizationContext instanceof GlobalOptimizationPerimeter;

String rangeActionSetpoints = optimizationContext.getRangeActionsPerState().entrySet().stream()
.flatMap(eState -> eState.getValue().stream().map(rangeAction -> {
double rangeActionValue;
if (rangeAction instanceof PstRangeAction) {
rangeActionValue = leaf.getOptimizedTap((PstRangeAction) rangeAction, eState.getKey());
} else {
rangeActionValue = leaf.getOptimizedSetpoint(rangeAction, eState.getKey());
}
if (globalPstOptimization) {
return format("%s@%s: %.0f", rangeAction.getName(), eState.getKey().getId(), rangeActionValue);
} else {
return format("%s: %.0f", rangeAction.getName(), rangeActionValue);
}
}))
.collect(Collectors.joining(", "));

logger.info("{}range action(s): {}", prefix == null ? "" : prefix, rangeActionSetpoints);
List<String> rangeActionSetpoints = optimizationContext.getRangeActionOptimizationStates().stream().flatMap(state ->
leaf.getActivatedRangeActions(state).stream().map(rangeAction -> {
double rangeActionValue = rangeAction instanceof PstRangeAction ? leaf.getOptimizedTap((PstRangeAction) rangeAction, state) :
leaf.getOptimizedSetpoint(rangeAction, state);
return globalPstOptimization ? format("%s@%s: %.0f", rangeAction.getName(), state.getId(), rangeActionValue) :
format("%s: %.0f", rangeAction.getName(), rangeActionValue);
})).collect(Collectors.toList());

boolean isRangeActionSetPointEmpty = rangeActionSetpoints.isEmpty();
if (isRangeActionSetPointEmpty) {
logger.info("{}No range actions activated", prefix == null ? "" : prefix);
} else {
logger.info("{}range action(s): {}", prefix == null ? "" : prefix, String.join(", ", rangeActionSetpoints));
}
}

public static void logMostLimitingElementsResults(FaraoLogger logger, OptimizationResult optimizationResult, ObjectiveFunctionParameters.ObjectiveFunctionType objectiveFunction, int numberOfLoggedElements) {
Expand Down Expand Up @@ -249,40 +246,55 @@ private static Map<FlowCnec, Double> getMostLimitingElementsAndMargins(Optimizat
return mostLimitingElementsAndMargins;
}

public static void logOptimizationSummary(FaraoLogger logger, State optimizedState, long activatedNetworkActions, long activatedRangeActions, Double initialFunctionalCost, Double initialVirtualCost, ObjectiveFunctionResult finalObjective) {
Optional<Contingency> optionalContingency = optimizedState.getContingency();
String scenarioName = optionalContingency.isEmpty() ? "preventive" : optionalContingency.get().getName();
String raResult = "";
if (activatedNetworkActions + activatedRangeActions == 0) {
raResult = "no remedial actions activated";
} else if (activatedNetworkActions > 0 && activatedRangeActions == 0) {
raResult = String.format("%s network action(s) activated", activatedNetworkActions);
} else if (activatedRangeActions > 0 && activatedNetworkActions == 0) {
raResult = String.format("%s range action(s) activated", activatedRangeActions);
public static void logFailedOptimizationSummary(FaraoLogger logger, State optimizedState, Set<NetworkAction> networkActions, Map<RangeAction<?>, java.lang.Double> rangeActions) {
String scenarioName = getScenarioName(optimizedState);
String raResult = getRaResult(networkActions, rangeActions);
logger.info("Scenario \"{}\": {}", scenarioName, raResult);
}

public static void logOptimizationSummary(FaraoLogger logger, State optimizedState, Set<NetworkAction> networkActions, Map<RangeAction<?>, java.lang.Double> rangeActions, ObjectiveFunctionResult preOptimObjectiveFunctionResult, ObjectiveFunctionResult finalObjective) {
String scenarioName = getScenarioName(optimizedState);
String raResult = getRaResult(networkActions, rangeActions);
Map<String, Double> finalVirtualCostDetailed = getVirtualCostDetailed(finalObjective);
String initialCostString;
if (preOptimObjectiveFunctionResult == null) {
initialCostString = "";
} else {
raResult = String.format("%s network action(s) and %s range action(s) activated", activatedNetworkActions, activatedRangeActions);
Map<String, Double> initialVirtualCostDetailed = getVirtualCostDetailed(preOptimObjectiveFunctionResult);
if (initialVirtualCostDetailed.isEmpty()) {
initialCostString = String.format("initial cost = %s (functional: %s, virtual: %s), ", formatDouble(preOptimObjectiveFunctionResult.getFunctionalCost() + preOptimObjectiveFunctionResult.getVirtualCost()), formatDouble(preOptimObjectiveFunctionResult.getFunctionalCost()), formatDouble(preOptimObjectiveFunctionResult.getVirtualCost()));
} else {
initialCostString = String.format("initial cost = %s (functional: %s, virtual: %s %s), ", formatDouble(preOptimObjectiveFunctionResult.getFunctionalCost() + preOptimObjectiveFunctionResult.getVirtualCost()), formatDouble(preOptimObjectiveFunctionResult.getFunctionalCost()), formatDouble(preOptimObjectiveFunctionResult.getVirtualCost()), initialVirtualCostDetailed);
}
}
String initialCostString = initialFunctionalCost == null || initialVirtualCost == null ? "" :
String.format("initial cost = %s (functional: %s, virtual: %s), ", formatDouble(initialFunctionalCost + initialVirtualCost), formatDouble(initialFunctionalCost), formatDouble(initialVirtualCost));

logger.info("Scenario \"{}\": {}{}, cost {} = {} (functional: {}, virtual: {})", scenarioName, initialCostString, raResult, OptimizationState.afterOptimizing(optimizedState),
formatDouble(finalObjective.getCost()), formatDouble(finalObjective.getFunctionalCost()), formatDouble(finalObjective.getVirtualCost()));
logger.info("Scenario \"{}\": {}{}, cost {} = {} (functional: {}, virtual: {}{})", scenarioName, initialCostString, raResult, OptimizationState.afterOptimizing(optimizedState),
formatDouble(finalObjective.getCost()), formatDouble(finalObjective.getFunctionalCost()), formatDouble(finalObjective.getVirtualCost()), finalVirtualCostDetailed.isEmpty() ? "" : " " + finalVirtualCostDetailed);
}

public static void logFailedOptimizationSummary(FaraoLogger logger, State optimizedState, long activatedNetworkActions, long activatedRangeActions) {
Optional<Contingency> optionalContingency = optimizedState.getContingency();
String scenarioName = optionalContingency.isEmpty() ? "preventive" : optionalContingency.get().getName();
String raResult = "";
public static String getRaResult(Set<NetworkAction> networkActions, Map<RangeAction<?>, java.lang.Double> rangeActions) {
long activatedNetworkActions = networkActions.size();
long activatedRangeActions = rangeActions.size();
String networkActionsNames = StringUtils.join(networkActions.stream().map(Identifiable::getName).collect(Collectors.toSet()), ", ");

Set<String> rangeActionsSet = new HashSet<>();
rangeActions.forEach((key, value) -> rangeActionsSet.add(format("%s: %.0f", key.getName(), value)));
String rangeActionsNames = StringUtils.join(rangeActionsSet, ", ");

if (activatedNetworkActions + activatedRangeActions == 0) {
raResult = "no remedial actions activated";
return "no remedial actions activated";
} else if (activatedNetworkActions > 0 && activatedRangeActions == 0) {
raResult = String.format("%s network action(s) activated", activatedNetworkActions);
return String.format("%s network action(s) activated : %s", activatedNetworkActions, networkActionsNames);
} else if (activatedRangeActions > 0 && activatedNetworkActions == 0) {
raResult = String.format("%s range action(s) activated", activatedRangeActions);
return String.format("%s range action(s) activated : %s", activatedRangeActions, rangeActionsNames);
} else {
raResult = String.format("%s network action(s) and %s range action(s) activated", activatedNetworkActions, activatedRangeActions);
return String.format("%s network action(s) and %s range action(s) activated : %s and %s",
activatedNetworkActions, activatedRangeActions, networkActionsNames, rangeActionsNames);
}
logger.info("Scenario \"{}\": {}", scenarioName, raResult);
}

public static String getScenarioName(State state) {
Optional<Contingency> optionalContingency = state.getContingency();
return optionalContingency.isEmpty() ? "preventive" : optionalContingency.get().getName();
}

public static String formatDouble(double value) {
Expand All @@ -294,4 +306,15 @@ public static String formatDouble(double value) {
return String.format(Locale.ENGLISH, "%.2f", value);
}
}

/**
* For a given virtual-cost-name, if its associated virtual cost is positive, this method will return a map containing
* these information to be used in the Rao logs
*/
public static Map<String, Double> getVirtualCostDetailed(ObjectiveFunctionResult objectiveFunctionResult) {
return objectiveFunctionResult.getVirtualCostNames().stream()
.filter(virtualCostName -> objectiveFunctionResult.getVirtualCost(virtualCostName) > 1e-6)
.collect(Collectors.toMap(Function.identity(),
name -> Math.round(objectiveFunctionResult.getVirtualCost(name) * 100.0) / 100.0));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ public Pair<Double, List<FlowCnec>> getVirtualCostAndCostlyElements(FlowResult
return getVirtualCostAndCostlyElements(flowResult, rangeActionActivationResult, sensitivityResult, sensitivityStatus, virtualCostName, new HashSet<>());
}

public Pair<Double, List<FlowCnec>> getVirtualCostAndCostlyElements(FlowResult flowResult, RangeActionActivationResult rangeActionActivationResult, SensitivityResult sensitivityResult, ComputationStatus sensitivityStatus, String virtualCostName, Set<String> contingenciesToExlude) {
public Pair<Double, List<FlowCnec>> getVirtualCostAndCostlyElements(FlowResult flowResult, RangeActionActivationResult rangeActionActivationResult, SensitivityResult sensitivityResult, ComputationStatus sensitivityStatus, String virtualCostName, Set<String> contingenciesToExclude) {
return virtualCostEvaluators.stream()
.filter(costEvaluator -> costEvaluator.getName().equals(virtualCostName))
.findAny()
.map(costEvaluator -> costEvaluator.computeCostAndLimitingElements(flowResult, rangeActionActivationResult, sensitivityResult, sensitivityStatus, contingenciesToExlude))
.map(costEvaluator -> costEvaluator.computeCostAndLimitingElements(flowResult, rangeActionActivationResult, sensitivityResult, sensitivityStatus, contingenciesToExclude))
.orElse(Pair.of(Double.NaN, new ArrayList<>()));
}

Expand Down
Loading

0 comments on commit f0e0e58

Please sign in to comment.