Skip to content

Commit

Permalink
Add shadow prices
Browse files Browse the repository at this point in the history
  • Loading branch information
brynpickering committed Jan 18, 2024
1 parent 17447e9 commit a891a1b
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/calliope/backend/backend_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,17 @@ def get_global_expression(
xr.DataArray: global expression array.
"""

@abstractmethod
def get_shadow_prices(self, name: str) -> xr.DataArray:
"""Extract shadow prices (a.k.a. duals) from a constraint.
Args:
name (str): Name of constraint for which you're seeking duals.
Returns:
xr.DataArray: duals array.
"""

@abstractmethod
def update_parameter(
self, name: str, new_values: Union[xr.DataArray, SupportsFloat]
Expand Down
19 changes: 19 additions & 0 deletions src/calliope/backend/pyomo_backend_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ def __init__(self, inputs: xr.Dataset, **kwargs):
self._instance.constraints = pmo.constraint_dict()
self._instance.objectives = pmo.objective_dict()

self._instance.dual = pmo.suffix(direction=pmo.suffix.IMPORT)

self._add_all_inputs_as_parameters()

def add_parameter(
Expand Down Expand Up @@ -247,6 +249,14 @@ def get_global_expression(
else:
return global_expression

def get_shadow_prices(self, name: str) -> xr.DataArray:
constraint = self.get_constraint(name, as_backend_objs=True)
return self._apply_func(
self._duals_from_pyomo_constraint,
constraint,
dual_getter=self._instance.dual,
)

def solve(
self,
solver: str,
Expand Down Expand Up @@ -752,6 +762,15 @@ def _from_pyomo_expr(val: pmo.expression, *, eval_body: bool = False) -> Any:
else:
return val.to_string()

@staticmethod
def _duals_from_pyomo_constraint(
val: pmo.constraint, *, dual_getter: pmo.suffix
) -> float:
if pd.isnull(val):
return np.nan
else:
return dual_getter.get(val)

@contextmanager
def _datetime_as_string(self, data: Union[xr.DataArray, xr.Dataset]) -> Iterator:
"""Context manager to temporarily convert np.dtype("datetime64[ns]") coordinates (e.g. timesteps) to strings with a resolution of minutes.
Expand Down

0 comments on commit a891a1b

Please sign in to comment.