B
    Z                 @   sH  d Z ddlZddlmZ ddlmZmZmZ ddl	m
Z
 ddlmZmZmZ ddlmZ yddlmZ W n ek
r   d	d
 ZY nX ddlmZ dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Z G d"d# d#eZ!G d$d% d%eZ"ee"e! G d&d' d'e
Z#G d(d) d)e#Z$G d*d+ d+e#Z%dS ),a1  
Created on Wed Jul 12 09:35:35 2017

Notes
-----
Code written using below textbook as a reference.
Results are checked against the expected outcomes in the text book.

Properties:
Hyndman, Rob J., and George Athanasopoulos. Forecasting: principles and practice. OTexts, 2014.

Author: Terence L van Zyl

    N)Results)populate_wrapperunion_dictsResultsWrapper)TimeSeriesModel)basinhoppingbruteminimize)sqeuclidean)
inv_boxcoxc             C   s*   |dkr t t ||  | S t | S )Nr   )npZexpZlog1p)xZlmbda r   :lib/python3.7/site-packages/statsmodels/tsa/holtwinters.pyr      s    r   )boxcoxc             C   sp   | ||< |dd \}}}}	}
}d| }d| }|| }d|dd< d|dd< |	|d< |
|d< ||||||fS )z"Initialization for the Holt ModelsN      r   r   )r   xipylbalphabeta_l0b0phialphacbetacy_alphar   r   r   
_holt_init   s    r!   c
             C   s\   t | |||||\}
}}}}}x2td|D ]$}||d  |||d    ||< q*W t||S )zH
    Simple Exponential Smoothing
    Minimization Function
    (,)
    r   )r!   ranger
   )r   r   r   r   r   r   smnmax_seenr   r   r   r   r   r    ir   r   r   _holt__-   s    $r(   c
             C   s   t | |||||\}
}}}}}|
dkr*|	S ||
kr6|	S xrtd|D ]d}||d  |||d  ||d  |    ||< ||| ||d    |||d  |   ||< qBW t|||  |S )z^
    Multiplicative and Multiplicative Damped 
    Minimization Function
    (M,) & (Md,)
    g        r   )r!   r"   r
   )r   r   r   r   r   r   r#   r$   r%   r&   r   r   r   r   r   r    r'   r   r   r   _holt_mul_dam9   s    04r)   c
             C   s   t | |||||\}
}}}}}|
dkr*|	S ||
kr6|	S xrtd|D ]d}||d  |||d  |||d      ||< ||| ||d    || ||d    ||< qBW t|||  |S )zR
    Additive and Additive Damped 
    Minimization Function
    (A,) & (Ad,)
    g        r   )r!   r"   r
   )r   r   r   r   r   r   r#   r$   r%   r&   r   r   r   r   r   r    r'   r   r   r   _holt_add_damJ   s    04r*   c          	   C   s   | ||< |dd \}}	}
}}}|dd }d| }d|	 }d|
 }|| }|
| }d|dd< d|dd< d|dd< ||d< ||d< ||d|< ||	|
||||||f	S )z3Initialization for the Holt Winters Seasonal ModelsNr   r   r   r   )r   r   r   r   r   r   r#   r$   r   r   gammar   r   r   s0r   r   gammacr    y_gammar   r   r   _holt_win_init[   s    r/   c
          	   C   s   t | |||||||\	}
}}}}}}}}|
dkr4|	S |d|
 krD|	S xrtd|D ]d}||d  ||d   |||d    ||< ||d  ||d   |||d    ||| d < qPW t||d|d    |S )zE
    Multiplicative Seasonal 
    Minimization Function
    (,M)
    g        r   N)r/   r"   r
   )r   r   r   r   r   r   r#   r$   r%   r&   r   r   r+   r   r   r   r-   r    r.   r'   r   r   r   _holt_win__muln   s    &,8r0   c
          	   C   s   t | |||||||\	}
}}}}}}}}|
dkr4|	S |d|
 krD|	S xztd|D ]l}||d  |
