Skip to content

Commit 8890621

Browse files
committed
Test priority-based bounds calculation for the Matryoshka algorithm
Also fix a bug in bounds calculation that was causing impossible bounds sent to users. Signed-off-by: Sahas Subramanian <[email protected]>
1 parent 19121df commit 8890621

File tree

2 files changed

+99
-24
lines changed

2 files changed

+99
-24
lines changed

src/frequenz/sdk/actor/_power_managing/_matryoshka.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,13 @@ def get_status(
148148
if next_proposal.priority <= priority:
149149
break
150150
if next_proposal.bounds:
151-
lower_bound = max(lower_bound, next_proposal.bounds[0])
152-
upper_bound = min(upper_bound, next_proposal.bounds[1])
151+
calc_lower_bound = max(lower_bound, next_proposal.bounds[0])
152+
calc_upper_bound = min(upper_bound, next_proposal.bounds[1])
153+
if calc_lower_bound <= calc_upper_bound:
154+
lower_bound = calc_lower_bound
155+
upper_bound = calc_upper_bound
156+
else:
157+
break
153158

154159
return Report(
155160
target_power=self._target_power.get(battery_ids, Power.zero()),

tests/actor/_power_managing/test_matryoshka.py

Lines changed: 92 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from frequenz.sdk.timeseries import Power, battery_pool
1111

1212

13-
async def test_matryoshka_algorithm() -> None:
13+
async def test_matryoshka_algorithm() -> None: # pylint: disable=too-many-statements
1414
"""Tests for the power managing actor."""
1515
batteries = frozenset({2, 5})
1616

@@ -25,7 +25,7 @@ async def test_matryoshka_algorithm() -> None:
2525

2626
call_count = 0
2727

28-
def case(
28+
def test_tgt_power(
2929
priority: int,
3030
power: float,
3131
bounds: tuple[float, float] | None,
@@ -50,23 +50,93 @@ def case(
5050
Power.from_watts(expected) if expected is not None else None
5151
)
5252

53-
case(priority=2, power=25.0, bounds=(25.0, 50.0), expected=25.0)
54-
case(priority=1, power=20.0, bounds=(20.0, 50.0), expected=None)
55-
case(priority=3, power=10.0, bounds=(10.0, 15.0), expected=15.0)
56-
case(priority=3, power=10.0, bounds=(10.0, 22.0), expected=22.0)
57-
case(priority=1, power=30.0, bounds=(20.0, 50.0), expected=None)
58-
case(priority=3, power=10.0, bounds=(10.0, 50.0), expected=30.0)
59-
case(priority=2, power=40.0, bounds=(40.0, 50.0), expected=40.0)
60-
case(priority=2, power=0.0, bounds=(-200.0, 200.0), expected=30.0)
61-
case(priority=4, power=-50.0, bounds=(-200.0, -50.0), expected=-50.0)
62-
case(priority=3, power=-0.0, bounds=(-200.0, 200.0), expected=None)
63-
case(priority=1, power=-150.0, bounds=(-200.0, -150.0), expected=-150.0)
64-
case(priority=4, power=-180.0, bounds=(-200.0, -50.0), expected=None)
65-
case(priority=4, power=50.0, bounds=(50.0, 200.0), expected=50.0)
66-
67-
case(priority=4, power=0.0, bounds=(-200.0, 200.0), expected=-150.0)
68-
case(priority=3, power=0.0, bounds=(-200.0, 200.0), expected=None)
69-
case(priority=2, power=50.0, bounds=(-100, 100), expected=-100.0)
70-
case(priority=1, power=100.0, bounds=(100, 200), expected=100.0)
71-
case(priority=1, power=50.0, bounds=(50, 200), expected=50.0)
72-
case(priority=1, power=200.0, bounds=(50, 200), expected=100.0)
53+
def test_bounds(
54+
priority: int, expected_power: float, expected_bounds: tuple[float, float]
55+
) -> None:
56+
report = algorithm.get_status(batteries, priority, system_bounds)
57+
assert report.target_power.as_watts() == expected_power
58+
assert report.available_bounds.lower.as_watts() == expected_bounds[0]
59+
assert report.available_bounds.upper.as_watts() == expected_bounds[1]
60+
61+
test_tgt_power(priority=2, power=25.0, bounds=(25.0, 50.0), expected=25.0)
62+
test_bounds(priority=2, expected_power=25.0, expected_bounds=(-200.0, 200.0))
63+
test_bounds(priority=1, expected_power=25.0, expected_bounds=(25.0, 50.0))
64+
65+
test_tgt_power(priority=1, power=20.0, bounds=(20.0, 50.0), expected=None)
66+
test_bounds(priority=1, expected_power=25.0, expected_bounds=(25.0, 50.0))
67+
68+
test_tgt_power(priority=3, power=10.0, bounds=(10.0, 15.0), expected=15.0)
69+
test_bounds(priority=3, expected_power=15.0, expected_bounds=(-200.0, 200.0))
70+
test_bounds(priority=2, expected_power=15.0, expected_bounds=(10.0, 15.0))
71+
test_bounds(priority=1, expected_power=15.0, expected_bounds=(10.0, 15.0))
72+
73+
test_tgt_power(priority=3, power=10.0, bounds=(10.0, 22.0), expected=22.0)
74+
test_bounds(priority=3, expected_power=22.0, expected_bounds=(-200.0, 200.0))
75+
test_bounds(priority=2, expected_power=22.0, expected_bounds=(10.0, 22.0))
76+
test_bounds(priority=1, expected_power=22.0, expected_bounds=(10.0, 22.0))
77+
78+
test_tgt_power(priority=1, power=30.0, bounds=(20.0, 50.0), expected=None)
79+
test_bounds(priority=1, expected_power=22.0, expected_bounds=(10.0, 22.0))
80+
81+
test_tgt_power(priority=3, power=10.0, bounds=(10.0, 50.0), expected=30.0)
82+
test_bounds(priority=3, expected_power=30.0, expected_bounds=(-200.0, 200.0))
83+
test_bounds(priority=2, expected_power=30.0, expected_bounds=(10.0, 50.0))
84+
test_bounds(priority=1, expected_power=30.0, expected_bounds=(25.0, 50.0))
85+
86+
test_tgt_power(priority=2, power=40.0, bounds=(40.0, 50.0), expected=40.0)
87+
test_bounds(priority=3, expected_power=40.0, expected_bounds=(-200.0, 200.0))
88+
test_bounds(priority=2, expected_power=40.0, expected_bounds=(10.0, 50.0))
89+
test_bounds(priority=1, expected_power=40.0, expected_bounds=(40.0, 50.0))
90+
91+
test_tgt_power(priority=2, power=0.0, bounds=(-200.0, 200.0), expected=30.0)
92+
test_bounds(priority=4, expected_power=30.0, expected_bounds=(-200.0, 200.0))
93+
test_bounds(priority=3, expected_power=30.0, expected_bounds=(-200.0, 200.0))
94+
test_bounds(priority=2, expected_power=30.0, expected_bounds=(10.0, 50.0))
95+
test_bounds(priority=1, expected_power=30.0, expected_bounds=(10.0, 50.0))
96+
97+
test_tgt_power(priority=4, power=-50.0, bounds=(-200.0, -50.0), expected=-50.0)
98+
test_bounds(priority=4, expected_power=-50.0, expected_bounds=(-200.0, 200.0))
99+
test_bounds(priority=3, expected_power=-50.0, expected_bounds=(-200.0, -50.0))
100+
test_bounds(priority=2, expected_power=-50.0, expected_bounds=(-200.0, -50.0))
101+
test_bounds(priority=1, expected_power=-50.0, expected_bounds=(-200.0, -50.0))
102+
103+
test_tgt_power(priority=3, power=-0.0, bounds=(-200.0, 200.0), expected=None)
104+
test_bounds(priority=1, expected_power=-50.0, expected_bounds=(-200.0, -50.0))
105+
106+
test_tgt_power(priority=1, power=-150.0, bounds=(-200.0, -150.0), expected=-150.0)
107+
test_bounds(priority=2, expected_power=-150.0, expected_bounds=(-200.0, -50.0))
108+
test_bounds(priority=1, expected_power=-150.0, expected_bounds=(-200.0, -50.0))
109+
110+
test_tgt_power(priority=4, power=-180.0, bounds=(-200.0, -50.0), expected=None)
111+
test_bounds(priority=1, expected_power=-150.0, expected_bounds=(-200.0, -50.0))
112+
113+
test_tgt_power(priority=4, power=50.0, bounds=(50.0, 200.0), expected=50.0)
114+
test_bounds(priority=4, expected_power=50.0, expected_bounds=(-200.0, 200.0))
115+
test_bounds(priority=3, expected_power=50.0, expected_bounds=(50.0, 200.0))
116+
test_bounds(priority=2, expected_power=50.0, expected_bounds=(50.0, 200.0))
117+
test_bounds(priority=1, expected_power=50.0, expected_bounds=(50.0, 200.0))
118+
119+
test_tgt_power(priority=4, power=0.0, bounds=(-200.0, 200.0), expected=-150.0)
120+
test_bounds(priority=4, expected_power=-150.0, expected_bounds=(-200.0, 200.0))
121+
test_bounds(priority=3, expected_power=-150.0, expected_bounds=(-200.0, 200.0))
122+
test_bounds(priority=2, expected_power=-150.0, expected_bounds=(-200.0, 200.0))
123+
test_bounds(priority=1, expected_power=-150.0, expected_bounds=(-200.0, 200.0))
124+
125+
test_tgt_power(priority=3, power=0.0, bounds=(-200.0, 200.0), expected=None)
126+
test_bounds(priority=3, expected_power=-150.0, expected_bounds=(-200.0, 200.0))
127+
test_bounds(priority=2, expected_power=-150.0, expected_bounds=(-200.0, 200.0))
128+
test_bounds(priority=1, expected_power=-150.0, expected_bounds=(-200.0, 200.0))
129+
130+
test_tgt_power(priority=2, power=50.0, bounds=(-100, 100), expected=-100.0)
131+
test_bounds(priority=3, expected_power=-100.0, expected_bounds=(-200.0, 200.0))
132+
test_bounds(priority=2, expected_power=-100.0, expected_bounds=(-200.0, 200.0))
133+
test_bounds(priority=1, expected_power=-100.0, expected_bounds=(-100.0, 100.0))
134+
135+
test_tgt_power(priority=1, power=100.0, bounds=(100, 200), expected=100.0)
136+
test_bounds(priority=1, expected_power=100.0, expected_bounds=(-100.0, 100.0))
137+
138+
test_tgt_power(priority=1, power=50.0, bounds=(50, 200), expected=50.0)
139+
test_bounds(priority=1, expected_power=50.0, expected_bounds=(-100.0, 100.0))
140+
141+
test_tgt_power(priority=1, power=200.0, bounds=(50, 200), expected=100.0)
142+
test_bounds(priority=1, expected_power=100.0, expected_bounds=(-100.0, 100.0))

0 commit comments

Comments
 (0)