#LRUCacheUnhashable
#own implementation of LRU cache to handle unhashable lists
from collections import OrderedDict
from modules.config import VERBOSE, CACHE_MAX_SIZE
from typing import Callable, Optional
[docs]
class LRUCacheUnhashable:
"""
A decorator class that caches results for functions with unhashable arguments.
Uses an OrderedDict to implement a simple LRU eviction policy.
"""
def __init__(self,
orig_func: Optional[Callable] = None,
maxsize: int = CACHE_MAX_SIZE,
):
"""initialisation"""
self.orig_func = orig_func
self.maxsize = maxsize
self.cache = OrderedDict()
self.cache_hits = 0
self.cache_misses = 0
def __call__(self,
bit_string_list: list[int],
) -> float:
"""Call wrapper and return result"""
key = self.list_to_bit_string(bit_string_list)
if key in self.cache:
self.cache_hits += 1
if VERBOSE:
print(f'Reading cache with key = {key}')
print(f'Cache is now {self.cache}')
self.cache.move_to_end(key)
result = self.cache[key]
else:
self.cache_misses += 1
result = self.orig_func(bit_string_list)
self.cache[key] = result # store the result in the cache
if VERBOSE:
print(f'Updating cache with key = {key}')
if len(self.cache) > self.maxsize:
item = self.cache.popitem(last=False)
if VERBOSE:
print(f'Evicting item {item} from cache')
print(f'Cache is now {self.cache}')
return result
[docs]
@staticmethod
def list_to_bit_string(bit_string_input: list[int]) -> str:
"""Convert list in format [0,1] to bit string eg '01'"""
if isinstance(bit_string_input, list):
bit_string_list = bit_string_input
else:
raise Exception(f'{bit_string_list} is not a list')
return ''.join(map(str, bit_string_list))
[docs]
def print_cache(self):
"""Print cache"""
print(f'cache = {self.cache}')
[docs]
def print_cache_stats(self):
"""Print cache stats"""
print(f'Items in cache = {len(self.cache)}')
print(f'cache_hit = {self.cache_hits}')
print(f'cache_miss = {self.cache_misses}')
if self.cache_hits + self.cache_misses == 0:
print(f'The cache is empty - no stats available')
else:
self.cache_hit_rate = self.cache_hits/(self.cache_hits+self.cache_misses)
print(f'cache_hit_rate = {self.cache_hit_rate:.3f}')
[docs]
def report_cache_stats(self):
"""Reports cache stats"""
items = len(self.cache)
hits = self.cache_hits
misses = self.cache_misses
return items, hits, misses
[docs]
def clear_cache(self):
"""Clear cache"""
self.cache = OrderedDict()
self.cache_hits, self.cache_misses = 0, 0