Repository navigation
Expand file tree
/
Copy pathpiecewise_function.py
More file actions
94 lines (83 loc) · 3.44 KB
/
Copy pathpiecewise_function.py
File metadata and controls
94 lines (83 loc) · 3.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import numpy as np
from rocketpy.mathutils.function import Function
class PiecewiseFunction(Function):
"""Class for creating piecewise functions. These kind of functions are
defined by a dictionary of functions, where the keys are tuples that
represent the domain of the function. The domains must be disjoint.
"""
def __new__(
cls,
source,
inputs=None,
outputs=None,
interpolation="spline",
extrapolation=None,
datapoints=100,
):
"""
Creates a piecewise function from a dictionary of functions. The keys of
the dictionary must be tuples that represent the domain of the function.
The domains must be disjoint. The piecewise function will be evaluated
at datapoints points to create Function object.
Parameters
----------
source: dictionary
A dictionary of Function objects, where the keys are the domains.
inputs : list of strings
A list of strings that represent the inputs of the function.
outputs: list of strings
A list of strings that represent the outputs of the function.
interpolation: str
The type of interpolation to use. The default value is 'spline'.
extrapolation: str
The type of extrapolation to use. The default value is None.
datapoints: int
The number of points in which the piecewise function will be
evaluated to create a base function. The default value is 100.
"""
cls.__validate__source(source)
if inputs is None:
inputs = ["Scalar"]
if outputs is None:
outputs = ["Scalar"]
input_data = np.array([])
output_data = np.array([])
for lower, upper in sorted(source.keys()):
grid = np.linspace(lower, upper, datapoints)
# since intervals are disjoint and sorted, we only need to check
# if the first point is already included
if input_data.size != 0:
if lower == input_data[-1]:
grid = np.delete(grid, 0)
input_data = np.concatenate((input_data, grid))
f = Function(source[(lower, upper)])
output_data = np.concatenate((output_data, f.get_value(grid)))
return Function(
np.concatenate(([input_data], [output_data])).T,
inputs=inputs,
outputs=outputs,
interpolation=interpolation,
extrapolation=extrapolation,
)
@staticmethod
def __validate__source(source):
"""Validates that source is dictionary with non-overlapping
intervals
Parameters
----------
source : dict
A dictionary of Function objects, where the keys are the domains.
"""
# Check if source is a dictionary
if not isinstance(source, dict):
raise TypeError("source must be a dictionary")
# Check if all keys are tuples
for key in source.keys():
if not isinstance(key, tuple):
raise TypeError("keys of source must be tuples")
# Check if all domains are disjoint
for lower1, upper1 in source.keys():
for lower2, upper2 in source.keys():
if (lower1, upper1) != (lower2, upper2):
if lower1 < upper2 and upper1 > lower2:
raise ValueError("domains must be disjoint")