Skip to content

Commit

Permalink
Fix expectation computation
Browse files Browse the repository at this point in the history
  • Loading branch information
tbittar committed Aug 21, 2024
1 parent 27f8ad8 commit bcafb95
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 23 deletions.
6 changes: 4 additions & 2 deletions src/andromede/expression/linear_expression_efficient.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,8 @@ def _merge_dicts(
rhs: Dict[TermKeyEfficient, TermEfficient],
merge_func: Callable[[TermEfficient, TermEfficient], TermEfficient],
neutral: float,
) -> Dict[TermKeyEfficient, TermEfficient]: ...
) -> Dict[TermKeyEfficient, TermEfficient]:
...


@overload
Expand All @@ -389,7 +390,8 @@ def _merge_dicts(
rhs: Dict[PortFieldId, PortFieldTerm],
merge_func: Callable[[PortFieldTerm, PortFieldTerm], PortFieldTerm],
neutral: float,
) -> Dict[PortFieldId, PortFieldTerm]: ...
) -> Dict[PortFieldId, PortFieldTerm]:
...


def _get_neutral_term(term: T_val, neutral: float) -> T_val:
Expand Down
36 changes: 19 additions & 17 deletions src/andromede/simulation/linear_expression_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
ResolvedLinearExpression,
ResolvedTerm,
)
from andromede.expression.scenario_operator import Expectation
from andromede.expression.time_operator import TimeShift
from andromede.expression.value_provider import (
TimeScenarioIndex,
Expand All @@ -50,11 +51,10 @@ def resolve(
# Here, the value provide is used only to evaluate possible time operator args if the term has one
resolved_variables = self.resolve_variables(term, row_id)

# TODO: For now all coefficients are the same for a given "variable_name", we are not able to represent things like sum(a_t * x_t)... but everything else is ok:
# sum(a_t') * x_t
# a_t * sum(x_t')
# a_t * x_t
# TODO: Next line is to be moved inside the for loop once we have figured out how to represent sum(a_t * x_t)
# TODO: Contrary to the time aggregator that does a sum which is the default behaviour when append resolved terms, expectation performs an averaging, so weights must be included in coefficients. We feel here that we could generalize time and scenario aggregation over variables with more general operators, the following lines are very specific to expectation with same weights over all scenarios
weight = 1
if isinstance(term.scenario_aggregator, Expectation):
weight = 1 / self.value_provider.scenarios()

for ts_id, lp_variable in resolved_variables.items():
# TODO: Could we check in which case coeff resolution leads to the same result for each element in the for loop ? When there is only a literal, etc, etc ?
Expand All @@ -63,7 +63,9 @@ def resolve(
self.value_provider,
RowIndex(ts_id.time, ts_id.scenario),
)
resolved_terms.append(ResolvedTerm(resolved_coeff, lp_variable))
resolved_terms.append(
ResolvedTerm(weight * resolved_coeff, lp_variable)
)

resolved_constant = resolve_coefficient(
expression.constant, self.value_provider, row_id
Expand All @@ -84,17 +86,17 @@ def resolve_variables(
operator_ts_ids = self._row_id_to_term_time_scenario_id(term, row_id)
for time in operator_ts_ids.time_indices:
for scenario in operator_ts_ids.scenario_indices:
solver_vars[TimeScenarioIndex(time, scenario)] = (
self.context.get_component_variable(
time,
scenario,
term.component_id,
term.variable_name,
# At term build time, no information on the variable structure is known, we use it now
self.context.network.get_component(term.component_id)
.model.variables[term.variable_name]
.structure,
)
solver_vars[
TimeScenarioIndex(time, scenario)
] = self.context.get_component_variable(
time,
scenario,
term.component_id,
term.variable_name,
# At term build time, no information on the variable structure is known, we use it now
self.context.network.get_component(term.component_id)
.model.variables[term.variable_name]
.structure,
)
return solver_vars

Expand Down
8 changes: 4 additions & 4 deletions tests/functional/test_xpansion.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,10 +375,10 @@ def test_generation_xpansion_two_time_steps_two_scenarios(
status = problem.solver.Solve()

assert status == problem.solver.OPTIMAL
# assert problem.solver.NumVariables() == 2 * scenarios * horizon + 1
# assert (
# problem.solver.NumConstraints() == 3 * scenarios * horizon
# ) # Flow balance, Max generation for each cluster
assert problem.solver.NumVariables() == 2 * scenarios * horizon + 1
assert (
problem.solver.NumConstraints() == 3 * scenarios * horizon
) # Flow balance, Max generation for each cluster
assert problem.solver.Objective().Value() == pytest.approx(
490 * 300
+ 0.5 * (10 * 300 + 10 * 300 + 40 * 200)
Expand Down

0 comments on commit bcafb95

Please sign in to comment.