1from typing import Tuple, List4class Schedule:5 def __call__(self, x):
6 raise NotImplementedError()9class Flat(Schedule):10 def __init__(self, value):
11 self.__value = value13 def __call__(self, x):
14 return self.__value16 def __str__(self):
17 return f"Schedule({self.__value})"20class Dynamic(Schedule):21 def __init__(self, value):
22 self.__value = value24 def __call__(self, x):
25 return self.__value27 def update(self, value):
28 self.__value = value30 def __str__(self):
31 return "Dynamic"34class Piecewise(Schedule):endpoints
is list of pairs (x, y)
. The values between endpoints are linearly interpolated. y
values outside the range covered by x
are outside_value
.
39 def __init__(self, endpoints: List[Tuple[float, float]], outside_value: float = None):(x, y)
pairs should be sorted
50 indexes = [e[0] for e in endpoints]
51 assert indexes == sorted(indexes)
52
53 self._outside_value = outside_value
54 self._endpoints = endpointsy
for given x
56 def __call__(self, x):iterate through each segment
62 for (x1, y1), (x2, y2) in zip(self._endpoints[:-1], self._endpoints[1:]):interpolate if x
is within the segment
64 if x1 <= x < x2:
65 dx = float(x - x1) / (x2 - x1)
66 return y1 + dx * (y2 - y1)return outside value otherwise
69 return self._outside_value71 def __str__(self):
72 endpoints = ", ".join([f"({e[0]}, {e[1]})" for e in self._endpoints])
73 return f"Schedule[{endpoints}, {self._outside_value}]"76class RelativePiecewise(Piecewise):77 def __init__(self, relative_endpoits: List[Tuple[float, float]], total_steps: int):
78 endpoints = []
79 for e in relative_endpoits:
80 index = int(total_steps * e[0])
81 assert index >= 0
82 endpoints.append((index, e[1]))
83
84 super().__init__(endpoints, outside_value=relative_endpoits[-1][1])