forked from philharmonic/philharmonic
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathenvironment.py
More file actions
161 lines (129 loc) · 5.42 KB
/
Copy pathenvironment.py
File metadata and controls
161 lines (129 loc) · 5.42 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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import pandas as pd
import numpy as np
import inputgen
def cleaned_requests(requests):
"""return requests with simultaneous boot & delete actions removed"""
times = []
values = []
del_vms = set([req.vm for req in requests.values if req.what == 'delete'])
boot_vms = set([req.vm for req in requests.values if req.what == 'boot'])
useless_vms = boot_vms.intersection(del_vms)
for t, req in requests.iteritems():
if req.vm not in useless_vms:
values.append(req)
times.append(t)
return pd.TimeSeries(values, times)
return requests
class Environment(object):
"""provides data about all the data centers
- e.g. the temperature and prices at different location
"""
def __init__(self):
pass
def __repr__(self):
return repr({'start': self.start, 'end': self.end,
'period': self.period,
'_forecast_periods': self._forecast_periods})
def current_data(self):
"""return all the current data for all the locations"""
raise NotImplemented
class SimulatedEnvironment(Environment):
"""stores and provides simulated data about the environment
- e.g. the temperature and prices at different location
"""
def __init__(self, *args):
super(SimulatedEnvironment, self).__init__()
self._t = None
def set_time(self, t):
self._t = t
def get_time(self):
return self._t
t = property(get_time, set_time, doc="current time")
def set_period(self, period):
self._period = period
def get_period(self):
return self._period
period = property(get_period, set_period, doc="period between time steps")
def set_forecast_periods(self, num_periods):
self._forecast_periods = num_periods
def get_forecast_periods(self, num_periods):
return self._forecast_periods
forecast_periods = property(get_forecast_periods, set_forecast_periods,
doc="number of periods we get forecasts for")
def get_forecast_end(self): # TODO: parametrize
return self._t + self._forecast_periods * self._period
forecast_end = property(get_forecast_end, doc="time by which we forecast")
def current_data(self, forecast=True):
"""Return el. prices and temperatures from now to forecast_end with
optional forecasting error (for forecast=True).
"""
if forecast and hasattr(self, 'forecast_el'):
el_prices = self.forecast_el[self.t:self.forecast_end]
else:
el_prices = self.el_prices[self.t:self.forecast_end]
if self.temperature is not None:
if forecast and hasattr(self, 'forecast_temp'):
temperature = self.forecast_temp[self.t:self.forecast_end]
else:
temperature = self.temperature[self.t:self.forecast_end]
return el_prices, temperature
def _generate_forecast(self, data, SD):
return data + SD * np.random.randn(*data.shape)
def model_forecast_errors(self, SD_el, SD_temp):
self.forecast_el = self._generate_forecast(self.el_prices, SD_el)
if not self.temperature is None:
self.forecast_temp = self._generate_forecast(self.temperature, SD_temp)
class PPSimulatedEnvironment(SimulatedEnvironment):
"""Peak pauser simulation scenario with one location, el price"""
pass
# TODO: merge these two with SimulatedEnvironment
class FBFSimpleSimulatedEnvironment(SimulatedEnvironment):
"""Couple of requests in a day."""
def __init__(self, times=None, requests=None, forecast_periods=24):
"""@param times: list of time ticks"""
super(SimulatedEnvironment, self).__init__()
if not times is None:
self._times = times
self._period = times[1] - times[0]
self._t = self._times[0]
self.start = self._times[0]
self.end = self._times[-1]
if requests is not None:
self._requests = requests
else:
self._requests = inputgen.normal_vmreqs(self.start, self.end)
else:
self._t = 0
self._period = 1
self.el_prices = []
self.temperature = []
self._forecast_periods = forecast_periods
# TODO: better to make the environment immutable
def itertimes(self):
"""Generator that iterates over times. To be called by the simulator."""
for t in self._times:
self._t = t
yield t
def itertimes_immutable(self):
"""Like itertimes, but doesn't alter state. Goes from start to end."""
t = self.start
while t <= self.end:
yield t
t += self._period
def times_index(self):
"""Return a pandas Index based on the set times"""
idx = pd.date_range(start=self.start, end=self.end, freq=self.period)
return idx
def forecast_window_index(self):
"""Return a pandas Index from t to forecast_end"""
idx = pd.date_range(start=self.t, end=self.forecast_end,
freq=self.period)
return idx
def get_requests(self):
start = self.get_time()
justabit = pd.offsets.Micro(1)
end = start + self._period - justabit
#TODO: if same vm booted & deleted at once, skip it
return cleaned_requests(self._requests[start:end])
class GASimpleSimulatedEnvironment(FBFSimpleSimulatedEnvironment):
pass