# Path: sampyl/state.py
# class State(collections.OrderedDict):
#     """ State object for storing parameter values.
#         
#         Inherits from OrderedDict.
# 
#     """
# 
#     def tovector(self):
#         """ Return the parameter values as a flat vector. """
#         return np.hstack(self.values())
# 
#     def fromvector(self, vec):
#         """ Update the state using a numpy array. 
# 
#             :param vec: np.array for updating the state.
#         """
#         var_sizes = self.size()
#         i = 0
#         for var in self:
#             self[var] = np.squeeze(vec[i:(i+var_sizes[var])])
#             i += var_sizes[var]
#         return self
# 
#     def freeze(self):
#         """ Return a immutable tuple of the state values."""
#         return tuple(self.tovector())
# 
#     @staticmethod
#     def init_fromvector(vec, state):
#         ""
#         vals = []
#         var_sizes = state.size()
#         i = 0
#         for var in state:
#             vals.append(np.squeeze(vec[i:(i+var_sizes[var])]))
#             i += var_sizes[var]
#         return State(zip(state.keys(), vals))
# 
#     @staticmethod
#     def fromfunc(func):
#         """ Initialize a State from the arguments of a function """
#         var_names = func_var_names(func)
#         return State.fromkeys(var_names)
# 
#     def size(self):
#         return State([(var, np.size(self[var])) for var in self])
# 
#     def __add__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             return handle_number(self, other, '__add__')
#         elif isinstance(other, collections.Iterable):
#             return handle_iterable(self, other, '__add__')
#         else:
#             raise TypeError("Addition not supported for State and {}".format(other))
# 
#     def __sub__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             return handle_number(self, other, '__sub__')
#         elif isinstance(other, collections.Iterable):
#             return handle_iterable(self, other, '__sub__')
#         else:
#             raise TypeError("Subtraction not supported for State and {}".format(other))
# 
#     def __mul__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             return handle_number(self, other, '__mul__')
#         else:
#             raise TypeError("Multiplication not supported for State and {}".format(other))
# 
#     def __truediv__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             return handle_number(self, other, '__truediv__')
#         else:
#             raise TypeError("Division not supported for State and {}".format(other))
# 
#     def __radd__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             # Commutative, so nothing changes
#             return self + other
#         else:
#             raise TypeError("Can only broadcast from the left.")
# 
#     def __rmul__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             # Commutative, so nothing changes
#             return self * other
#         else:
#             raise TypeError("Can only broadcast from the left.")
# 
#     def __rsub__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             return handle_number(self, other, '__rsub__')
#         elif isinstance(other, collections.Iterable):
#             return handle_iterable(self, other, '__rsub__')
#         else:
#             raise TypeError("Subtraction not supported for State and {}".format(other))
# 
#     def __rtruediv__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             return handle_number(self, other, '__truediv__')
#         else:
#             raise TypeError("Division not supported for State and {}".format(other))


