# Path: ndd/estimators.py
# class Nsb(EntropyEstimator):
#     """
#     Nemenman-Shafee-Bialek (NSB) entropy estimator.
# 
#     The estimate depends on k (the alphabet size).
# 
#     Parameters
#     ----------
#     alpha : float, optional
#         Concentration parameter. alpha > 0.0.
#         If alpha is passed, use a single Dirichlet prior
#         (Wolpert-Wolf estimator).
#         Default: use a mixture-of-Dirichlets prior (NSB estimator).
# 
#     Notes
#     -----
#     @inproceedings{nemenman2002entropy,
#       title={Entropy and inference, revisited},
#       author={Nemenman, Ilya and Shafee, Fariel and Bialek, William},
#       booktitle={Advances in neural information processing systems},
#       pages={471--478},
#       year={2002}
#     }
# 
#     @article{nemenman2004entropy,
#       title={Entropy and information in neural spike trains: Progress on the sampling problem},
#       author={Nemenman, Ilya and Bialek, William and Van Steveninck, Rob De Ruyter},
#       journal={Physical Review E},
#       volume={69},
#       number={5},
#       pages={056111},
#       year={2004},
#       publisher={APS}
#     }
# 
#     """
# 
#     def __init__(self, alpha=None):
#         super(Nsb, self).__init__()
#         if alpha:
#             self.alpha = self.check_alpha(alpha)
#         else:
#             self.alpha = None
# 
#     @fit_function
#     def fit(self, nk, k=None, zk=None):
#         if k is None:
#             raise NddError('NSB estimator needs k')
#         if k == 1:
#             self.estimate_, self.err_ = PZERO, PZERO
#             return self
# 
#         if self.alpha is None:
#             if zk is not None:
#                 self.estimate_, self.err_ = ndd.fnsb.nsb_from_multiplicities(
#                     nk, zk, k)
#             else:
#                 self.estimate_, self.err_ = ndd.fnsb.nsb(nk, k)
#         else:  # wolpert-wolf estimator
#             estimator = WolpertWolf(self.alpha).fit(nk=nk, k=k, zk=zk)
#             self.estimate_ = estimator.estimate_
#             self.err_ = estimator.err_
#         return self
# 
# class Plugin(EntropyEstimator):
#     """Plugin (maximum likelihood) entropy estimator.
# 
#     Insert the maximum likelihood estimate of the PMF from empirical
#     frequencies over bins into the entropy definition.
#     For alpha > 0, the estimate depends on k (the alphabet size).
# 
#     Parameters
#     ----------
#     alpha : float
#         Add alpha pseudocounts to the each frequency count. alpha >= 0.
#         Defaults to zero pseudocounts (plugin estimator).
# 
#     Returns
#     -------
#     float
#         Entropy estimate.
# 
#     """
# 
#     def __init__(self, alpha=None):
#         super(Plugin, self).__init__()
#         if alpha:
#             self.alpha = self.check_alpha(alpha)
#         else:
#             self.alpha = None
# 
#     @fit_function
#     def fit(self, nk, k=None, zk=None):
#         self.err_ = numpy.inf
#         if zk is not None:
#             if k is None:
#                 k = numpy.sum(zk[nk > 0])
#             if k == 1:
#                 self.estimate_, self.err_ = PZERO, PZERO
#                 return self
#             if self.alpha:
#                 self.estimate_ = ndd.fnsb.pseudo_from_multiplicities(
#                     nk, zk, k, self.alpha)
#             else:
#                 self.estimate_ = ndd.fnsb.plugin_from_multiplicities(nk, zk)
#         else:
#             if k is None:
#                 k = numpy.sum(nk > 0)
#             if k == 1:
#                 self.estimate_, self.err_ = PZERO, PZERO
#                 return self
#             if self.alpha:
#                 self.estimate_ = ndd.fnsb.pseudo(nk, k, self.alpha)
#             else:
#                 self.estimate_ = ndd.fnsb.plugin(nk)
#         return self


import itertools
import json
import sys
import numpy
import numpy.random as random
import pytest
import ndd
from ndd.estimators import Nsb, Plugin
"""Prepare test .json files."""
# pylint: disable=missing-docstring



SEED = 123


def approx(a, rel=1.e-5, abs=1.e-3):  # pylint: disable=redefined-builtin
    """Wrap pytest approx. Parms values from numpy.isclose()"""
    return pytest.approx(a, rel=rel, abs=abs)


def random_counts(n=None, k=None, alpha=None):
    """Sample from random multinomial."""
    random.seed(SEED)
    pp = random.dirichlet([alpha] * k)
    return random.multinomial(n, pp)


