Skip to content

Commit

Permalink
Api for hydrp heuristic model
Browse files Browse the repository at this point in the history
  • Loading branch information
Juliette-Gerbaux committed Jun 24, 2024
1 parent ac42ad6 commit 3dddf92
Show file tree
Hide file tree
Showing 2 changed files with 336 additions and 333 deletions.
278 changes: 144 additions & 134 deletions tests/functional/test_hydro_heuristic_complex_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,31 @@
# This file is part of the Antares project.

import pandas as pd
import pytest
import numpy as np
from typing import List, Dict
from math import ceil, floor
import ortools.linear_solver.pywraplp as pywraplp

from andromede.expression import literal, param, var
from andromede.expression.expression import ExpressionRange
from andromede.expression.indexing_structure import IndexingStructure
from andromede.model import Model, ModelPort, float_parameter, float_variable, model
from andromede.model.parameter import float_parameter, int_parameter
from andromede.model.variable import float_variable, int_variable
from andromede.model import Model, float_parameter, float_variable, model
from andromede.model.parameter import float_parameter
from andromede.model.variable import float_variable
from andromede.model.constraint import Constraint
from andromede.simulation import (
BlockBorderManagement,
OutputValues,
TimeBlock,
build_problem,
)
from andromede.simulation.optimization import OptimizationProblem
from andromede.study import (
ConstantData,
DataBase,
Network,
Node,
PortRef,
TimeScenarioIndex,
TimeScenarioSeriesData,
TimeSeriesData,
TimeIndex,
create_component,
)
from andromede.study.data import AbstractDataStructure

CONSTANT = IndexingStructure(False, False)
TIME_AND_SCENARIO_FREE = IndexingStructure(True, True)
Expand All @@ -52,103 +44,132 @@
CONSTANT_PER_SCENARIO = IndexingStructure(False, True)


def get_hydro_model(horizon: str) -> Model:
HYDRO_MODEL = {
"id": "H",
"parameters": [
float_parameter("max_generating", NON_ANTICIPATIVE_TIME_VARYING),
float_parameter("min_generating", NON_ANTICIPATIVE_TIME_VARYING),
float_parameter("capacity", CONSTANT),
float_parameter("initial_level", CONSTANT_PER_SCENARIO),
float_parameter("generating_target", TIME_AND_SCENARIO_FREE),
float_parameter("overall_target", CONSTANT_PER_SCENARIO),
float_parameter("inflow", TIME_AND_SCENARIO_FREE),
float_parameter(
"max_epsilon", NON_ANTICIPATIVE_TIME_VARYING
), # not really a parameter, it is just to implement correctly one constraint
float_parameter("lower_rule_curve", NON_ANTICIPATIVE_TIME_VARYING),
float_parameter("upper_rule_curve", NON_ANTICIPATIVE_TIME_VARYING),
],
"variables": [
float_variable(
"generating",
lower_bound=param("min_generating"),
upper_bound=param("max_generating"),
structure=TIME_AND_SCENARIO_FREE,
),
float_variable(
"level",
lower_bound=literal(0),
upper_bound=param("capacity"),
structure=TIME_AND_SCENARIO_FREE,
),
float_variable(
"overflow",
lower_bound=literal(0),
structure=TIME_AND_SCENARIO_FREE,
),
float_variable(
"epsilon",
lower_bound=-param("max_epsilon"),
upper_bound=param("max_epsilon"),
structure=TIME_AND_SCENARIO_FREE,
),
],
"constraints": [
Constraint(
"Level balance",
var("level")
== var("level").shift(-1)
- var("generating")
- var("overflow")
+ param("inflow")
+ var("epsilon"),
),
# Constraint(
# "Respect generating target",
# var("generating").sum() == param("overall_target"),
# ),
Constraint(
"Initial level",
var("level").eval(literal(0))
== param("initial_level")
- var("generating").eval(literal(0))
- var("overflow").eval(literal(0))
+ param("inflow").eval(literal(0)),
),
],
}


def get_heuristic_hydro_model(
hydro_model: Dict,
horizon: str,
) -> Model:
objective_function_cost = {"gamma_d": 1}

