Repository navigation
Expand file tree
/
Copy pathenvironments.py
More file actions
143 lines (98 loc) · 4.55 KB
/
Copy pathenvironments.py
File metadata and controls
143 lines (98 loc) · 4.55 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
import torch
class TabularPOMDP():
def __init__(self, p_s, p_or_s, p_s_sa, episode_length):
""" Tabular POMDP environment.
p_s: p(s) initial distribution of the latent state.
p_or_s: p(or|s) distribution of observation and reward given latent state.
p_s_sa: p(s|s,a) transition distribution of next latent state given current state and action.
episode_length: length of an episode.
"""
# POMDP dynamics
self.p_s = torch.as_tensor(p_s) # size (s_nvals,)
self.p_s_sa = torch.as_tensor(p_s_sa) # size (s_nvals, a_nvals, s_nvals)
self.p_or_s = torch.as_tensor(p_or_s) # size (s_nvals, o_nvals, r_nvals)
self.episode_length = episode_length
# sanity checks
assert self.p_s.ndim == 1
assert self.p_s_sa.ndim == 3
assert self.p_or_s.ndim == 3
assert self.p_s.shape[0] == self.p_s_sa.shape[0]
assert self.p_s.shape[0] == self.p_s_sa.shape[2]
assert self.p_s.shape[0] == self.p_or_s.shape[0]
self.s_nvals = self.p_s.shape[0]
self.a_nvals = self.p_s_sa.shape[1]
self.o_nvals = self.p_or_s.shape[1]
self.r_nvals = self.p_or_s.shape[2]
# Initialize current time step
self.current_step = -1
def reset(self):
self.current_step = 0
# Reset the environment to an initial state sampled from p(s)
self.s = torch.distributions.categorical.Categorical(probs=self.p_s,).sample()
# Sample o, r from p(o,r|s)
o, r, done, info = self.sample_ordi_s()
return o, r, done, info
def step(self, action):
""" Take a step in the environment
1. Generate new hidden state p(s|s,a)
2. Get Obeservation, Reward from p(o,r|s)
3. Update done flag
3. Return obs, reward, done, info
"""
self.current_step += 1
# Sample next hidden state from current state and action p(s|s,a)
self.s = torch.distributions.categorical.Categorical(probs=self.p_s_sa[self.s, action],).sample()
# Sample reward and observation from current hidden state p(o,r|s)
o, r, done, info = self.sample_ordi_s()
return o, r, done, info
def sample_ordi_s(self):
# Sample from joint distribution
_or = torch.distributions.categorical.Categorical(probs=self.p_or_s[self.s].view(-1),).sample()
o = _or // self.p_or_s.shape[2]
r = _or % self.p_or_s.shape[2]
done = torch.tensor(self.current_step >= self.episode_length, dtype=torch.long)
info = {"state": self.s}
return o, r, done, info
class RewardMapWrapper():
def __init__(self, env, reward_map):
self.env = env
self.reward_map = reward_map
def reset(self):
o, r, d, info = self.env.reset()
# return mapped reward
return o, self.reward_map[r], d, info
def step(self, action):
o, r, d, info = self.env.step(action)
# return mapped reward
return o, self.reward_map[r], d, info
class BeliefStateWrapper():
def __init__(self, env, belief_model, with_done=False):
self.env = env
self.belief_model = belief_model
self.with_done = with_done
def update_belief_state(self, a, o, r, d):
''' Update the proba distribution of hidden state representation p(s|h).
Ie the distribution of the hidden state estimated s given the whole history '''
with torch.no_grad():
self.belief_state = self.belief_model.log_q_s_h(
regime=torch.tensor(1.).unsqueeze(0), # interventional regime
loq_q_sprev_hprev=None if self.belief_state is None else self.belief_state.unsqueeze(0),
a=None if a is None else torch.as_tensor(a).unsqueeze(0),
o=o.unsqueeze(0),
r=r.unsqueeze(0),
d=d.unsqueeze(0),
with_done=self.with_done).squeeze(0)
def reset(self):
''' Reset hidden state belief '''
o, r, d, info = self.env.reset()
self.belief_state = None
self.update_belief_state(None, o, r, d)
# return belief state as the observation
return torch.exp(self.belief_state), r, d, info
def step(self, action):
''' Take a step, update hidden state beliefs and
return the hidden state p(s|h) as observation '''
o, r, d, info = self.env.step(action)
self.update_belief_state(action, o, r, d)
# return belief state as the observation
return torch.exp(self.belief_state), r, d, info