Skip to content

Commit d331f46

Browse files
authored
Merge pull request #354 from EnergySystemsModellingLab/custom_constraints
Enable customisation of constraints
2 parents 130c8f1 + 73c734f commit d331f46

5 files changed

Lines changed: 50 additions & 4 deletions

File tree

src/muse/constraints.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ def factory(
218218
"""
219219
from functools import partial
220220

221-
if settings is None:
221+
if not settings:
222222
settings = (
223223
"max_production",
224224
"max_capacity_expansion",

src/muse/data/example/default/settings.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ constraints = [
5959
"max_production",
6060
"max_capacity_expansion",
6161
"demand",
62-
"search_space"
62+
"search_space",
63+
"minimum_service"
6364
]
6465
demand_share = "new_and_retro" # Optional, default to new_and_retro
6566
forecast = 5 # Optional, defaults to 5

src/muse/data/example/default_timeslice/settings.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ constraints = [
6161
"max_production",
6262
"max_capacity_expansion",
6363
"demand",
64-
"search_space"
64+
"search_space",
65+
"minimum_service"
6566
]
6667
demand_share = "new_and_retro" # Optional, default to new_and_retro
6768
forecast = 5 # Optional, defaults to 5

src/muse/sectors/subsector.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ def factory(
184184
# only used by self-investing agents
185185
investment=getattr(settings, "lpsolver", "adhoc"),
186186
forecast=getattr(settings, "forecast", 5),
187+
constraints=getattr(settings, "constraints", ()),
187188
)
188189
# technologies can have nans where a commodity
189190
# does not apply to a technology at all

tests/test_subsector.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from collections.abc import Sequence
2+
from unittest.mock import MagicMock, patch
23

34
import xarray as xr
4-
from pytest import fixture
5+
from pytest import fixture, raises
56

67

78
@fixture
@@ -134,3 +135,45 @@ def test_factory_smoke_test(model, technologies, tmp_path):
134135

135136
assert isinstance(subsector, Subsector)
136137
assert len(subsector.agents) == 2
138+
139+
140+
def test_factory_constraints_passed_to_agents(model, technologies, tmp_path):
141+
from muse import examples
142+
from muse.readers.toml import read_settings
143+
from muse.sectors.subsector import Subsector
144+
145+
examples.copy_model(model, tmp_path)
146+
settings = read_settings(tmp_path / "model" / "settings.toml")
147+
148+
# The constraints in the settings are not none
149+
assert len(settings.sectors.residential.subsectors.retro_and_new.constraints) > 0
150+
151+
class BreakException(Exception):
152+
pass
153+
154+
_withness = MagicMock()
155+
156+
def agent_factory(*args, **kwargs):
157+
_withness(*args, **kwargs)
158+
raise BreakException()
159+
160+
# We asses they are indeed passed to the agents factory
161+
with patch("muse.agents.agents_factory", new=agent_factory):
162+
with raises(BreakException):
163+
Subsector.factory(
164+
settings.sectors.residential.subsectors.retro_and_new, technologies
165+
)
166+
assert (
167+
_withness.call_args[1]["constraints"]
168+
== settings.sectors.residential.subsectors.retro_and_new.constraints
169+
)
170+
171+
# But if there are no constraints, we pass an empty tuple
172+
settings.sectors.residential.subsectors.retro_and_new.constraints.clear()
173+
_withness.reset_mock()
174+
with patch("muse.agents.agents_factory", new=agent_factory):
175+
with raises(BreakException):
176+
Subsector.factory(
177+
settings.sectors.residential.subsectors.retro_and_new, technologies
178+
)
179+
assert tuple(_withness.call_args[1]["constraints"]) == ()

0 commit comments

Comments
 (0)