1from typing import Tuple, List
4class Schedule:
5 def __call__(self, x):
6 raise NotImplementedError()
9class Flat(Schedule):
10 def __init__(self, value):
11 self.__value = value
13 def __call__(self, x):
14 return self.__value
16 def __str__(self):
17 return f"Schedule({self.__value})"
20class Dynamic(Schedule):
21 def __init__(self, value):
22 self.__value = value
24 def __call__(self, x):
25 return self.__value
27 def update(self, value):
28 self.__value = value
30 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 = endpoints
y
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_value
71 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])