||d    |||d    ||< ||d  |||d    |||d    ||| d < qPW t||d|d    |S )z?
    Additive Seasonal 
    Minimization Function
    (,A)
    g        r   N)r/   r"   r
   )r   r   r   r   r   r   r#   r$   r%   r&   r   r   r+   r   r   r   r-   r    r.   r'   r   r   r   _holt_win__add   s    &0<r1   c
          	   C   s8  t | |||||||\	}
}}}}}}}}|
| dkr8|	S ||
ksL|d|
 krP|	S xtd|D ]}||d  ||d   |||d  |||d      ||< ||| ||d    || ||d    ||< ||d  ||d  |||d     |||d    ||| d < q\W t|||  |d|d    |S )zq
    Additive and Additive Damped with Multiplicative Seasonal 
    Minimization Function
    (A,M) & (Ad,M)
    g        r   N)r/   r"   r
   )r   r   r   r   r   r   r#   r$   r%   r&   r   r   r+   r   r   r   r-   r    r.   r'   r   r   r   _holt_win_add_mul_dam   s    &&02r2   c
          	   C   s8  t | |||||||\	}
}}}}}}}}|
| dkr8|	S ||
ksL|d|
 krP|	S xtd|D ]}||d  ||d   |||d  ||d  |    ||< ||| ||d    |||d  |   ||< ||d  ||d  ||d  |   |||d    ||| d < q\W t|||  |d|d    |S )z}
    Multiplicative and Multiplicative Damped with Multiplicative Seasonal 
    Minimization Function
    (M,M) & (Md,M)
    g        r   N)r/   r"   r
   )r   r   r   r   r   r   r#   r$   r%   r&   r   r   r+   r   r   r   r-   r    r.   r'   r   r   r   _holt_win_mul_mul_dam   s    &&04r3   c
          	   C   s@  t | |||||||\	}
}}}}}}}}|
| dkr8|	S ||
ksL|d|
 krP|	S xtd|D ]}||d  |
||d    |||d  |||d      ||< ||| ||d    || ||d    ||< ||d  |||d  |||d      |||d    ||| d < q\W t|||  |d|d    |S )zk
    Additive and Additive Damped with Additive Seasonal 
    Minimization Function
    (A,A) & (Ad,A)
    g        r   N)r/   r"   r
   )r   r   r   r   r   r   r#   r$   r%   r&   r   r   r+   r   r   r   r-   r    r.   r'   r   r   r   _holt_win_add_add_dam   s    &&0Lr4   c
          	   C   s@  t | |||||||\	}
}}}}}}}}|
| dkr8|	S ||
ksL|d|
 krP|	S xtd|D ]}||d  |
||d    |||d  ||d  |    ||< ||| ||d    |||d  |   ||< ||d  |||d  ||d  |    |||d    ||| d < q\W t|| | |d|d    |S )zw
    Multiplicative and Multiplicative Damped with Additive Seasonal 
    Minimization Function
    (M,A) & (M,Ad)
    g        r   N)r/   r"   r
   )r   r   r   r   r   r   r#   r$   r%   r&   r   r   r+   r   r   r   r-   r    r.   r'   r   r   r   _holt_win_mul_add_dam   s    &&0Lr5   c                   s4   e Zd ZdZ fddZd
ddZddd	Z  ZS )HoltWintersResultsa  
    Holt Winter's Exponential Smoothing Results

    Parameters
    ----------
    model : ExponentialSmoothing instance
        The fitted model instance
    params : dictionary
        All the parameters for the Exponential Smoothing model.

    Attributes
    ----------
    specification : dictionary
        Dictionary including all attributes from the VARMAX model instance.
    params: dictionary
        All the parameters for the Exponential Smoothing model.
    fittedfcast: array
        An array of both the fitted values and forecast values.
    fittedvalues: array
        An array of the fitted values. Fitted by the Exponential Smoothing 
        model.
    fcast: array
        An array of the forecast values forecast by the Exponential Smoothing
        model.
    sse: float
        The sum of squared errors
    level: array
        An array of the levels values that make up the fitted values.
    slope: array
        An array of the slope values that make up the fitted values.
    season: array
        An array of the seaonal values that make up the fitted values.
    aic: float
        The Akaike information criterion.
    bic: float
        The Bayesian information criterion.
    aicc: float
        AIC with a correction for finite sample sizes.
    resid: array
        An array of the residuals of the fittedvalues and actual values.
    k: int
        the k parameter used to remove the bias in AIC, BIC etc.

    c                s"   |j | _ tt| j||f| d S )N)datasuperr6   __init__)selfmodelparamskwds)	__class__r   r   r9     s    zHoltWintersResults.__init__Nc             C   s   | j | j||S )a  
        In-sample prediction and out-of-sample forecasting

        Parameters
        ----------
        start : int, str, or datetime, optional
            Zero-indexed observation number at which to start forecasting, ie.,
            the first forecast is start. Can also be a date string to
            parse or a datetime type. Default is the the zeroth observation.
        end : int, str, or datetime, optional
            Zero-indexed observation number at which to end forecasting, ie.,
            the first forecast is start. Can also be a date string to
            parse or a datetime type. However, if the dates index does not
            have a fixed frequency, end must be an integer index if you
            want out of sample prediction. Default is the last observation in
            the sample.        

        Returns
        -------
        forecast : array
            Array of out of sample forecasts.
        )r;   predictr<   )r:   startendr   r   r   r?     s    zHoltWintersResults.predictr   c             C   sd   y4| j jd d }| j jd | }| j j| j||dS  tk
