2020-07-01 15:40:40 +02:00
|
|
|
import time
|
|
|
|
import random
|
2020-07-01 16:13:56 +02:00
|
|
|
from heapq import heappush, heappop
|
2020-07-01 15:59:49 +02:00
|
|
|
|
|
|
|
|
|
|
|
class Memo(object):
|
|
|
|
def __init__(self, size=1):
|
|
|
|
"""
|
|
|
|
Create a key-value data-structure that will never exceed `size`
|
2020-07-01 16:13:56 +02:00
|
|
|
members. Memo evicts the least-recently-accessed elements from itself
|
|
|
|
before adding inserting new key-value pairs.
|
2020-07-01 15:59:49 +02:00
|
|
|
"""
|
|
|
|
if size <= 0:
|
|
|
|
raise Exception("We do not support an empty memo")
|
|
|
|
self.xs = {}
|
2020-07-01 16:13:56 +02:00
|
|
|
self.heap = [(0, None)] * size
|
2020-07-01 15:59:49 +02:00
|
|
|
|
|
|
|
def contains(self, k):
|
|
|
|
"""
|
|
|
|
Return true if key `k` exists in the Memo.
|
|
|
|
"""
|
|
|
|
return k in self.xs
|
|
|
|
|
|
|
|
def get(self, k):
|
|
|
|
"""
|
|
|
|
Return the memoized item at key `k`.
|
|
|
|
"""
|
2020-07-01 16:13:56 +02:00
|
|
|
# "touch" the element in the heap
|
2020-07-01 15:59:49 +02:00
|
|
|
return self.xs[k]
|
|
|
|
|
|
|
|
def set(self, k, v):
|
|
|
|
"""
|
|
|
|
Memoize value `v` at key `k`.
|
|
|
|
"""
|
2020-07-01 16:13:56 +02:00
|
|
|
_, to_evict = heappop(self.heap)
|
|
|
|
if to_evict != None:
|
|
|
|
del self.xs[to_evict]
|
|
|
|
heappush(self.heap, (time.time(), k))
|
2020-07-01 15:59:49 +02:00
|
|
|
self.xs[k] = v
|
|
|
|
|
|
|
|
|
2020-07-01 16:13:56 +02:00
|
|
|
memo = Memo(size=10)
|
2020-07-01 15:40:40 +02:00
|
|
|
|
|
|
|
|
|
|
|
def f(x):
|
2020-07-01 15:59:49 +02:00
|
|
|
"""
|
|
|
|
Compute some mysterious, expensive function.
|
|
|
|
"""
|
|
|
|
if memo.contains(x):
|
2020-07-01 15:40:40 +02:00
|
|
|
print("Hit.\t\tf({})".format(x))
|
2020-07-01 15:59:49 +02:00
|
|
|
return memo.get(x)
|
2020-07-01 15:40:40 +02:00
|
|
|
else:
|
|
|
|
print("Computing...\tf({})".format(x))
|
|
|
|
time.sleep(0.25)
|
|
|
|
res = random.randint(0, 10)
|
2020-07-01 15:59:49 +02:00
|
|
|
memo.set(x, res)
|
2020-07-01 15:40:40 +02:00
|
|
|
return res
|
|
|
|
|
|
|
|
|
|
|
|
[f(random.randint(0, 10)) for _ in range(10)]
|