Heating controller with neural thermal model written in Python
Jacek Kowalski
2018-06-24 66a9fb40efe1311b34a3cee3f83f10c6990759af
commit | author | age
425bf7 1 import datetime
JK 2
3 import gym
4 import gym.spaces
5 import matplotlib.dates
6 import matplotlib.pyplot as plot
7 import numpy
8
9 from .ArgParser import get_sliding_window_from_config
10 from .Cost import NegativeCost
11
12
13 class CentralHeatingHistoryEnv(gym.Env):
14     metadata = {'render.modes': ['human']}
15
16     def __init__(self):
17         self.config = None
18         self.model = None
19
20         self.sliding_window_adapter = None
21         self.window = None
22
23         self.cost_class = NegativeCost
24         self.cost = None
25
26         # Required by OpenAI Gym
27         self.action_space = gym.spaces.Discrete(2)
28
29     def reset(self):
30         if not self.config or not self.model:
31             raise Exception("config and model must be set before use!")
32
33         self.cost = self.cost_class()
34
35         self.sliding_window_adapter = get_sliding_window_from_config(self.config)
36         self.window = next(self.sliding_window_adapter)
37
38         observation_min = numpy.array([-50.] * self.window.get_window_size())
39         observation_max = numpy.array([50.] * self.window.get_window_size())
40
41         # Required by OpenAI Gym
42         self.observation_space = gym.spaces.Box(observation_min, observation_max, dtype=numpy.float32)
43
44         return numpy.array(self.window.get_window_values())
45
46     def step(self, action):
47         return_observation = None
48         return_cost = None
49         return_done = False
50         return_info = None
51
52         try:
53             self.window.set_current_value('mode', action)
54             next_temp_in = self.model.get_temperature(self.window.get_model_values())
55             self.window.set_next_value('temp_in', next_temp_in)
56
57             if next_temp_in > 27 or next_temp_in < 15:
58                 raise StopIteration()
59
60             self.window = next(self.sliding_window_adapter)
61             return_observation = self.window.get_window_values()
62
63             partial_cost = self.cost.add_partial_cost(self.window)
64             return_cost = sum(partial_cost.values())
65         except StopIteration:
66             return_observation = self.window.get_window_values(offset=1)
67             return_done = True
68
69         return numpy.array(return_observation), return_cost, return_done, return_info
70
71     def render(self, mode='human', close=False):
72         if close or not self.window.plot:
73             return
74
75         x = matplotlib.dates.date2num([datetime.datetime.fromtimestamp(i) for i in self.window.get_plot_data('time')])
76         for i in self.window.plot.keys():
77             if i == "time":
78                 continue
79             plot.plot_date(x, self.window.get_plot_data(i), '-', label=i)
80
81         plot.grid(True)
82         plot.legend()
83         plot.xlabel('date')
84         plot.ylabel('temperature/state')
85         plot.show(block=True)
86
87
88 class CentralHeatingInfiniteEnv(CentralHeatingHistoryEnv):
89     def __init__(self):
90         super().__init__()
91
92     def step(self, action):
93         try:
94             return super().step(action)
95         except KeyboardInterrupt:
96             return None, 0, True, None