r^   | j jf d|i| jjS X dS )a%  
        Out-of-sample forecasts

        Parameters
        ----------
        steps : int
            The number of out of sample forecasts from the end of the
            sample.

        Returns
        -------
        forecast : array
            Array of out of sample forecasts
        r   )r@   rA   hN)r;   _indexr?   r<   
ValueError_predictfcastvalues)r:   Zstepsr@   rA   r   r   r   forecast2  s    zHoltWintersResults.forecast)NN)r   )__name__
__module____qualname____doc__r9   r?   rH   __classcell__r   r   )r>   r   r6      s   ,
r6   c               @   s>   e Zd ZddddddZeejeZdddZeejeZdS )HoltWintersResultsWrapperZrows)fittedvalueslevelresidseasonslopedates)r?   rH   N)	rI   rJ   rK   Z_attrsr   r   Z_wrap_attrsZ_methodsZ_wrap_methodsr   r   r   r   rN   J  s   rN   c                   s@   e Zd ZdZd fdd	ZdddZdd
dZdddZ  ZS )ExponentialSmoothinga  
    Holt Winter's Exponential Smoothing

    Parameters
    ----------
    endog : array-like
        Time series
    trend : {"add", "mul", "additive", "multiplicative", None}, optional
        Type of trend component.
    damped : bool, optional
        Should the trend component be damped.
    seasonal : {"add", "mul", "additive", "multiplicative", None}, optional
        Type of seasonal component.
    seasonal_periods : int, optional
        The number of seasons to consider for the holt winters.

    Returns
    -------
    results : ExponentialSmoothing class        

    Notes
    -----
    This is a full implementation of the holt winters exponential smoothing as
    per [1]. This includes all the unstable methods as well as the stable methods.
    The implementation of the library covers the functionality of the R 
    library as much as possible whilst still being pythonic.

    References
    ----------
    [1] Hyndman, Rob J., and George Athanasopoulos. Forecasting: principles and practice. OTexts, 2014.
    NFnonec	       	         s   t t| j|d |||d |dkr0ddd| }|| _|| _|dkrRddd| }|| _|dk| _|dk| _| jdks| jdkr|dk rt	d| jr| jst	d| jr|d ks|d	krt	d
|| _
nd	| _
t| j| _d S )N)missing)ZadditiveZmultiplicativeaddmul)rY   rX   g        z-Unable to correct for negative or zero valuesz#Can only dampen the trend componentr   z%Unable to detect season automatically)r8   rU   r9   trenddampedseasonaltrending	seasoninganyNotImplementedErrorseasonal_periodslenendognobs)	r:   rc   rZ   r[   r\   ra   rT   ZfreqrW   )r>   r   r   r9   z  s.    


 zExponentialSmoothing.__init__c             C   st   |dkr| j d d }| j||d\}}}}|dkrJ| jf d|i|}n| jf ddi|}|j||| d  S )a  
        Returns in-sample and out-of-sample prediction.

        Parameters
        ----------
        params : array
            The fitted model parameters.
        start : int, str, or datetime
            Zero-indexed observation number at which to start forecasting, ie.,
            the first forecast is start. Can also be a date string to
            parse or a datetime type.
        end : int, str, or datetime
            Zero-indexed observation number at which to end forecasting, ie.,
            the first forecast is start. Can also be a date string to
            parse or a datetime type.

        Returns
        -------
        predicted values : array
        NrB   r   )r@   rA   r   rC   )rD   Z_get_prediction_indexrF   fittedfcast)r:   r<   r@   rA   Zout_of_sampleZprediction_indexresr   r   r   r?     s    zExponentialSmoothing.predictTc	       ,      C   s  |}	|}