def estimator_prms():
    return [
        {},  # Nsb
        {
            'estimator': Nsb(alpha=1.0),
        },  # Wolpert-Wolf
        {
            'estimator': Plugin(),
        },  # plugin estimator
        {

# Path: ndd/estimators.py
# class Nsb(EntropyEstimator):
#     """
#     Nemenman-Shafee-Bialek (NSB) entropy estimator.
# 
#     The estimate depends on k (the alphabet size).
# 
#     Parameters
#     ----------
#     alpha : float, optional
#         Concentration parameter. alpha > 0.0.
#         If alpha is passed, use a single Dirichlet prior
#         (Wolpert-Wolf estimator).
#         Default: use a mixture-of-Dirichlets prior (NSB estimator).
# 
#     Notes
#     -----
#     @inproceedings{nemenman2002entropy,
#       title={Entropy and inference, revisited},
#       author={Nemenman, Ilya and Shafee, Fariel and Bialek, William},
#       booktitle={Advances in neural information processing systems},
#       pages={471--478},
#       year={2002}
#     }
# 
#     @article{nemenman2004entropy,
#       title={Entropy and information in neural spike trains: Progress on the sampling problem},
#       author={Nemenman, Ilya and Bialek, William and Van Steveninck, Rob De Ruyter},
#       journal={Physical Review E},
#       volume={69},
#       number={5},
#       pages={056111},
#       year={2004},
#       publisher={APS}
#     }
# 
#     """
# 
#     def __init__(self, alpha=None):
#         super(Nsb, self).__init__()
#         if alpha:
#             self.alpha = self.check_alpha(alpha)
#         else:
#             self.alpha = None
# 
#     @fit_function
#     def fit(self, nk, k=None, zk=None):
#         if k is None:
#             raise NddError('NSB estimator needs k')
#         if k == 1:
#             self.estimate_, self.err_ = PZERO, PZERO
#             return self
# 
#         if self.alpha is None:
#             if zk is not None:
#                 self.estimate_, self.err_ = ndd.fnsb.nsb_from_multiplicities(
#                     nk, zk, k)
#             else:
#                 self.estimate_, self.err_ = ndd.fnsb.nsb(nk, k)
#         else:  # wolpert-wolf estimator
#             estimator = WolpertWolf(self.alpha).fit(nk=nk, k=k, zk=zk)
#             self.estimate_ = estimator.estimate_
#             self.err_ = estimator.err_
#         return self
# 
# class Plugin(EntropyEstimator):
#     """Plugin (maximum likelihood) entropy estimator.
# 
#     Insert the maximum likelihood estimate of the PMF from empirical
#     frequencies over bins into the entropy definition.
#     For alpha > 0, the estimate depends on k (the alphabet size).
# 
#     Parameters
#     ----------
#     alpha : float
#         Add alpha pseudocounts to the each frequency count. alpha >= 0.
#         Defaults to zero pseudocounts (plugin estimator).
# 
#     Returns
#     -------
#     float
#         Entropy estimate.
# 
#     """
# 
#     def __init__(self, alpha=None):
#         super(Plugin, self).__init__()
#         if alpha:
#             self.alpha = self.check_alpha(alpha)
#         else:
#             self.alpha = None
# 
#     @fit_function
#     def fit(self, nk, k=None, zk=None):
#         self.err_ = numpy.inf
#         if zk is not None:
#             if k is None:
#                 k = numpy.sum(zk[nk > 0])
#             if k == 1:
#                 self.estimate_, self.err_ = PZERO, PZERO
#                 return self
#             if self.alpha:
#                 self.estimate_ = ndd.fnsb.pseudo_from_multiplicities(
#                     nk, zk, k, self.alpha)
#             else:
#                 self.estimate_ = ndd.fnsb.plugin_from_multiplicities(nk, zk)
#         else:
#             if k is None:
#                 k = numpy.sum(nk > 0)
#             if k == 1:
#                 self.estimate_, self.err_ = PZERO, PZERO
#                 return self
#             if self.alpha:
#                 self.estimate_ = ndd.fnsb.pseudo(nk, k, self.alpha)
#             else:
#                 self.estimate_ = ndd.fnsb.plugin(nk)
#         return self


# Path: tests/make_test_ref.py
import itertools
import json
import sys
import numpy
import numpy.random as random
import pytest
import ndd
from ndd.estimators import Nsb, Plugin

"""Prepare test .json files."""
# pylint: disable=missing-docstring



SEED = 123


def approx(a, rel=1.e-5, abs=1.e-3):  # pylint: disable=redefined-builtin
    """Wrap pytest approx. Parms values from numpy.isclose()"""
    return pytest.approx(a, rel=rel, abs=abs)


def random_counts(n=None, k=None, alpha=None):
    """Sample from random multinomial."""
    random.seed(SEED)
    pp = random.dirichlet([alpha] * k)
    return random.multinomial(n, pp)


def estimator_prms():
    return [
        {},  # Nsb
        {
            'estimator': Nsb(alpha=1.0),
        },  # Wolpert-Wolf
        {
            'estimator': Plugin(),
        },  # plugin estimator
        {

            'estimator': Plugin(alpha=1.0),