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"

Piecewise schedule

34class Piecewise(Schedule):

Initialize

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

Find 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])