U
    Kvf3  ã                   @   sH   d Z ddlZG dd„ dƒZG dd„ dƒZdd„ Zdd	d
„Zddd„ZdS )zM
Created on Thu May 15 16:36:05 2014

Author: Josef Perktold
License: BSD-3

é    Nc                   @   s<   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zed
d„ ƒZ	dS )ÚLinearConstraintsa»  Class to hold linear constraints information

    Affine constraints are defined as ``R b = q` where `R` is the constraints
    matrix and `q` are the constraints values and `b` are the parameters.

    This is in analogy to patsy's LinearConstraints class but can be pickled.

    Parameters
    ----------
    constraint_matrix : ndarray
        R matrix, 2-dim with number of columns equal to the number of
        parameters. Each row defines one constraint.
    constraint_values : ndarray
        1-dim array of constant values
    variable_names : list of strings
        parameter names, used only for display
    kwds : keyword arguments
        keywords are attached to the instance.

    c                 K   s<   || _ || _|| _|| _|| _| j |¡ | j | jf| _d S ©N)Úconstraint_matrixÚconstraint_valuesÚvariable_namesÚcoefsÚ	constantsÚ__dict__ÚupdateÚtuple)Úselfr   r   r   Úkwds© r   úA/tmp/pip-unpacked-wheel-2v6byqio/statsmodels/base/_constraints.pyÚ__init__#   s    zLinearConstraints.__init__c                 c   s   | j E d H  d S r   ©r   )r   r   r   r   Ú__iter__1   s    zLinearConstraints.__iter__c                 C   s
   | j | S r   r   )r   Úidxr   r   r   Ú__getitem__4   s    zLinearConstraints.__getitem__c                 C   sÂ   dd„ }g }t | Ž D ]¢\}}g }t || jƒD ]d\}}|dkrT|g krT||||ƒ7 }q,|dkrp|d|||ƒ 7 }q,|dk r,|d|t |¡|ƒ 7 }q,|dt| ¡ ƒ 7 }| d |¡¡ qd |¡S )	Nc                 S   s,   t  | ¡} | dkr$t| ƒd | }n|}|S )Né   z * )ÚnpÚabsÚstr)ÚvÚnameÚssr   r   r   Úprod_string8   s
    
z.LinearConstraints.__str__.<locals>.prod_stringr   z + z - z = Ú Ú
)Úzipr   r   r   r   ÚitemÚappendÚjoin)r   r   Zconstraints_stringsÚrÚqr   r   r   r   r   r   Ú__str__7   s    zLinearConstraints.__str__c                 C   s   | |j |j|jƒS )aL  class method to create instance from patsy instance

        Parameters
        ----------
        lc : instance
            instance of patsy LinearConstraint, or other instances that have
            attributes ``lc.coefs, lc.constants, lc.variable_names``

        Returns
        -------
        instance of this class

        )r   r   r   )ÚclsÚlcr   r   r   Ú
from_patsyO   s    zLinearConstraints.from_patsyN)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r%   Úclassmethodr(   r   r   r   r   r      s   r   c                   @   s*   e Zd ZdZd	dd„Zdd„ Zdd„ ZdS )
ÚTransformRestrictiona  Transformation for linear constraints `R params = q`

    Note, the transformation from the reduced to the full parameters is an
    affine and not a linear transformation if q is not zero.


    Parameters
    ----------
    R : array_like
        Linear restriction matrix
    q : arraylike or None
        values of the linear restrictions


    Notes
    -----
    The reduced parameters are not sorted with respect to constraints.

    TODO: error checking, eg. inconsistent constraints, how?

    Inconsistent constraints will raise an exception in the calculation of
    the constant or offset. However, homogeneous constraints, where q=0, will
    can have a solution where the relevant parameters are constraint to be
    zero, as in the following example::

        b1 + b2 = 0 and b1 + 2*b2 = 0, implies that b2 = 0.

    The transformation applied from full to reduced parameter space does not
    raise and exception if the constraint does not hold.
    TODO: maybe change this, what's the behavior in this case?


    The `reduce` transform is applied to the array of explanatory variables,
    `exog`, when transforming a linear model to impose the constraints.
    Nc           
   
   C   s.  t  |¡ }| _|d k	r(t  |¡ }| _|j\}}|| | _| _|| | _t  	|¡|j
 t j |¡j
¡ }t j |¡\}}|| _|| _|d d …d |…f  }| _|d d …|d …f | _|d k	r$z(|j
 t j |j
 |j
¡|j
¡¡| _W n8 t jjjk
r  }	 ztd|	f ƒ‚W 5 d }	~	X Y nX nd| _d S )Nz8possibly inconsistent constraints. error generated by
%rr   )r   Z
atleast_2dÚRÚasarrayr$   ÚshapeÚk_constrÚk_varsZ
k_unconstrZeyeÚTÚdotÚlinalgZpinvZeighÚevalsÚevecsÚLÚ
transf_matÚsolveÚconstantZLinAlgErrorÚ
ValueError)
r   r/   r$   r2   r3   Úmr7   r8   r9   Úer   r   r   r   †   s(    

 	
(ÿzTransformRestriction.__init__c                 C   s    t  |¡}| j |j¡j| j S )a·  transform from the reduced to the full parameter space

        Parameters
        ----------
        params_reduced : array_like
            parameters in the transformed space

        Returns
        -------
        params : array_like
            parameters in the original space

        Notes
        -----
        If the restriction is not homogeneous, i.e. q is not equal to zero,
        then this is an affine transform.
        )r   r0   r:   r5   r4   r<   )r   Zparams_reducedr   r   r   Úexpand«   s    
zTransformRestriction.expandc                 C   s   t  |¡}| | j¡S )a¾  transform from the full to the reduced parameter space

        Parameters
        ----------
        params : array_like
            parameters or data in the original space

        Returns
        -------
        params_reduced : array_like
            parameters in the transformed space

        This transform can be applied to the original parameters as well
        as to the data. If params is 2-d, then each row is transformed.
        )r   r0   r5   r:   )r   Úparamsr   r   r   ÚreduceÀ   s    
zTransformRestriction.reduce)N)r)   r*   r+   r,   r   r@   rB   r   r   r   r   r.   a   s   $
%r.   c                 C   s@   |  |¡  |j¡}|  |j¡  tj ||  | ¡| ¡¡}| | S )a¢  find the parameters that statisfy linear constraint from unconstrained

    The linear constraint R params = q is imposed.

    Parameters
    ----------
    params : array_like
        unconstrained parameters
    Sinv : ndarray, 2d, symmetric
        covariance matrix of the parameter estimate
    R : ndarray, 2d
        constraint matrix
    q : ndarray, 1d
        values of the constraint

    Returns
    -------
    params_constraint : ndarray
        parameters of the same length as params satisfying the constraint

    Notes
    -----
    This is the exact formula for OLS and other linear models. It will be
    a local approximation for nonlinear models.

    TODO: Is Sinv always the covariance matrix?
    In the linear case it can be (X'X)^{-1} or sigmahat^2 (X'X)^{-1}.

    My guess is that this is the point in the subspace that satisfies
    the constraint that has minimum Mahalanobis distance. Proof ?
    )r5   r4   r   r6   r;   )rA   ZSinvr/   r$   ZrsrZ	reductionr   r   r   Útransform_params_constraintÔ   s    !&rC   c                 C   sö   | }|dkri }|| }}|j |j }}	t||ƒ}
|
 |	¡}|	 |
j ¡ ¡}t|dƒr`||j7 }|dk	rr|
 |¡}ddl	}| 	| 