|}|}| j }| j}| j}| j}| j}| j}| j}d}|rF|nd}|dkrbd}t||}n8t|t	r||}t||}n|rt|\}}nd}|
 }t|dkrtdt| jf}t| jf}t| j| d f}td| }ttjj}|r|t| j| dk  }|rJ||||  |d|  |  nd}|d	krlt|d| | nt|d| | }nN|r|d }|d	kr|d |d  n|d |d  }g }n|d }d}g }|rn|	dk	r|	nd
t|d }|
dk	r |
n|rd| n|
} d}!|dk	r$|nd}"tttttttttd	}#|r|dk	rT|n
dd|  }!t|	dk|
dk|dkd||dko|gdg|  }$|#||f }%nr|rt|	dk|
dkddd|dko|gdg|  }$|#d|f }%n,t|	dkdddddgdg|  }$|#d }%|| |!|||"g| |dd< |$tddddddgdg|  @ }&tddddddgdg|  }'t |%|'|& |&||||||| j|f	dddd}(|(\||&< }})}*|dd \}	}
}}}}|dd }|rt!|%||$ |$||||||| j|f	|'|$ ddd}(n,t"|%||$ |$||||||| j|f	|'|$ d}(|(j#||$< |dd \}	}
}}}}|dd }|(}| j$d|	|
||||||||d}+||+j%_&|+S )aY  
        fit Holt Winter's Exponential Smoothing

        Parameters
        ----------
        smoothing_level : float, optional
            The alpha value of the simple exponential smoothing, if the value is
            set then this value will be used as the value.
        smoothing_slope :  float, optional
            The beta value of the holts trend method, if the value is
            set then this value will be used as the value.
        smoothing_seasonal : float, optional
            The gamma value of the holt winters seasonal method, if the value is
            set then this value will be used as the value.
        damping_slope : float, optional
            The phi value of the damped method, if the value is
            set then this value will be used as the value.
        optimized : bool, optional
            Should the values that have not been set above be optimized 
            automatically?
        use_boxcox : {True, False, 'log', float}, optional
            Should the boxcox tranform be applied to the data first? If 'log' 
            then apply the log. If float then use lambda equal to float.
        remove_bias : bool, optional
            Should the bias be removed from the forecast values and fitted values 
            before being returned? Does this by enforcing average residuals equal 
            to zero.
        use_basinhopping : bool, optional
            Should the opptimser try harder using basinhopping to find optimal 
            values?

        Returns
        -------
        results : HoltWintersResults class
            See statsmodels.tsa.holtwinters.HoltWintersResults

        Notes
        -----
        This is a full implementation of the holt winters exponential smoothing as
        per [1]. This includes all the unstable methods as well as the stable methods.
        The implementation of the library covers the functionality of the R 
        library as much as possible whilst still being pythonic.

        References
        ----------
        [1] Hyndman, Rob J., and George Athanasopoulos. Forecasting: principles and practice. OTexts, 2014.
        Ng      ?logg        r   z!Only 1 dimensional data supportedr   r   rY   g      ?g?gGz?)	)rY   rX   )rY   rY   )rY   N)rX   rX   )rX   rY   )rX   N)NrX   )NrY   )NNg?TF)NN)g        g      ?)g        N   )ZNsZfull_outputZfinish)argsboundsg{Gz?)Zminimizer_kwargsZstepsize)rC   smoothing_levelsmoothing_slopesmoothing_seasonaldamping_slopeinitial_levelinitial_slopeinitial_seasons