list_constraint = hydro_model["constraints"] + [
Constraint(
"Respect generating target",
var("generating").sum() + var("gap_to_target") == param("overall_target"),
),
Constraint(
"Definition of distance between target and generating",
var("distance_between_target_and_generating")
>= param("generating_target") - var("generating"),
),
Constraint(
"Definition of distance between generating and target",
var("distance_between_target_and_generating")
>= var("generating") - param("generating_target"),
),
]
if horizon == "monthly":
list_constraint.append(Constraint("No overflow", var("overflow") <= literal(0)))
list_constraint.append(
Constraint("No gap to target", var("gap_to_target") <= literal(0))
)

HYDRO_HEURISTIC = model(
id="H",
parameters=[
float_parameter("gamma_delta", CONSTANT),
float_parameter("gamma_y", CONSTANT),
float_parameter("gamma_w", CONSTANT),
float_parameter("gamma_d", CONSTANT),
float_parameter("gamma_v+", CONSTANT),
float_parameter("gamma_v-", CONSTANT),
float_parameter("gamma_o", CONSTANT),
float_parameter("gamma_s", CONSTANT),
int_parameter("alpha_o", CONSTANT),
int_parameter("alpha_g", CONSTANT),
int_parameter("alpha_f", CONSTANT),
float_parameter("lower_rule_curve", NON_ANTICIPATIVE_TIME_VARYING),
float_parameter("upper_rule_curve", NON_ANTICIPATIVE_TIME_VARYING),
float_parameter("max_generating", NON_ANTICIPATIVE_TIME_VARYING),
float_parameter("min_generating", NON_ANTICIPATIVE_TIME_VARYING),
float_parameter("capacity", CONSTANT),
float_parameter("initial_level", CONSTANT_PER_SCENARIO),
float_parameter("generating_target", TIME_AND_SCENARIO_FREE),
float_parameter("overall_target", CONSTANT_PER_SCENARIO),
float_parameter("inflow", TIME_AND_SCENARIO_FREE),
float_parameter("max_epsilon", NON_ANTICIPATIVE_TIME_VARYING),
],
variables=[
float_variable(
"generating",
lower_bound=param("min_generating"),
upper_bound=param("max_generating"),
structure=TIME_AND_SCENARIO_FREE,
),
float_variable(
"level",
lower_bound=literal(0),
upper_bound=param("capacity"),
structure=TIME_AND_SCENARIO_FREE,
),
float_variable(
"overflow",
lower_bound=literal(0),
structure=TIME_AND_SCENARIO_FREE,
),
float_variable(
"epsilon",
lower_bound=-param("max_epsilon"),
upper_bound=param("max_epsilon"),
structure=TIME_AND_SCENARIO_FREE,
),
parameters=hydro_model["parameters"],
variables=hydro_model["variables"]
+ [
float_variable(
"distance_between_target_and_generating",
lower_bound=literal(0),
structure=TIME_AND_SCENARIO_FREE,
),
]
+ [
(
float_variable(
"gap_to_target",
lower_bound=literal(0),
structure=CONSTANT_PER_SCENARIO,
)
if horizon == "daily"
else float_variable(
"gap_to_target",
lower_bound=literal(0),
upper_bound=literal(0),
structure=CONSTANT,
)
)
],
constraints=[
Constraint(
"Level balance",
var("level")
== var("level").shift(-1)
- var("generating")
- param("alpha_o") * var("overflow")
+ param("inflow")
+ var("epsilon"),
),
Constraint(
"Respect generating target",
param("alpha_g") * var("generating").sum()
== param("alpha_g") * param("overall_target"),
),
Constraint(
"Initial level",
var("level").eval(literal(0))
== param("initial_level")
- var("generating").eval(literal(0))
- param("alpha_o") * var("overflow").eval(literal(0))
+ param("inflow").eval(literal(0)),
),
# Constraint(
# "Final level",
# param("alpha_f") * var("level").eval(literal(0))
# == param("alpha_f") * var("level").eval(literal(-1)),
# ),
Constraint(
"Definition of distance between target and generating",
var("distance_between_target_and_generating")
>= param("generating_target") - var("generating"),
),
Constraint(
"Definition of distance between generating and target",
var("distance_between_target_and_generating")
>= var("generating") - param("generating_target"),
),
],
constraints=list_constraint,
objective_operational_contribution=(
param("gamma_d") * var("distance_between_target_and_generating")
objective_function_cost["gamma_d"]
* var("distance_between_target_and_generating")
)
.sum()
.expec(),
Expand All @@ -172,11 +193,13 @@ def test_hydro_heuristic() -> None:
monthly_max_generating = get_maxpower_data("monthly")

# Ajustement de la réapartition mensuelle
monthly_generation = create_hydro_problem(
initial_level = 0.5 * 1711510
monthly_generation, _ = create_hydro_problem(
horizon="monthly",
target=list(monthly_target),
inflow=list(monthly_inflow),
max_generating=monthly_max_generating,
initial_level=initial_level,
)

weekly_target = np.zeros(52)
Expand Down Expand Up @@ -205,13 +228,14 @@ def test_hydro_heuristic() -> None:
)
)
# Ajustement de la répartition jour par jour
daily_generation = create_hydro_problem(
daily_generation, initial_level = create_hydro_problem(
horizon="daily",
target=list(daily_target),
inflow=list(daily_inflow),
max_generating=list(
daily_max_generating[day_in_year : day_in_year + number_day_month]
),
initial_level=initial_level,
)

# Calcul des cibles hebdomadaires
Expand Down Expand Up @@ -242,19 +266,22 @@ def create_hydro_problem(
target: List[float],
inflow: List[float],
max_generating: List[float],
) -> List[float]:
initial_level: float,
) -> tuple[List[float], float]:

database = generate_database(
horizon=horizon,
target=target,
inflow=inflow,
max_generating=max_generating,
initial_level=initial_level,
)

time_block = TimeBlock(1, [i for i in range(len(target))])
scenarios = 1

hydro = create_component(model=get_hydro_model(horizon), id="H")
hydro = create_component(
model=get_heuristic_hydro_model(HYDRO_MODEL, horizon), id="H"
)

network = Network("test")
network.add_component(hydro)
Expand All @@ -278,33 +305,22 @@ def create_hydro_problem(

output = OutputValues(problem)

return output.component("H").var("generating").value[0] # type:ignore
return (
output.component("H").var("generating").value[0], # type:ignore
output.component("H").var("level").value[0][-1], # type:ignore
)


def generate_database(
horizon: str,
target: List[float],
inflow: List[float],
max_generating: List[float],
initial_level: float,
) -> DataBase:
database = DataBase()

database.add_data("H", "gamma_delta", ConstantData(1))
database.add_data("H", "gamma_y", ConstantData(0))
database.add_data("H", "gamma_w", ConstantData(0))
database.add_data("H", "gamma_d", ConstantData(1))
database.add_data("H", "gamma_v+", ConstantData(0))
database.add_data("H", "gamma_v-", ConstantData(0))
database.add_data("H", "gamma_o", ConstantData(0))
database.add_data("H", "gamma_s", ConstantData(0))
if horizon == "monthly":
database.add_data("H", "alpha_o", ConstantData(0))
elif horizon == "daily":
database.add_data("H", "alpha_o", ConstantData(1))
database.add_data("H", "alpha_g", ConstantData(1))
database.add_data("H", "alpha_f", ConstantData(1))
database.add_data("H", "capacity", ConstantData(1711510))
database.add_data("H", "initial_level", ConstantData(0.5 * 1711510))
database.add_data("H", "initial_level", ConstantData(initial_level))

inflow_data = pd.DataFrame(
inflow,
Expand Down Expand Up @@ -333,19 +349,13 @@ def generate_database(
),
)

if horizon == "monthly":
database.add_data("H", "max_epsilon", ConstantData(0))
elif horizon == "daily":
database.add_data(
"H",
"max_epsilon",
TimeSeriesData(
{
TimeIndex(i): 1711510 if i == 0 else 0
for i in range(len(max_generating))
}
),
)
database.add_data(
"H",
"max_epsilon",
TimeSeriesData(
{TimeIndex(i): 1711510 if i == 0 else 0 for i in range(len(max_generating))}
),
)

return database

Expand Down
Loading

0 comments on commit 3dddf92

Please sign in to comment.