commit | author | age
|
425bf7
|
1 |
import abc |
JK |
2 |
from copy import deepcopy |
|
3 |
|
|
4 |
from numpy import binary_repr |
|
5 |
from .Env import CentralHeatingHistoryEnv |
|
6 |
from .Model import Model |
|
7 |
from .Cost import Cost |
|
8 |
from .SlidingWindow import SlidingWindow |
|
9 |
|
|
10 |
|
|
11 |
class Controller(abc.ABC): |
|
12 |
def __init__(self): |
|
13 |
pass |
|
14 |
|
|
15 |
@abc.abstractmethod |
|
16 |
def act(self, window: SlidingWindow) -> int: |
|
17 |
pass |
|
18 |
|
|
19 |
|
|
20 |
class StaticController(Controller): |
|
21 |
def __init__(self, output: int): |
|
22 |
self.output = output |
|
23 |
|
|
24 |
def act(self, window: SlidingWindow) -> int: |
|
25 |
return self.output |
|
26 |
|
|
27 |
|
|
28 |
class ThermostatController(Controller): |
|
29 |
def __init__(self, temp_min, temp_max): |
|
30 |
self.temp_min = temp_min |
|
31 |
self.temp_max = temp_max |
|
32 |
self.mode = 0 |
|
33 |
|
|
34 |
def act(self, window: SlidingWindow): |
|
35 |
temp_in = window.get_current_value('temp_in') |
|
36 |
|
|
37 |
if self.mode: |
|
38 |
if temp_in >= self.temp_max: |
|
39 |
self.mode = False |
|
40 |
return False |
|
41 |
else: |
|
42 |
return True |
|
43 |
|
|
44 |
if temp_in <= self.temp_min: |
|
45 |
self.mode = True |
|
46 |
return True |
|
47 |
|
|
48 |
return False |
|
49 |
|
|
50 |
|
|
51 |
class ReplayController(Controller): |
|
52 |
def act(self, window: SlidingWindow): |
|
53 |
return window.get_current_value('mode') |
|
54 |
|
|
55 |
|
|
56 |
class CostController(Controller): |
|
57 |
def __init__(self, model: Model, cost_calculator_class, *args, **kwargs): |
|
58 |
self.model = model |
|
59 |
self.cost_calculator_class = cost_calculator_class |
|
60 |
|
|
61 |
def act(self, window: SlidingWindow): |
|
62 |
saved_mode = window.get_current_value('mode') |
|
63 |
saved_temp = window.get_next_value('temp_in') |
|
64 |
|
|
65 |
window.set_current_value('mode', 0) |
|
66 |
window.set_next_value('temp_in', self.model.get_temperature(window.get_model_values())) |
|
67 |
cost_no = self.cost_calculator_class().compute_partial_cost(window) |
|
68 |
cost_no = sum(cost_no.values()) |
|
69 |
window.set_current_value('mode', 1) |
|
70 |
window.set_next_value('temp_in', self.model.get_temperature(window.get_model_values())) |
|
71 |
cost_yes = self.cost_calculator_class().compute_partial_cost(window) |
|
72 |
cost_yes = sum(cost_yes.values()) |
|
73 |
|
|
74 |
window.set_current_value('mode', saved_mode) |
|
75 |
window.set_next_value('temp_in', saved_temp) |
|
76 |
return cost_yes < cost_no |
|
77 |
|
|
78 |
|
|
79 |
class BruteForceController(CostController): |
|
80 |
def act(self, window: SlidingWindow): |
|
81 |
future_values = window.future_values - window.model_future_values |
|
82 |
|
|
83 |
last_mode = window.get_previous_value('mode') |
|
84 |
|
|
85 |
best_cost = float('+inf') |
|
86 |
best_option = None |
|
87 |
|
|
88 |
for i in range(1 << future_values): |
|
89 |
test_modes = binary_repr(i, future_values) |
|
90 |
test_diffs = (-0.02, 0.02) |
|
91 |
test_costs = [None] * len(test_diffs) |
|
92 |
for i, diff in enumerate(test_diffs): |
|
93 |
test_window = window.copy(plot=False) |
|
94 |
test_costs[i] = self.cost_calculator_class() |
|
95 |
for mode in test_modes: |
|
96 |
mode = int(mode) |
|
97 |
test_window.set_current_value('mode', mode) |
|
98 |
model_calc = self.model.get_temperature(test_window.get_model_values()) |
|
99 |
model_calc += diff |
|
100 |
test_window.set_next_value('temp_in', model_calc) |
|
101 |
test_window.set_next_value('temp_out', test_window.get_next_value('temperature')) |
|
102 |
test_costs[i].add_partial_cost(test_window) |
|
103 |
test_window.next() |
|
104 |
test_cost = max(*test_costs) |
|
105 |
if test_cost.total() < best_cost or (test_cost.total() == best_cost and int(test_modes[0]) == last_mode): |
|
106 |
best_cost = test_cost.total() |
|
107 |
best_option = test_modes |
|
108 |
return int(best_option[0]) |
|
109 |
|
|
110 |
|
|
111 |
def simulate(env: CentralHeatingHistoryEnv, controller: Controller, render=True): |
|
112 |
state, reward, done, info = env.reset(), 0, False, None |
|
113 |
while not done: |
|
114 |
action = controller.act(env.window) |
|
115 |
state, reward, done, info = env.step(action) |
|
116 |
|
|
117 |
|
|
118 |
print(env.cost) |
|
119 |
if render: |
|
120 |
env.render() |