Skip to content

Commit 8765f0b

Browse files
committed
Add extrnal dependency
1 parent 2eb87ad commit 8765f0b

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed

src/extern/__init__.py

Whitespace-only changes.

src/extern/tile_coding.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
"""
2+
Tile Coding Software version 3.0beta
3+
by Rich Sutton
4+
based on a program created by Steph Schaeffer and others
5+
External documentation and recommendations on the use of this code is available in the
6+
reinforcement learning textbook by Sutton and Barto, and on the web.
7+
These need to be understood before this code is.
8+
9+
This software is for Python 3 or more.
10+
11+
This is an implementation of grid-style tile codings, based originally on
12+
the UNH CMAC code (see http://www.ece.unh.edu/robots/cmac.htm), but by now highly changed.
13+
Here we provide a function, "tiles", that maps floating and integer
14+
variables to a list of tiles, and a second function "tiles-wrap" that does the same while
15+
wrapping some floats to provided widths (the lower wrap value is always 0).
16+
17+
The float variables will be gridded at unit intervals, so generalization
18+
will be by approximately 1 in each direction, and any scaling will have
19+
to be done externally before calling tiles.
20+
21+
Num-tilings should be a power of 2, e.g., 16. To make the offsetting work properly, it should
22+
also be greater than or equal to four times the number of floats.
23+
24+
The first argument is either an index hash table of a given size (created by (make-iht size)),
25+
an integer "size" (range of the indices from 0), or nil (for testing, indicating that the tile
26+
coordinates are to be returned without being converted to indices).
27+
"""
28+
29+
from math import floor, log
30+
from itertools import zip_longest
31+
32+
basehash = hash
33+
34+
35+
class IHT:
36+
"""Structure to handle collisions"""
37+
38+
def __init__(self, sizeval):
39+
self.size = sizeval
40+
self.overfullCount = 0
41+
self.dictionary = {}
42+
43+
def __str__(self):
44+
"""Prepares a string for printing whenever this object is printed"""
45+
return "Collision table:" + \
46+
" size:" + str(self.size) + \
47+
" overfullCount:" + str(self.overfullCount) + \
48+
" dictionary:" + str(len(self.dictionary)) + " items"
49+
50+
def count(self):
51+
return len(self.dictionary)
52+
53+
def fullp(self):
54+
return len(self.dictionary) >= self.size
55+
56+
def getindex(self, obj, readonly=False):
57+
d = self.dictionary
58+
if obj in d:
59+
return d[obj]
60+
elif readonly:
61+
return None
62+
size = self.size
63+
count = self.count()
64+
if count >= size:
65+
if self.overfullCount == 0: print('IHT full, starting to allow collisions')
66+
self.overfullCount += 1
67+
return basehash(obj) % self.size
68+
else:
69+
d[obj] = count
70+
return count
71+
72+
73+
def hashcoords(coordinates, m, readonly=False):
74+
if type(m) == IHT: return m.getindex(tuple(coordinates), readonly)
75+
if type(m) == int: return basehash(tuple(coordinates)) % m
76+
if m == None: return coordinates
77+
78+
79+
def tiles(ihtORsize, numtilings, floats, ints=[], readonly=False):
80+
"""returns num-tilings tile indices corresponding to the floats and ints"""
81+
qfloats = [floor(f * numtilings) for f in floats]
82+
Tiles = []
83+
for tiling in range(numtilings):
84+
tilingX2 = tiling * 2
85+
coords = [tiling]
86+
b = tiling
87+
for q in qfloats:
88+
coords.append((q + b) // numtilings)
89+
b += tilingX2
90+
coords.extend(ints)
91+
Tiles.append(hashcoords(coords, ihtORsize, readonly))
92+
return Tiles
93+
94+
95+
def tileswrap(ihtORsize, numtilings, floats, wrawidths, ints=[], readonly=False):
96+
"""returns num-tilings tile indices corresponding to the floats and ints, wrapping some floats"""
97+
qfloats = [floor(f * numtilings) for f in floats]
98+
Tiles = []
99+
for tiling in range(numtilings):
100+
tilingX2 = tiling * 2
101+
coords = [tiling]
102+
b = tiling
103+
for q, width in zip_longest(qfloats, wrapwidths):
104+
c = (q + b % numtilings) // numtilings
105+
coords.append(c % width if width else c)
106+
b += tilingX2
107+
coords.extend(ints)
108+
Tiles.append(hashcoords(coords, ihtORsize, readonly))
109+
return Tiles

0 commit comments

Comments
 (0)