¡ ¡}d|kr–|d= |j||fd|i|—Ž}|jf d|i|—Ž}|
 |j¡ ¡ }|
j | ¡ ¡ |
jj¡}|||fS )a4  fit model subject to linear equality constraints

    The constraints are of the form   `R params = q`
    where R is the constraint_matrix and q is the vector of constraint_values.

    The estimation creates a new model with transformed design matrix,
    exog, and converts the results back to the original parameterization.


    Parameters
    ----------
    model: model instance
        An instance of a model, see limitations in Notes section
    constraint_matrix : array_like, 2D
        This is R in the linear equality constraint `R params = q`.
        The number of columns needs to be the same as the number of columns
        in exog.
    constraint_values :
        This is `q` in the linear equality constraint `R params = q`
        If it is a tuple, then the constraint needs to be given by two
        arrays (constraint_matrix, constraint_value), i.e. (R, q).
        Otherwise, the constraints can be given as strings or list of
        strings.
        see t_test for details
    start_params : None or array_like
        starting values for the optimization. `start_params` needs to be
        given in the original parameter space and are internally
        transformed.
    **fit_kwds : keyword arguments
        fit_kwds are used in the optimization of the transformed model.

    Returns
    -------
    params : ndarray ?
        estimated parameters (in the original parameterization
    cov_params : ndarray
        covariance matrix of the parameter estimates. This is a reverse
        transformation of the covariance matrix of the transformed model given
        by `cov_params()`
        Note: `fit_kwds` can affect the choice of covariance, e.g. by
        specifying `cov_type`, which will be reflected in the returned
        covariance.
    res_constr : results instance
        This is the results instance for the created transformed model.


    Notes
    -----
    Limitations:

    Models where the number of parameters is different from the number of
    columns of exog are not yet supported.

    Requires a model that implement an offset option.
    NÚoffsetr   Ústart_params)ÚendogÚexogr.   rB   r5   r<   ZsqueezeÚhasattrrD   ÚcopyZ_get_init_kwdsÚ	__class__Úfitr@   rA   r:   Ú
cov_paramsr4   )Úmodelr   r   rE   Úfit_kwdsr   r/   r$   rF   rG   ZtransfZexogp_strD   rI   Z	init_kwdsZ
mod_constrÚ
res_constrZparams_origrL   r   r   r   Úfit_constrainedû   s*    :





rP   c                 K   sÜ   | }ddl m} ||jƒ |¡}|j|j }}t|||||d\}	}
}|j|	ddd}|	|j_	|
|j_
| dd¡}|dkrŠ|
|j |j_nd|j_t|ƒ}|j j|7  _|j j|8  _t |¡|j_||j_||j_|S )	aÃ  fit_constraint that returns a results instance

    This is a development version for fit_constrained methods or
    fit_constrained as standalone function.

    It will not work correctly for all models because creating a new
    results instance is not standardized for use outside the `fit` methods,
    and might need adjustements for this.

    This is the prototype for the fit_constrained method that has been added
    to Poisson and GLM.
    r   )Ú
DesignInfo)rE   rN   F)rE   ÚmaxiterZwarn_convergenceÚcov_typeZ	nonrobustN)ZpatsyrQ   Z
exog_namesZlinear_constraintr   r   rP   rK   Z_resultsrA   Zcov_params_defaultÚgetZscaleZnormalized_cov_paramsÚlenZdf_residZdf_modelr   r(   Úconstraintsr2   Zresults_constrained)rM   rV   rE   rN   r   rQ   r'   r/   r$   rA   ZcovrO   ÚresrS   r2   r   r   r   Úfit_constrained_wrapX  s0    þÿrX   )NN)N)r,   Znumpyr   r   r.   rC   rP   rX   r   r   r   r   Ú<module>   s   Ts(   ÿ
]