use_boxcoxlamdaremove_bias)'rc   r[   r^   r]   rZ   r\   ra   r   
isinstancefloatsqueezer   ndimr`   zerosrd   ZfinfoZdoublemaxarangemeanlistr2   r3   r0   r4   r5   r1   r*   r)   r(   Zarrayr   r   r	   r   rF   Z_resultsZmle_retvals),r:   rk   rl   rm   rn   	optimizedrr   rt   Zuse_basinhoppingr   r   r+   r   r7   r[   r^   r]   rZ   r\   r$   Zoptrs   r   r   r   r#   r   r&   r   r   r,   Z
init_alphaZ	init_betaZ
init_gammaZinit_phiZ	func_dictr   funcZtxirj   rf   ZgridZJouthwfitr   r   r   fit  s    4
.4* 
  
 
*
"

zExponentialSmoothing.fitc       -         s8  |}|}|}|}| j }| j}| j}| j}| j}| j}| j|rB|nd}|	dkr^d}
t|d}nNt|	t	rx|	}
t||
}n4|	rt|\}}
n"d}
|
 }t|dkrtdt| jf}t| jf}d| }|| |dd< |rd| }|r
d| }|| |dd< t| j| d f}t| j| d f}t| j|  d f||d< ||d< |d< |rtt||d td|d d  ntd|d d }tjtjdd	 d
| }tjtjdd	 d
| } tjtjdd	 d
| }!|dkrxtd| jd D ]ȉ | d   d   ||| d  |!| d  |  | < |r|| |  | d   ||!| d  |  | < | d  || d  |!| d  | | d      d < qW |d d   }"    }#|  | d< |rN|!|d  ||d < |!|  || d< |||} fddt|d d D   d d< |d   }$n|dkrPxtd| jd D ]Љ | d  | d    ||| d  |!| d  |  | < |r>|| |  | d   ||!| d  |  | < | d  ||| d  |!| d  |  | d      d < qW |d d   }"    }#|  | d< |r|!|d  ||d < |!|  || d< |||} fddt|d d D   d d< |d   }$nxtd| jd D ]t | d  ||| d  |!| d  |  | < |rb|| |  | d   ||!| d  |  | < qbW |d d   }"    }#|  | d< |rH|!|d  ||d < |!|  || d< |||}|}$|d d   }%|	s|	dkst|	t	rt|$|
}$t|%|
}%| |d  |%}"|dkr|$t||
 d  }#n"|dkr|$t||
 d  }#n t|$d| d  |}&| d|  d d|  }'| jt|&| j  |'d  }(|(d|'d  |'d  | j|' d   })| jt|&| j  |'t| j  }*||$d| d   }+|r|$|+ 7 }$|stj}|||||d |d d |	|
|d
| _t | | j|$|$d| d  |$| d d |&|%|"|#|(|*|)|+|'d},t!|,S )z
        Helper prediction function

        Parameters
        ----------
        h : int, optional
            The number of time steps to forecast ahead.
        g      ?rg   g        Nr   z!Only 1 dimensional data supportedr   c             S   s   | S )Nr   )r   r   r   r   r   <lambda>  s    z/ExponentialSmoothing._predict.<locals>.<lambda>)rY   rX   Nc             S   s   dS )Nr   r   )r   r   r   r   r   r     s    c             S   s   dS )Nr   r   )r   r   r   r   r   r     s    rY   c                s    g | ]} d  |   qS )r   r   ).0j)r'   r$   r#   r   r   
<listcomp>  s    z1ExponentialSmoothing._predict.<locals>.<listcomp>rX   c                s    g | ]} d  |   qS )r   r   )r   r   )r'   r$   r#   r   r   r     s          )
rk   rl   rm   rn   ro   rp   rq   rr   rs   rt   )re   rO   rG   sserP   rS   rR   aicbicaiccrQ   k)"rc   r[   r^   r]   rZ   r\   ra   r   ru   rv   rw   r   rx   r`   ry   rd   Zcumsumrepeatr{   ZmultiplyrX   ZdividesubtractZpowerr"   copyr   r
   rg   r|   ZNaNr<   r6   rN   )-r:   rC   rk   rl   rm   ro   rp   rn   rq   rr   rs   rt   r   r   r+   r   r7   r[   r^   r]   rZ   r\   r   r    r.   r   r   r-   r   r   Zphi_hZtrendedZdetrendZdampenrS   rR   ZfittedrP   r   r   r   r   r   rQ   r   r   )r'   r$   r#   r   rF   V  s   
D



*
 $
2
*R
2
*"




&&

