# 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 json
import numpy as np
import pyphi
from pyphi import cache


def dumps(obj, **user_kwargs):
    """Serialize ``obj`` as JSON-formatted stream."""
    return json.dumps(obj, **_encoder_kwargs(user_kwargs))


def dump(obj, fp, **user_kwargs):
    """Serialize ``obj`` as a JSON-formatted stream and write to ``fp`` (a
    ``.write()``-supporting file-like object.
    """
    return json.dump(obj, fp, **_encoder_kwargs(user_kwargs))


def _check_version(version):
    """Check whether the JSON version matches the PyPhi version."""
    if version != pyphi.__version__:
        raise pyphi.exceptions.JSONVersionError(
            "Cannot load JSON from a different version of PyPhi. "
            "JSON version = {0}, current version = {1}.".format(
                version, pyphi.__version__
            )
        )


def _is_model(dct):
    """Check if ``dct`` is a PyPhi model serialization."""
    return CLASS_KEY in dct



# 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/jsonify.py
import json
import numpy as np
import pyphi
from pyphi import cache



def dumps(obj, **user_kwargs):
    """Serialize ``obj`` as JSON-formatted stream."""
    return json.dumps(obj, **_encoder_kwargs(user_kwargs))


def dump(obj, fp, **user_kwargs):
    """Serialize ``obj`` as a JSON-formatted stream and write to ``fp`` (a
    ``.write()``-supporting file-like object.
    """
    return json.dump(obj, fp, **_encoder_kwargs(user_kwargs))


def _check_version(version):
    """Check whether the JSON version matches the PyPhi version."""
    if version != pyphi.__version__:
        raise pyphi.exceptions.JSONVersionError(
            "Cannot load JSON from a different version of PyPhi. "
            "JSON version = {0}, current version = {1}.".format(
                version, pyphi.__version__
            )
        )


def _is_model(dct):
    """Check if ``dct`` is a PyPhi model serialization."""
    return CLASS_KEY in dct



class _ObjectCache(cache.DictCache):