memoization.py 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. from functools import wraps
  2. def recurrence_memo(initial):
  3. """
  4. Memo decorator for sequences defined by recurrence
  5. See usage examples e.g. in the specfun/combinatorial module
  6. """
  7. cache = initial
  8. def decorator(f):
  9. @wraps(f)
  10. def g(n):
  11. L = len(cache)
  12. if n <= L - 1:
  13. return cache[n]
  14. for i in range(L, n + 1):
  15. cache.append(f(i, cache))
  16. return cache[-1]
  17. return g
  18. return decorator
  19. def assoc_recurrence_memo(base_seq):
  20. """
  21. Memo decorator for associated sequences defined by recurrence starting from base
  22. base_seq(n) -- callable to get base sequence elements
  23. XXX works only for Pn0 = base_seq(0) cases
  24. XXX works only for m <= n cases
  25. """
  26. cache = []
  27. def decorator(f):
  28. @wraps(f)
  29. def g(n, m):
  30. L = len(cache)
  31. if n < L:
  32. return cache[n][m]
  33. for i in range(L, n + 1):
  34. # get base sequence
  35. F_i0 = base_seq(i)
  36. F_i_cache = [F_i0]
  37. cache.append(F_i_cache)
  38. # XXX only works for m <= n cases
  39. # generate assoc sequence
  40. for j in range(1, i + 1):
  41. F_ij = f(i, j, cache)
  42. F_i_cache.append(F_ij)
  43. return cache[n][m]
  44. return g
  45. return decorator