<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def memoize(fn):
 """Simple reset-able memoization decorator for functions and methods, assumes that all arguments to the function can be hashed and compared. """

    cache = {}

    @wraps(fn)
    def wrapped_fn(*args, **kwargs):
        cache_key = _memoize_cache_key(args, kwargs)
        try:
            return cache[cache_key]
        except KeyError:
            value = fn(*args, **kwargs)
            cache[cache_key] = value
            return value

    def clear_cache():
        cache.clear()

    # Needed to ensure that EnsemblRelease.clear_cache
    # is able to clear memoized values from each of its methods
    wrapped_fn.clear_cache = clear_cache
    # expose the cache so we can check if an item has already been computed
    wrapped_fn.cache = cache
    # if we want to check whether an item is in the cache, first need
    # to construct the same cache key as used by wrapped_fn
    wrapped_fn.make_cache_key = _memoize_cache_key
    return wrapped_fn