All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.powsybl.openrao.searchtreerao.result.impl.RangeActionActivationResultImpl Maven / Gradle / Ivy

/*
 * 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.result.impl;

import com.powsybl.openrao.commons.OpenRaoException;
import com.powsybl.openrao.data.crac.api.Identifiable;
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.searchtreerao.result.api.RangeActionActivationResult;
import com.powsybl.openrao.searchtreerao.result.api.RangeActionSetpointResult;

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

import static java.lang.String.format;

/**
 * @author Baptiste Seguinot {@literal }
 */
public class RangeActionActivationResultImpl implements RangeActionActivationResult {

    private final Map, ElementaryResult> elementaryResultMap = new HashMap<>();

    boolean shouldRecomputeSetpointsPerState = true;

    private Map > setpointPerStatePerPstId;

    private static class ElementaryResult {
        private final double refSetpoint;
        private final Map setPointPerState;

        ElementaryResult(double refSetpoint) {
            this.refSetpoint = refSetpoint;
            this.setPointPerState = new HashMap<>();
        }

        private void put(State state, Double setpoint) {
            setPointPerState.put(state, setpoint);
        }

        private boolean isExplicitlyActivatedDuringState(State state) {
            return setPointPerState.containsKey(state);
        }

        private double getSetpoint(State state) {
            if (setPointPerState.containsKey(state)) {
                return setPointPerState.get(state);
            } else {
                Optional lastActivation = getLastPreviousActivation(state);
                if (lastActivation.isPresent()) {
                    return setPointPerState.get(lastActivation.get());
                } else {
                    return refSetpoint;
                }
            }
        }

        private Optional getLastPreviousActivation(State state) {
            return setPointPerState.keySet().stream()
                .filter(s -> s.getContingency().equals(state.getContingency()) || s.getContingency().isEmpty())
                .filter(s -> s.getInstant().comesBefore(state.getInstant()))
                .max(Comparator.comparingInt(s -> s.getInstant().getOrder()));
        }

        private Set getAllStatesWithActivation() {
            return setPointPerState.keySet();
        }
    }

    public RangeActionActivationResultImpl(RangeActionSetpointResult rangeActionSetpointResult) {
        shouldRecomputeSetpointsPerState = true;
        rangeActionSetpointResult.getRangeActions().forEach(ra -> elementaryResultMap.put(ra, new ElementaryResult(rangeActionSetpointResult.getSetpoint(ra))));
    }

    public void putResult(RangeAction rangeAction, State state, double setpoint) {
        shouldRecomputeSetpointsPerState = true;
        elementaryResultMap.get(rangeAction).put(state, setpoint);
    }

    private synchronized void computeSetpointsPerStatePerPst() {
        if (!shouldRecomputeSetpointsPerState) {
            return;
        }
        setpointPerStatePerPstId = new HashMap<>();
        elementaryResultMap.forEach((rangeAction, elementaryResult) -> {
            String networkElementsIds = concatenateNetworkElementsIds(rangeAction);
            setpointPerStatePerPstId.computeIfAbsent(networkElementsIds, raId -> new HashMap<>());
            elementaryResult.getAllStatesWithActivation().forEach(state ->
                setpointPerStatePerPstId.get(networkElementsIds).put(state, elementaryResult.getSetpoint(state))
            );
        });
        shouldRecomputeSetpointsPerState = false;
    }

    private String concatenateNetworkElementsIds(RangeAction rangeAction) {
        return rangeAction.getNetworkElements().stream().map(Identifiable::getId).sorted().collect(Collectors.joining("+"));
    }

    @Override
    public Set> getRangeActions() {
        return elementaryResultMap.keySet();
    }

    @Override
    public Set> getActivatedRangeActions(State state) {
        computeSetpointsPerStatePerPst();
        return elementaryResultMap.entrySet().stream()
            .filter(e -> e.getValue().isExplicitlyActivatedDuringState(state))
            .filter(e -> {
                Optional pState = getPreviousState(state);
                if (pState.isEmpty()) {
                    return Math.abs(getOptimizedSetpoint(e.getKey(), state) - e.getValue().refSetpoint) > 1e-6; // TODO : use same parameter as min variation of MIP here?
                } else {
                    return Math.abs(getOptimizedSetpoint(e.getKey(), state) - getOptimizedSetpoint(e.getKey(), pState.get())) > 1e-6;
                }
            })
            .map(Map.Entry::getKey)
            .collect(Collectors.toSet());
    }

