com.powsybl.openrao.searchtreerao.searchtree.algorithms.SearchTreeBloomer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of open-rao-search-tree-rao Show documentation
Show all versions of open-rao-search-tree-rao Show documentation
Implementation of search tree remedial action optimisation with modular approach
The newest version!
/*
* Copyright (c) 2021, 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.searchtree.algorithms;
import com.powsybl.openrao.data.crac.api.RaUsageLimits;
import com.powsybl.openrao.data.crac.api.RemedialAction;
import com.powsybl.openrao.data.crac.api.State;
import com.powsybl.openrao.data.crac.api.networkaction.NetworkAction;
import com.powsybl.openrao.data.crac.api.rangeaction.PstRangeAction;
import com.powsybl.openrao.data.crac.api.rangeaction.RangeAction;
import com.powsybl.openrao.searchtreerao.commons.NetworkActionCombination;
import com.powsybl.openrao.searchtreerao.result.api.OptimizationResult;
import com.powsybl.openrao.searchtreerao.searchtree.inputs.SearchTreeInput;
import com.powsybl.openrao.searchtreerao.searchtree.parameters.SearchTreeParameters;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Joris Mancini {@literal }
*/
public final class SearchTreeBloomer {
private final List preDefinedNaCombinations;
private final List networkActionCombinationFilters;
private final SearchTreeInput input;
private final SearchTreeParameters parameters;
public SearchTreeBloomer(SearchTreeInput input, SearchTreeParameters parameters) {
RaUsageLimits raUsageLimits = parameters.getRaLimitationParameters().getOrDefault(input.getOptimizationPerimeter().getMainOptimizationState().getInstant(), new RaUsageLimits());
this.preDefinedNaCombinations = parameters.getNetworkActionParameters().getNetworkActionCombinations();
this.networkActionCombinationFilters = List.of(
new AlreadyAppliedNetworkActionsFilter(),
new AlreadyTestedCombinationsFilter(preDefinedNaCombinations),
new MaximumNumberOfRemedialActionsFilter(raUsageLimits.getMaxRa()),
new MaximumNumberOfRemedialActionPerTsoFilter(raUsageLimits.getMaxTopoPerTso(), raUsageLimits.getMaxRaPerTso()),
new MaximumNumberOfTsosFilter(raUsageLimits.getMaxTso()),
new FarFromMostLimitingElementFilter(input.getNetwork(), parameters.getNetworkActionParameters().skipNetworkActionFarFromMostLimitingElements(), parameters.getNetworkActionParameters().getMaxNumberOfBoundariesForSkippingNetworkActions()),
new ElementaryActionsCompatibilityFilter(),
new MaximumNumberOfElementaryActionsFilter(raUsageLimits.getMaxElementaryActionsPerTso())
);
this.input = input;
this.parameters = parameters;
}
/**
* This method generates a Set of NetworkActionCombinations.
* The networkActionCombinations generated would be available after this leaf inside the tree.
* They are either individual NetworkAction as defined in the Crac, or predefined
* combinations of NetworkActions, defined in the SearchTreeRaoParameters and considered as being efficient when
* activated together.
* The bloom method ensures that the returned NetworkActionCombinations respect the following rules:
*
* - they do not exceed the maximum number of usable remedial actions
* - they do not exceed the maximum number of usable remedial actions (PST & topo) per operator
* - they do not exceed the maximum number of operators
* - they are not too far away from the most limiting CNEC
*
*/
Set bloom(Leaf fromLeaf, Set networkActions) {
// preDefined combinations
Set networkActionCombinations = preDefinedNaCombinations.stream()
.distinct()
.filter(naCombination -> networkActions.containsAll(naCombination.getNetworkActionSet()))
.collect(Collectors.toSet());
// + individual available Network Actions
final List finalNetworkActionCombinations = new ArrayList<>(networkActionCombinations);
Set effectivelyFinalNACombinations = networkActionCombinations;
networkActions.stream()
.filter(na ->
finalNetworkActionCombinations.stream().noneMatch(naCombi -> naCombi.getNetworkActionSet().size() == 1 && naCombi.getNetworkActionSet().contains(na))
)
.forEach(ra -> effectivelyFinalNACombinations.add(new NetworkActionCombination(Set.of(ra))));
networkActionCombinations.addAll(effectivelyFinalNACombinations);
// filters
for (NetworkActionCombinationFilter networkActionCombinationFilter : networkActionCombinationFilters) {
networkActionCombinations = networkActionCombinationFilter.filter(networkActionCombinations, fromLeaf);
}
return networkActionCombinations;
}
/**
* This method checks if range action must be removed before applying a network action combination.
* If so, parentLeafRangeActions must be removed before applying the combination.
* Otherwise, it can be applied while keeping them.
* Such a check is performed by analyzing RaUsageLimits for the given state.
*/
boolean shouldRangeActionsBeRemovedToApplyNa(NetworkActionCombination naCombination, OptimizationResult optimizationResult) {
State optimizationState = input.getOptimizationPerimeter().getMainOptimizationState();
RaUsageLimits raUsageLimits = parameters.getRaLimitationParameters().get(optimizationState.getInstant());
if (Objects.isNull(raUsageLimits)) {
return false;
}
// maxRa
int naCombinationSize = naCombination.getNetworkActionSet().size();
Set alreadyActivatedNetworkActions = optimizationResult.getActivatedNetworkActions();
Set> alreadyActivatedRangeActions = optimizationResult.getActivatedRangeActions(optimizationState);
if (alreadyActivatedNetworkActions.size() + alreadyActivatedRangeActions.size() + naCombinationSize > raUsageLimits.getMaxRa()) {
return true;
}
// maxTso
Set operators = naCombination.getOperators();
Set activatedTsos = alreadyActivatedNetworkActions.stream().map(RemedialAction::getOperator).filter(Objects::nonNull).collect(Collectors.toSet());
alreadyActivatedRangeActions.stream().map(RemedialAction::getOperator).filter(Objects::nonNull).forEach(activatedTsos::add);
activatedTsos.addAll(operators);
if (activatedTsos.size() > raUsageLimits.getMaxTso()) {
return true;
}
// maxRaPerTso
for (String tso : operators) {
int numberOfAlreadyActivatedRangeActionsForTso = (int) alreadyActivatedRangeActions.stream().filter(ra -> tso.equals(ra.getOperator())).count();
int numberOfAlreadyAppliedNetworkActionsForTso = (int) alreadyActivatedNetworkActions.stream().filter(na -> tso.equals(na.getOperator())).count();
if (numberOfAlreadyAppliedNetworkActionsForTso + numberOfAlreadyActivatedRangeActionsForTso + naCombinationSize > raUsageLimits.getMaxRaPerTso().getOrDefault(tso, Integer.MAX_VALUE)) {
return true;
}
}
// maxElementaryActionPerTso
Map movedPstTapsPerTso = getNumberOfPstTapsMovedByTso(optimizationResult);
for (String tso : raUsageLimits.getMaxElementaryActionsPerTso().keySet()) {
int elementaryActions = 0;
Set tsosNetworkActions = naCombination.getNetworkActionSet().stream().filter(networkAction -> tso.equals(networkAction.getOperator())).collect(Collectors.toSet());
for (NetworkAction networkAction : tsosNetworkActions) {
// TODO: what if some network actions share common elementary action?
elementaryActions = elementaryActions + networkAction.getElementaryActions().size();
}
if (elementaryActions + movedPstTapsPerTso.getOrDefault(tso, 0) > raUsageLimits.getMaxElementaryActionsPerTso().getOrDefault(tso, Integer.MAX_VALUE)) {
return true;
}
}
return false;
}
boolean hasPreDefinedNetworkActionCombination(NetworkActionCombination naCombination) {
return this.preDefinedNaCombinations.contains(naCombination);
}
Map getNumberOfPstTapsMovedByTso(OptimizationResult optimizationResult) {
Map pstTapsMovedByTso = new HashMap<>();
Set activatedRangeActions = optimizationResult.getActivatedRangeActions(input.getOptimizationPerimeter().getMainOptimizationState()).stream().filter(PstRangeAction.class::isInstance).map(ra -> (PstRangeAction) ra).collect(Collectors.toSet());
for (PstRangeAction pstRangeAction : activatedRangeActions) {
String operator = pstRangeAction.getOperator();
int tapsMoved = Math.abs(optimizationResult.getOptimizedTap(pstRangeAction, input.getOptimizationPerimeter().getMainOptimizationState()) - input.getPrePerimeterResult().getTap(pstRangeAction));
pstTapsMovedByTso.put(operator, pstTapsMovedByTso.getOrDefault(operator, 0) + tapsMoved);
}
return pstTapsMovedByTso;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy