o
    0Gf                     @   sv   d Z ddlZddlmZ ddlmZ ddlmZm	Z	m
Z
mZmZmZ G dd dZG dd	 d	eZG d
d deZdS )zM
Created on Wed Feb 17 15:35:23 2021

Author: Josef Perktold
License: BSD-3

    N)stats)cache_readonly)_Gridcdf2prob_gridprob2cdf_grid_eval_bernstein_dd_eval_bernstein_2d_eval_bernstein_1dc                   @   sP   e Zd ZdZdd Zedd Zedd Zdd	 Z	d
d Z
dd Zdd ZdS )BernsteinDistributiona  Distribution based on Bernstein Polynomials on unit hypercube.

    Parameters
    ----------
    cdf_grid : array_like
        cdf values on a equal spaced grid of the unit hypercube [0, 1]^d.
        The dimension of the arrays define how many random variables are
        included in the multivariate distribution.

    Attributes
    ----------
    cdf_grid : grid of cdf values
    prob_grid : grid of cell or bin probabilities
    k_dim : (int) number of components, dimension of random variable
    k_grid : (tuple) shape of cdf_grid
    k_grid_product : (int) total number of bins in grid
    _grid : Grid instance with helper methods and attributes
    c                 C   sH   t | | _}|j| _|j| _t dd | jD | _t	| j| _
d S )Nc                 S   s   g | ]}|d  qS )    ).0ir   r   Clib/python3.10/site-packages/statsmodels/distributions/bernstein.py
<listcomp>*   s    z2BernsteinDistribution.__init__.<locals>.<listcomp>)npasarraycdf_gridndimk_dimshapek_gridZprodk_grid_productr   _grid)selfr   r   r   r   __init__&   s
   zBernsteinDistribution.__init__c                 C   s   t |}t |dk st |dkrtd|jdkr$|dddf }|jd }t |dkr5|g| }dd |D }t j||dd\}}td	d |D sQJ |t	| }t
|}| |S )
ao  Create distribution instance from data using histogram binning.

        Classmethod to construct a distribution instance.

        Parameters
        ----------
        data : array_like
            Data with observation in rows and random variables in columns.
            Data can be 1-dimensional in the univariate case.
        k_bins : int or list
            Number or edges of bins to be used in numpy histogramdd.
            If k_bins is a scalar int, then the number of bins of each
            component will be equal to it.

        Returns
        -------
        Instance of a Bernstein distribution
        r   r   zdata needs to be in [0, 1]Nc                 S   s"   g | ]}t d | d|d qS )r      )r   Zlinspace)r   Znir   r   r   r   K   s   " z3BernsteinDistribution.from_data.<locals>.<listcomp>F)binsZdensityc                 S   s   g | ]}|d  dkqS )r   r   r   )r   Zeir   r   r   r   O   s    )r   r   any
ValueErrorr   r   sizeZhistogramddalllenr   )clsdataZk_binsr   r   cer   r   r   r   	from_data-   s   



zBernsteinDistribution.from_datac                 C   s   t | jd dS )N)Zprepend)r   r   )r   r   r   r   	prob_gridU   s   zBernsteinDistribution.prob_gridc                 C   s>   t |}|jdkr| jdkr|dddf }t|| j}|S )a  cdf values evaluated at x.

        Parameters
        ----------
        x : array_like
            Points of multivariate random variable at which cdf is evaluated.
            This can be a single point with length equal to the dimension of
            the random variable, or two dimensional with points (observations)
            in rows and random variables in columns.
            In the univariate case, a 1-dimensional x will be interpreted as
            different points for evaluation.

        Returns
        -------
        pdf values

        Notes
        -----
        Warning: 2-dim x with many points can be memory intensive because
        currently the bernstein polynomials will be evaluated in a fully
        vectorized computation.
        r   N)r   r   r   r   r   r   r   xcdf_r   r   r   cdfY   s
   
zBernsteinDistribution.cdfc                 C   sD   t |}|jdkr| jdkr|dddf }| jt|| j }|S )a  pdf values evaluated at x.

        Parameters
        ----------
        x : array_like
            Points of multivariate random variable at which pdf is evaluated.
            This can be a single point with length equal to the dimension of
            the random variable, or two dimensional with points (observations)
            in rows and random variables in columns.
            In the univariate case, a 1-dimensional x will be interpreted as
            different points for evaluation.

        Returns
        -------
        cdf values

        Notes
        -----
        Warning: 2-dim x with many points can be memory intensive because
        currently the bernstein polynomials will be evaluated in a fully
        vectorized computation.
        r   N)r   r   r   r   r   r   r)   r   r+   pdf_r   r   r   pdfv   s
   
zBernsteinDistribution.pdfc                 C   sb   | j dkr| S dg| j  }t|dkr|g}|D ]
}tddd||< q| jt| }t|}|S )aF  Get marginal BernsteinDistribution.

        Parameters
        ----------
        idx : int or list of int
            Index or indices of the component for which the marginal
            distribution is returned.

        Returns
        -------
        BernsteinDistribution instance for the marginal distribution.
        r   r   r   N)r   r   r   slicer   tupler
   )r   idxsliiZcdf_mZbpd_marginalr   r   r   get_marginal   s   
z"BernsteinDistribution.get_marginalc              	   C   s   t j|| j }| j}g }tt|D ]H}|| dkr]t || jj	}g }t|D ])}| j
| }	| jj| ||  }
|tjj|	|
 d |	d|
  d || d q+|t | qt |}|S )zGenerate random numbers from distribution.

        Parameters
        ----------
        nobs : int
            Number of random observations to generate.
        r   r   )r!   )r   ZrandomZmultinomialr)   Zflattenr   ranger#   Zunravel_indexr   r   r   Z
x_marginalappendr   ZbetarvsZcolumn_stackZconcatenate)r   ZnobsZrvs_mnlZk_compZrvs_mr   r3   ZrvsijnZxgiZrvsmr   r   r   r9      s"   
"

zBernsteinDistribution.rvsN)__name__
__module____qualname____doc__r   classmethodr(   r   r)   r-   r0   r6   r9   r   r   r   r   r
      s    
'
r
   c                   @   s   e Zd Zdd Zdd ZdS )BernsteinDistributionBVc                 C   s   t || j}|S N)r   r   r*   r   r   r   r-      s   zBernsteinDistributionBV.cdfc                 C   s   | j t|| j }|S rB   )r   r   r)   r.   r   r   r   r0      s   zBernsteinDistributionBV.pdfNr<   r=   r>   r-   r0   r   r   r   r   rA      s    rA   c                   @   s    e Zd ZdddZdddZdS )BernsteinDistributionUVbinomc                 C   s   t || j|d}|S N)method)r	   r   )r   r+   rG   r,   r   r   r   r-      s   zBernsteinDistributionUV.cdfc                 C   s   | j t|| j|d }|S rF   )r   r	   r)   )r   r+   rG   r/   r   r   r   r0      s   zBernsteinDistributionUV.pdfN)rE   rC   r   r   r   r   rD      s    
rD   )r?   Znumpyr   Zscipyr   Zstatsmodels.tools.decoratorsr   Zstatsmodels.distributions.toolsr   r   r   r   r   r	   r
   rA   rD   r   r   r   r   <module>   s      :