# Path: pyphi/cache.py
# def cache(cache={}, maxmem=config.MAXIMUM_CACHE_MEMORY_PERCENTAGE, typed=False):
#     """Memory-limited cache decorator.
# 
#     ``maxmem`` is a float between 0 and 100, inclusive, specifying the maximum
#     percentage of physical memory that the cache can use.
# 
#     If ``typed`` is ``True``, arguments of different types will be cached
#     separately. For example, f(3.0) and f(3) will be treated as distinct calls
#     with distinct results.
# 
#     Arguments to the cached function must be hashable.
# 
#     View the cache statistics named tuple (hits, misses, currsize)
#     with f.cache_info(). Clear the cache and statistics with f.cache_clear().
#     Access the underlying function with f.__wrapped__.
#     """
#     # Constants shared by all lru cache instances:
#     # Unique object used to signal cache misses.
#     sentinel = object()
#     # Build a key from the function arguments.
#     make_key = _make_key
# 
#     def decorating_function(user_function, hits=0, misses=0):
#         full = False
#         # Bound method to look up a key or return None.
#         cache_get = cache.get
# 
#         if not maxmem:
# 
#             def wrapper(*args, **kwds):
#                 # Simple caching without memory limit.
#                 nonlocal hits, misses
#                 key = make_key(args, kwds, typed)
#                 result = cache_get(key, sentinel)
#                 if result is not sentinel:
#                     hits += 1
#                     return result
#                 result = user_function(*args, **kwds)
#                 cache[key] = result
#                 misses += 1
#                 return result
# 
#         else:
# 
#             def wrapper(*args, **kwds):
#                 # Memory-limited caching.
#                 nonlocal hits, misses, full
#                 key = make_key(args, kwds, typed)
#                 result = cache_get(key)
#                 if result is not None:
#                     hits += 1
#                     return result
#                 result = user_function(*args, **kwds)
#                 if not full:
#                     cache[key] = result
#                     # Cache is full if the total recursive usage is greater
#                     # than the maximum allowed percentage.
#                     current_process = psutil.Process(os.getpid())
#                     full = current_process.memory_percent() > maxmem
#                 misses += 1
#                 return result
# 
#         def cache_info():
#             """Report cache statistics."""
#             return _CacheInfo(hits, misses, len(cache))
# 
#         def cache_clear():
#             """Clear the cache and cache statistics."""
#             nonlocal hits, misses, full
#             cache.clear()
#             hits = misses = 0
#             full = False
# 
#         wrapper.cache_info = cache_info
#         wrapper.cache_clear = cache_clear
#         return update_wrapper(wrapper, user_function)
# 
#     return decorating_function


import numpy as np
from .cache import cache
        return None

    order = "C" if big_endian else "F"
    # For efficiency, use `ravel` (which returns a view of the array) instead
    # of `np.flatten` (which copies the whole array).
    return repertoire.squeeze().ravel(order=order)


def unflatten(repertoire, purview, N, big_endian=False):
    """Unflatten a repertoire.

    By default, the input is assumed to be in little-endian order.

    Args:
        repertoire (np.ndarray or None): A probability distribution.
        purview (Iterable[int]): The indices of the nodes whose states the
            probability is distributed over.
        N (int): The size of the network.

    Keyword Args:
        big_endian (boolean): If ``True``, assume the flat repertoire is in
            big-endian order.

    Returns:
        np.ndarray: The unflattened repertoire.
    """
    order = "C" if big_endian else "F"
    return repertoire.reshape(repertoire_shape(purview, N), order=order)



# Path: pyphi/cache.py
# def cache(cache={}, maxmem=config.MAXIMUM_CACHE_MEMORY_PERCENTAGE, typed=False):
#     """Memory-limited cache decorator.
# 
#     ``maxmem`` is a float between 0 and 100, inclusive, specifying the maximum
#     percentage of physical memory that the cache can use.
# 
#     If ``typed`` is ``True``, arguments of different types will be cached
#     separately. For example, f(3.0) and f(3) will be treated as distinct calls
#     with distinct results.
# 
#     Arguments to the cached function must be hashable.
# 
#     View the cache statistics named tuple (hits, misses, currsize)
#     with f.cache_info(). Clear the cache and statistics with f.cache_clear().
#     Access the underlying function with f.__wrapped__.
#     """
#     # Constants shared by all lru cache instances:
#     # Unique object used to signal cache misses.
#     sentinel = object()
#     # Build a key from the function arguments.
#     make_key = _make_key
# 
#     def decorating_function(user_function, hits=0, misses=0):
#         full = False
#         # Bound method to look up a key or return None.
#         cache_get = cache.get
# 
#         if not maxmem:
# 
#             def wrapper(*args, **kwds):
#                 # Simple caching without memory limit.
#                 nonlocal hits, misses
#                 key = make_key(args, kwds, typed)
#                 result = cache_get(key, sentinel)
#                 if result is not sentinel:
#                     hits += 1
#                     return result
#                 result = user_function(*args, **kwds)
#                 cache[key] = result
#                 misses += 1
#                 return result
# 
#         else:
# 
#             def wrapper(*args, **kwds):
#                 # Memory-limited caching.
#                 nonlocal hits, misses, full
#                 key = make_key(args, kwds, typed)
#                 result = cache_get(key)
#                 if result is not None:
#                     hits += 1
#                     return result
#                 result = user_function(*args, **kwds)
#                 if not full:
#                     cache[key] = result
#                     # Cache is full if the total recursive usage is greater
#                     # than the maximum allowed percentage.
#                     current_process = psutil.Process(os.getpid())
#                     full = current_process.memory_percent() > maxmem
#                 misses += 1
#                 return result
# 
#         def cache_info():
#             """Report cache statistics."""
#             return _CacheInfo(hits, misses, len(cache))
# 
#         def cache_clear():
#             """Clear the cache and cache statistics."""
#             nonlocal hits, misses, full
#             cache.clear()
#             hits = misses = 0
#             full = False
# 
#         wrapper.cache_info = cache_info
#         wrapper.cache_clear = cache_clear
#         return update_wrapper(wrapper, user_function)
# 
#     return decorating_function


# Path: pyphi/distribution.py
import numpy as np
from .cache import cache

        return None

    order = "C" if big_endian else "F"
    # For efficiency, use `ravel` (which returns a view of the array) instead
    # of `np.flatten` (which copies the whole array).
    return repertoire.squeeze().ravel(order=order)


def unflatten(repertoire, purview, N, big_endian=False):
    """Unflatten a repertoire.

    By default, the input is assumed to be in little-endian order.

    Args:
        repertoire (np.ndarray or None): A probability distribution.
        purview (Iterable[int]): The indices of the nodes whose states the
            probability is distributed over.
        N (int): The size of the network.

    Keyword Args:
        big_endian (boolean): If ``True``, assume the flat repertoire is in
            big-endian order.

    Returns:
        np.ndarray: The unflattened repertoire.
    """
    order = "C" if big_endian else "F"
    return repertoire.reshape(repertoire_shape(purview, N), order=order)



@cache(cache={}, maxmem=None)