    @Override
    public double getOptimizedSetpoint(RangeAction rangeAction, State state) {
        computeSetpointsPerStatePerPst();
        String networkElementsIds = concatenateNetworkElementsIds(rangeAction);
        // if at least one elementary result is on the correct network elements, find the right state to get the setpoint
        // else return the reference setpoint
        if (setpointPerStatePerPstId.containsKey(networkElementsIds)) {
            Map setPointPerState = setpointPerStatePerPstId.get(networkElementsIds);
            // if an elementary result is defined for the network element and state, return it
            // else find a previous state with an elementary result
            // if none are found, return reference setpoint
            Double lastSetpoint = getSetpointForState(setPointPerState, state);
            if (lastSetpoint != null) {
                return lastSetpoint;
            }
        }
        if (!elementaryResultMap.containsKey(rangeAction)) {
            throw new OpenRaoException(format("range action %s is not present in the result", rangeAction.getName()));
        }
        return elementaryResultMap.get(rangeAction).refSetpoint;
    }

    private Double getSetpointForState(Map setPointPerState, State state) {
        if (setPointPerState.containsKey(state)) {
            return setPointPerState.get(state);
        }
        Optional previousState = getPreviousState(state);
        // setPointPerState does not contain a setpoint for any of state's previous states
        return previousState.map(value -> getSetpointForState(setPointPerState, value)).orElse(null);
    }

    @Override
    public Map, Double> getOptimizedSetpointsOnState(State state) {
        computeSetpointsPerStatePerPst();
        Map, Double> optimizedSetpoints = new HashMap<>();
        elementaryResultMap.forEach((ra, re) -> optimizedSetpoints.put(ra, getOptimizedSetpoint(ra, state)));
        return optimizedSetpoints;
    }

    @Override
    public double getSetPointVariation(RangeAction rangeAction, State state) {
        computeSetpointsPerStatePerPst();
        Optional previousState = getPreviousState(state);
        if (previousState.isEmpty()) {
            return getOptimizedSetpoint(rangeAction, state) - elementaryResultMap.get(rangeAction).refSetpoint;
        } else {
            return getOptimizedSetpoint(rangeAction, state) - getOptimizedSetpoint(rangeAction, previousState.get());
        }
    }

    @Override
    public int getOptimizedTap(PstRangeAction pstRangeAction, State state) {
        computeSetpointsPerStatePerPst();
        return pstRangeAction.convertAngleToTap(getOptimizedSetpoint(pstRangeAction, state));
    }

    @Override
    public Map getOptimizedTapsOnState(State state) {
        computeSetpointsPerStatePerPst();
        Map optimizedTaps = new HashMap<>();
        elementaryResultMap.entrySet().stream()
            .filter(e -> e.getKey() instanceof PstRangeAction)
            .forEach(e -> optimizedTaps.put((PstRangeAction) e.getKey(), getOptimizedTap((PstRangeAction) e.getKey(), state)));
        return optimizedTaps;
    }

    @Override
    public int getTapVariation(PstRangeAction pstRangeAction, State state) {
        computeSetpointsPerStatePerPst();
        Optional previousState = getPreviousState(state);
        if (previousState.isEmpty()) {
            return getOptimizedTap(pstRangeAction, state) - pstRangeAction.convertAngleToTap(elementaryResultMap.get(pstRangeAction).refSetpoint);
        } else {
            return getOptimizedTap(pstRangeAction, state) - getOptimizedTap(pstRangeAction, previousState.get());
        }
    }

    private Optional getPreviousState(State state) {
        return elementaryResultMap.values().stream()
            .flatMap(eR -> eR.getAllStatesWithActivation().stream())
            .filter(s -> s.getContingency().equals(state.getContingency()) || s.getContingency().isEmpty())
            .filter(s -> s.getInstant().comesBefore(state.getInstant()))
            .max(Comparator.comparingInt(s -> s.getInstant().getOrder()));
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy