forge/ethyr/rollouts.py (68 lines of code) (raw):
from pdb import set_trace as T
from itertools import chain
import numpy as np
from forge.blade.lib.log import Blob
#Untested function
def discountRewards(rewards, gamma=0.99):
rets, N = [], len(rewards)
discounts = np.array([gamma**i for i in range(N)])
rewards = np.array(rewards)
for idx in range(N): rets.append(sum(rewards[idx:]*discounts[:N-idx]))
return rets
def sumReturn(rewards):
return [sum(rewards) for e in rewards]
def mergeRollouts(rollouts):
atnArgs = [rollout.atnArgs for rollout in rollouts]
vals = [rollout.vals for rollout in rollouts]
rets = [rollout.returns for rollout in rollouts]
atnArgs = list(chain(*atnArgs))
atnArgs = list(zip(*atnArgs))
vals = list(chain(*vals))
rets = list(chain(*rets))
return atnArgs, vals, rets
class Rollout:
def __init__(self, returnf=discountRewards):
self.atnArgs = []
self.vals = []
self.rewards = []
self.pop_rewards = []
self.returnf = returnf
self.feather = Feather()
def step(self, atnArgs, val, reward):
self.atnArgs.append(atnArgs)
self.vals.append(val)
self.rewards.append(reward)
def finish(self):
self.rewards[-1] = -1
self.returns = self.returnf(self.rewards)
self.lifespan = len(self.rewards)
self.feather.finish()
#Rollout logger
class Feather:
def __init__(self):
self.expMap = set()
self.blob = Blob()
def scrawl(self, stim, ent, val, reward):
self.blob.annID = ent.annID
tile = self.tile(stim)
self.move(tile, ent.pos)
#self.action(arguments, atnArgs)
self.stats(val, reward)
def tile(self, stim):
R, C = stim.shape
rCent, cCent = R//2, C//2
tile = stim[rCent, cCent]
return tile
def action(self, arguments, atnArgs):
move, attk = arguments
moveArgs, attkArgs, _ = atnArgs
moveLogits, moveIdx = moveArgs
attkLogits, attkIdx = attkArgs
def move(self, tile, pos):
tile = type(tile.state)
if pos not in self.expMap:
self.expMap.add(pos)
self.blob.unique[tile] += 1
self.blob.counts[tile] += 1
def stats(self, value, reward):
self.blob.reward.append(reward)
self.blob.value.append(float(value))
def finish(self):
self.blob.finish()