@@ -43,9 +43,15 @@ def _clamp_to_bounds( # pylint: disable=too-many-return-statements
4343 lower_bound : Power ,
4444 upper_bound : Power ,
4545 exclusion_bounds : timeseries .Bounds [Power ] | None ,
46- ) -> Power :
46+ ) -> tuple [ Power | None , Power | None ] :
4747 """Clamp the given value to the given bounds.
4848
49+ When the given value can falls within the exclusion zone, and can be clamped to
50+ both sides, both options will be returned.
51+
52+ When the given value falls outside the usable bounds and can be clamped only to
53+ one side, only that option will be returned.
54+
4955 Args:
5056 value: The value to clamp.
5157 lower_bound: The lower bound to clamp to.
@@ -65,29 +71,27 @@ def _clamp_to_bounds( # pylint: disable=too-many-return-statements
6571 lower_bound , upper_bound , exclusion_bounds
6672 ):
6773 case (True , True ):
68- return Power . zero ()
74+ return None , None
6975 case (True , False ):
7076 if value < exclusion_bounds .upper :
71- return exclusion_bounds .upper
77+ return None , exclusion_bounds .upper
7278 case (False , True ):
7379 if value > exclusion_bounds .lower :
74- return exclusion_bounds .lower
80+ return exclusion_bounds .lower , None
7581
7682 # If the given value is outside the given bounds, clamp it to the closest bound.
7783 if value < lower_bound :
78- return lower_bound
84+ return lower_bound , None
7985 if value > upper_bound :
80- return upper_bound
86+ return None , upper_bound
8187
8288 # If the given value is within the exclusion bounds and the exclusion bounds are
8389 # within the given bounds, clamp the given value to the closest exclusion bound.
8490 if exclusion_bounds is not None :
8591 if exclusion_bounds .lower < value < exclusion_bounds .upper :
86- if value - exclusion_bounds .lower < exclusion_bounds .upper - value :
87- return exclusion_bounds .lower
88- return exclusion_bounds .upper
92+ return exclusion_bounds .lower , exclusion_bounds .upper
8993
90- return value
94+ return value , value
9195
9296
9397def _check_exclusion_bounds_overlap (
@@ -217,12 +221,23 @@ def _calc_target_power(
217221 if upper_bound < lower_bound :
218222 break
219223 if next_proposal .preferred_power :
220- target_power = _clamp_to_bounds (
224+ match _clamp_to_bounds (
221225 next_proposal .preferred_power ,
222226 lower_bound ,
223227 upper_bound ,
224228 exclusion_bounds ,
225- )
229+ ):
230+ case (None , power ) | (power , None ) if power :
231+ target_power = power
232+ case (power_low , power_high ) if power_low and power_high :
233+ if (
234+ power_high - next_proposal .preferred_power
235+ < next_proposal .preferred_power - power_low
236+ ):
237+ target_power = power_high
238+ else :
239+ target_power = power_low
240+
226241 proposal_lower = next_proposal .bounds .lower or lower_bound
227242 proposal_upper = next_proposal .bounds .upper or upper_bound
228243 # If the bounds from the current proposal are fully within the exclusion
0 commit comments