o
    0Gf                     @   s:   d Z ddlZddlmZ ddlmZmZ G dd dZdS )zL
Created on Sun May 10 08:23:48 2015

Author: Josef Perktold
License: BSD-3
    N   )NonePenalty)approx_fprime_csapprox_fprimec                       s   e Zd ZdZ fddZdddZd fdd	Zd fd	d
	ZdddZd fdd	Z	d fdd	Z
dddZd fdd	Zd fdd	Z  ZS )PenalizedMixina  Mixin class for Maximum Penalized Likelihood

    Parameters
    ----------
    args and kwds for the model super class
    penal : None or instance of Penalized function class
        If penal is None, then NonePenalty is used.
    pen_weight : float or None
        factor for weighting the penalization term.
        If None, then pen_weight is set to nobs.


    TODO: missing **kwds or explicit keywords

    TODO: do we adjust the inherited docstrings?
    We would need templating to add the penalization parameters
    c                    s   | dd | _| dd | _t j|i | | jd u r"t| j| _| jd u r.t | _d| _| j	ddg t
| dg | _| j	ddg d S )Npenal
pen_weightr   _null_drop_keys)popr   r   super__init__lenZendogr   Z
_init_keysextendgetattrr	   )selfargskwds	__class__ ;lib/python3.10/site-packages/statsmodels/base/_penalized.pyr       s   

zPenalizedMixin.__init__Nc                 K   s2   |d u rt | dr| |}| |}|S d}|S )NZ	scaletyper   )hasattrZpredictZestimate_scale)r   paramsscaler   Zmur   r   r   _handle_scale7   s   


zPenalizedMixin._handle_scalec                    \   |du r| j }t j|fi |}|dkr,| j|fi |}|d| | | j| 8 }|S )z3
        Log-likelihood of model at params
        Nr   r   )r   r   logliker   r   func)r   r   r   r   llfr   r   r   r   r   C      zPenalizedMixin.loglikec                    n   |du r| j }t j|fi |}t|jd }|dkr5| j|fi |}|d| | | | j| 8 }|S )z@
        Log-likelihood of model observations at params
        Nr   r   )r   r   
loglikeobsfloatshaper   r   r   )r   r   r   r   r   Znobs_llfr   r   r   r   r!   Q   s    zPenalizedMixin.loglikeobsfdc                    sN   du rj  fdd}|dkrt||S |dkr#t||ddS td)	z4score based on finite difference derivative
        Nc                       j | fdi S Nr   r   pr   r   r   r   r   <lambda>g       z.PenalizedMixin.score_numdiff.<locals>.<lambda>csr$   T)Zcenteredz-method not recognized, should be "fd" or "cs")r   r   r   
ValueError)r   r   r   methodr   r   r   r*   r   score_numdiffa   s   
zPenalizedMixin.score_numdiffc                    r   )z-
        Gradient of model at params
        Nr   r   )r   r   scorer   r   deriv)r   r   r   r   scr   r   r   r   r1   p   r   zPenalizedMixin.scorec                    r    )z:
        Gradient of model observations at params
        Nr   r   )r   r   	score_obsr"   r#   r   r   r2   )r   r   r   r   r3   Znobs_scr   r   r   r   r4   ~   s    zPenalizedMixin.score_obsc                    s4   du rj  fdd}ddlm} |||S )z6hessian based on finite difference derivative
        Nc                    r%   r&   r'   r(   r*   r   r   r+      r,   z0PenalizedMixin.hessian_numdiff.<locals>.<lambda>r   )approx_hess)r   statsmodels.tools.numdiffr5   )r   r   r   r   r   r5   r   r*   r   hessian_numdiff   s
   
zPenalizedMixin.hessian_numdiffc                    s   |du r| j }t j|fi |}|dkrB| j|fi |}| j|}|jdkr8|d| t||  8 }|S |d| | | 8 }|S )z,
        Hessian of model at params
        Nr   r   )	r   r   hessianr   r   Zderiv2ndimnpZdiag)r   r   r   r   Zhessr   hr   r   r   r8      s   
zPenalizedMixin.hessianc           
         s   ddl m} ddlm} t| ||fr|ddi |du r d}|du r&d}t jdd|i|}|du r7|S |d	u r=d
}t	t
|j|k d }t	t
|j|kd }| rf| j|fi |}	|	S |S )a  minimize negative penalized log-likelihood

        Parameters
        ----------
        method : None or str
            Method specifies the scipy optimizer as in nonlinear MLE models.
        trim : {bool, float}
            Default is False or None, which uses no trimming.
            If trim is True or a float, then small parameters are set to zero.
            If True, then a default threshold is used. If trim is a float, then
            it will be used as threshold.
            The default threshold is currently 1e-4, but it will change in
            future and become penalty function dependent.
        kwds : extra keyword arguments
            This keyword arguments are treated in the same way as in the
            fit method of the underlying model class.
            Specifically, additional optimizer keywords and cov_type related
            keywords can be added.
        r   )GLMGam)GLMZmax_start_irlsNZbfgsFr/   Tg-C6?r   )Z*statsmodels.gam.generalized_additive_modelr<   Z+statsmodels.genmod.generalized_linear_modelr=   
isinstanceupdater   fitr:   Znonzeroabsr   anyZ
_fit_zeros)
r   r/   Ztrimr   r<   r=   resZ
drop_indexZ
keep_indexZres_auxr   r   r   r@      s&   zPenalizedMixin.fit)N)Nr$   )NN)__name__
__module____qualname____doc__r   r   r   r!   r0   r1   r4   r7   r8   r@   __classcell__r   r   r   r   r      s    



r   )	rG   Znumpyr:   Z
_penaltiesr   r6   r   r   r   r   r   r   r   <module>   s
    