zExponentialSmoothing._predict)NFNNNNrV   )NN)NNNNTFFF)NNNNNNNNNNN)	rI   rJ   rK   rL   r9   r?   r   rF   rM   r   r   )r>   r   rU   Y  s    
  
 !  rU   c                   s.   e Zd ZdZ fddZd fdd	Z  ZS )	SimpleExpSmoothinga  
    Simple Exponential Smoothing wrapper(...)

    Parameters
    ----------
    endog : array-like
        Time series

    Returns
    -------
    results : SimpleExpSmoothing class

    Notes
    -----
    This is a full implementation of the simple exponential smoothing as
    per [1].

    See Also
    ---------
    Exponential Smoothing
    Holt

    References
    ----------
    [1] Hyndman, Rob J., and George Athanasopoulos. Forecasting: principles and practice. OTexts, 2014.
    c                s   t t| | d S )N)r8   r   r9   )r:   rc   )r>   r   r   r9     s    zSimpleExpSmoothing.__init__NTc                s   t t| j||dS )a/  
        fit Simple Exponential Smoothing wrapper(...)

        Parameters
        ----------
        smoothing_level : float, optional
            The smoothing_level value of the simple exponential smoothing, if the value is
            set then this value will be used as the value.
        optimized : bool
            Should the values that have not been set above be optimized automatically?

        Returns
        -------
        results : HoltWintersResults class
            See statsmodels.tsa.holtwinters.HoltWintersResults

        Notes
        -----
        This is a full implementation of the simple exponential smoothing as
        per [1].

        References
        ----------
        [1] Hyndman, Rob J., and George Athanasopoulos. Forecasting: principles and practice. OTexts, 2014.
        )rk   r~   )r8   r   r   )r:   rk   r~   )r>   r   r   r     s    zSimpleExpSmoothing.fit)NT)rI   rJ   rK   rL   r9   r   rM   r   r   )r>   r   r     s   r   c                   s0   e Zd ZdZd	 fdd	Zd
 fdd	Z  ZS )Holta  
    Holt's Exponential Smoothing wrapper(...)

    Parameters
    ----------
    endog : array-like
        Time series
    expoential : bool, optional
        Type of trend component.
    damped : bool, optional
        Should the trend component be damped.

    Returns
    -------
    results : Holt class        

    Notes
    -----
    This is a full implementation of the holts exponential smoothing as
    per [1].

    See Also
    ---------
    Exponential Smoothing
    Simple Exponential Smoothing

    References
    ----------
    [1] Hyndman, Rob J., and George Athanasopoulos. Forecasting: principles and practice. OTexts, 2014.
    Fc                s&   |rdnd}t t| j|||d d S )NrY   rX   )rZ   r[   )r8   r   r9   )r:   rc   Zexponentialr[   rZ   )r>   r   r   r9   S  s    zHolt.__init__NTc                s   t t| j||||dS )a}  
        fit Holt's Exponential Smoothing wrapper(...)

        Parameters
        ----------
        smoothing_level : float, optional
            The alpha value of the simple exponential smoothing, if the value is
            set then this value will be used as the value.
        smoothing_slope :  float, optional
            The beta value of the holts trend method, if the value is
            set then this value will be used as the value.
        damping_slope : float, optional
            The phi value of the damped method, if the value is
            set then this value will be used as the value.
        optimized : bool, optional
            Should the values that have not been set above be optimized automatically?

        Returns
        -------
        results : HoltWintersResults class
            See statsmodels.tsa.holtwinters.HoltWintersResults

        Notes
        -----
        This is a full implementation of the holts exponential smoothing as
        per [1].

        References
        ----------
        [1] Hyndman, Rob J., and George Athanasopoulos. Forecasting: principles and practice. OTexts, 2014.
        )rk   rl   rn   r~   )r8   r   r   )r:   rk   rl   rn   r~   )r>   r   r   r   W  s     zHolt.fit)FF)NNNT)rI   rJ   rK   rL   r9   r   rM   r   r   )r>   r   r   3  s   r   )&rL   Znumpyr   Zstatsmodels.base.modelr   Zstatsmodels.base.wrapperr   r   r   Zstatsmodels.tsa.base.tsa_modelr   Zscipy.optimizer   r   r	   Zscipy.spatial.distancer
   Zscipy.specialr   ImportErrorZscipy.statsr   r!   r(   r)   r*   r/   r0   r1   r2   r3   r4   r5   r6   rN   rU   r   r   r   r   r   r   <module>   s>   c
   !<