from .core import np, AUTOGRAD, auto_grad_logp
from scipy.optimize import minimize
from .state import State
            automatically if it is installed. Otherwise, you can pass in a
            gradient function to the optimizer.
        method: string
            Optimizing method, one of these or a callable function:
                'Nelder-Mead'
                'Powell'
                'CG'
                'BFGS'
                'Newton-CG'
                'Anneal (deprecated as of scipy version 0.14.0)'
                'L-BFGS-B'
                'TNC'
                'COBYLA'
                'SLSQP'
                'dogleg'
                'trust-ncg'
                custom - a callable object (added in version 0.14.0)
            If not given, chosen to be one of BFGS, L-BFGS-B, SLSQP, depending 
            if the problem has constraints or bounds.
        bounds: dict of tuples
            Tuples of bounding values for each parameter, example:
            bounds = {'x': (low, high), 'y': (low, high)}
            Use None if not bounded in a direction, ex: {'x': (0, None)}
        verbose: boolean
            Set to True to print out optimization information

    """

    # Making sure to get the keys from logp function so that arguments are
    # ordered correctly, then update from starting state.

# Path: sampyl/state.py
# class State(collections.OrderedDict):
#     """ State object for storing parameter values.
#         
#         Inherits from OrderedDict.
# 
#     """
# 
#     def tovector(self):
#         """ Return the parameter values as a flat vector. """
#         return np.hstack(self.values())
# 
#     def fromvector(self, vec):
#         """ Update the state using a numpy array. 
# 
#             :param vec: np.array for updating the state.
#         """
#         var_sizes = self.size()
#         i = 0
#         for var in self:
#             self[var] = np.squeeze(vec[i:(i+var_sizes[var])])
#             i += var_sizes[var]
#         return self
# 
#     def freeze(self):
#         """ Return a immutable tuple of the state values."""
#         return tuple(self.tovector())
# 
#     @staticmethod
#     def init_fromvector(vec, state):
#         ""
#         vals = []
#         var_sizes = state.size()
#         i = 0
#         for var in state:
#             vals.append(np.squeeze(vec[i:(i+var_sizes[var])]))
#             i += var_sizes[var]
#         return State(zip(state.keys(), vals))
# 
#     @staticmethod
#     def fromfunc(func):
#         """ Initialize a State from the arguments of a function """
#         var_names = func_var_names(func)
#         return State.fromkeys(var_names)
# 
#     def size(self):
#         return State([(var, np.size(self[var])) for var in self])
# 
#     def __add__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             return handle_number(self, other, '__add__')
#         elif isinstance(other, collections.Iterable):
#             return handle_iterable(self, other, '__add__')
#         else:
#             raise TypeError("Addition not supported for State and {}".format(other))
# 
#     def __sub__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             return handle_number(self, other, '__sub__')
#         elif isinstance(other, collections.Iterable):
#             return handle_iterable(self, other, '__sub__')
#         else:
#             raise TypeError("Subtraction not supported for State and {}".format(other))
# 
#     def __mul__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             return handle_number(self, other, '__mul__')
#         else:
#             raise TypeError("Multiplication not supported for State and {}".format(other))
# 
#     def __truediv__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             return handle_number(self, other, '__truediv__')
#         else:
#             raise TypeError("Division not supported for State and {}".format(other))
# 
#     def __radd__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             # Commutative, so nothing changes
#             return self + other
#         else:
#             raise TypeError("Can only broadcast from the left.")
# 
#     def __rmul__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             # Commutative, so nothing changes
#             return self * other
#         else:
#             raise TypeError("Can only broadcast from the left.")
# 
#     def __rsub__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             return handle_number(self, other, '__rsub__')
#         elif isinstance(other, collections.Iterable):
#             return handle_iterable(self, other, '__rsub__')
#         else:
#             raise TypeError("Subtraction not supported for State and {}".format(other))
# 
#     def __rtruediv__(self, other):
#         if isinstance(other, int) or isinstance(other, float):
#             return handle_number(self, other, '__truediv__')
#         else:
#             raise TypeError("Division not supported for State and {}".format(other))


# Path: sampyl/starting.py
from .core import np, AUTOGRAD, auto_grad_logp
from scipy.optimize import minimize
from .state import State

            automatically if it is installed. Otherwise, you can pass in a
            gradient function to the optimizer.
        method: string
            Optimizing method, one of these or a callable function:
                'Nelder-Mead'
                'Powell'
                'CG'
                'BFGS'
                'Newton-CG'
                'Anneal (deprecated as of scipy version 0.14.0)'
                'L-BFGS-B'
                'TNC'
                'COBYLA'
                'SLSQP'
                'dogleg'
                'trust-ncg'
                custom - a callable object (added in version 0.14.0)
            If not given, chosen to be one of BFGS, L-BFGS-B, SLSQP, depending 
            if the problem has constraints or bounds.
        bounds: dict of tuples
            Tuples of bounding values for each parameter, example:
            bounds = {'x': (low, high), 'y': (low, high)}
            Use None if not bounded in a direction, ex: {'x': (0, None)}
        verbose: boolean
            Set to True to print out optimization information

    """

    # Making sure to get the keys from logp function so that arguments are
    # ordered correctly, then update from starting state.

    state = State.fromfunc(logp)