
    J-j                         d Z ddlmZmZmZ ddlZddlmZ ddlZ	ddl
mZmZ ddlmZ ddlmZ [[[d	Z G d
 de      Z G d de      Z G d de      Z G d de      Zy)a  Collection of classes that sample from parametrized distributions and
provide an update mechanism of the distribution parameters.

All classes are supposed to follow the base class
`StatisticalModelSamplerWithZeroMeanBaseClass` interface in module
`interfaces`.
    )absolute_importdivisionprint_functionN   )range)rglenprint_warning)Hessian),StatisticalModelSamplerWithZeroMeanBaseClassTc                   \    e Zd Zd Zd
dZd Zd Zd Zed        Z	ed        Z
ed	        Zy)GaussSamplerc                     d| _         y)z-declarative init, doesn't need to be executedN)	dimensionselfs    Y/Users/jameslopez/projects/TradingBot25/.venv/lib/python3.12/site-packages/cma/sampler.py__init__zGaussSampler.__init__   s	        Nc                 <    | j                  t        |||             y)ab  set Hessian from f at x0.

        >>> import numpy as np, cma
        >>> es = cma.CMAEvolutionStrategy(3 * [1], 1, {'verbose':-9})
        >>> es.sm.set_H_by_f(cma.ff.elli, 3 * [0])  # Hessian of cma.ff.elli

        Now the eigen spectrum of H^1/2 C H^1/2 where H is the Hessian of ``cma.ff.elli``
        is given by the `spectrum` property.
        N)set_H_Hessian)r   fx0epss       r   
set_H_by_fzGaussSampler.set_H_by_f   s     	

8Ar3'(r   c                    t         j                  j                  |      \  }}t        |dk        r2t	        j
                  dj                  t        |dk        |             y|dz  |z  | _        | j                  j                  | _
        y)z@set Hessian w.r.t. which to compute the eigen spectrum.
        r   zcThe Hessian has {0} negative eigenvalues:
{1}
Hence, no (new) Hessian is set as spectrum reference.N      ?)nplinalgeighanywarningswarnformatsum_rightT_left)r   HDBs       r   r   zGaussSampler.set_H#   so     yy~~a 1q1u:MM  $VCAJ24 fqj[[]]
r   c                      yzdo nothing by defaultN r   argskwargss      r   updatezGaussSampler.update/       r   c                      yr.   r/   r0   s      r   
update_nowzGaussSampler.update_now2   r4   r   c                 p   t        | d      s	 | j                  dz  S t	        j
                  t        t        j                  j                  t	        j                  t	        j                  | j                  | j                        | j                                          S # t        $ r Y | j                  S w xY w)z5return eigen spectrum w.r.t. H like sqrt(H) C sqrt(H)r)      )hasattrr+   AttributeError	variancesr   asarraysortedr    eigvalshdotr)   covariance_matrixr'   r   s    r   eigenspectrumzGaussSampler.eigenspectrum5   s     tW%vvqy  zz&!3!3BFF266JJ..<0155> "? @ A 	A " >>!s   B 	B54B5c                      y)*condition number of the correlation matrixr   r/   r   s    r   corr_conditionzGaussSampler.corr_condition@        r   c                     ddddd}	 || j                      }|S # t        $ r- | j                   }|dz  ddd	|z  z  z
  dd
|dz  z  z  z   z  }Y |S w xY w)aJ  approximation of the expected length when isotropic with variance 1.

        The exact value could be computed by::

            from scipy.special import gamma
            return 2**0.5 * gamma((self.dimension+1) / 2) / gamma(self.dimension / 2)

        The approximation obeys ``chin < chin_hat < (1 + 5e-5) * chin``.
        gS63E?g(?gz63E?g:\?)r   r8         r   r         ?rH      r8   )r   KeyError)r   valuesvalNs       r   chinzGaussSampler.chinD   s     (O%,<>	A(C
 
	  	AAS&Aa!e,rR!Q$Y/??@C
		As    2AAN)__name__
__module____qualname__r   r   r   r3   r6   propertyrA   rD   rO   r/   r   r   r   r      sY    
)# 	A 	A    r   r   c                       e Zd ZdZej
                  j                  dfdZed        Z	ddZ
d Zd Zd Zd	 Zed
        Zed        Zed        Zy)GaussStandardConstantzqStandard Multi-variate normal distribution with zero mean.

    No update/change of distribution parameters.
    Fc                     	 t        |      | _        t        j                  |      | _        || _        || _        y # t
        $ r
 || _        Y !w xY wrP   )lenr   r   r<   standard_deviations	TypeErrorrandn	quadratic)r   r   r[   r\   r2   s        r   r   zGaussStandardConstant.__init___   sK    	' ^DN')zz)'<D$ 
"  	'&DN	's   *; AAc                 v    t        | d      st        j                  | j                        S | j                  dz  S )NrY   r8   )r9   r   onesr   rY   r   s    r   r;   zGaussStandardConstant.variancesk   s1    t23774>>**''**r   c                 6   | j                  || j                        }|r_|du r| j                  }n|}t        |      D ]>  }t	        ||   dz        }ddk  s|| j                  dz   kD  s,||xx   ||dz  z  z  cc<   @ t        | d      r|| j                  z  }|S )NTr8   r   rG   333333$@r   rY   )r[   r   rO   r   r&   r9   rY   )r   numbersame_lengtharzlen_isss          r   samplezGaussStandardConstant.sampleq   s    jj0d"yy"3ZQ^q5B$!66FdRWn,F   4./4+++C
r   c                 <    t        | d      r| j                  |z  S |S NrY   r9   rY   r   xs     r   	transformzGaussStandardConstant.transform   s#    4./++a//r   c                 <    t        | d      r|| j                  z  S |S ri   rj   rk   s     r   transform_inversez'GaussStandardConstant.transform_inverse   s#    4./t////r   c                 v    t        j                  t        j                  | j                  |      dz              S Nr8   )r   sqrtr&   ro   rk   s     r   normzGaussStandardConstant.norm   s*    wwrvvd44Q7:;<<r   c                     	 | xj                   |dz  z  c_         | S # t        $ r. |dz  t        j                  | j                        z  | _         Y | S w xY w)zvariance multiplierr   )rY   r:   r   r^   r   r   factors     r   __imul__zGaussStandardConstant.__imul__   sZ    	M$$3$   	M'-s{RWWT^^5L'LD$	Ms    3AAc                 r    t        | d      r+t        | j                        t        | j                        z  S y)NrY   rI   )r9   maxrY   minr   s    r   condition_numberz&GaussStandardConstant.condition_number   s1    4./t//03t7O7O3PPPr   c                     | j                   sy 	 t        j                  | j                  dz        S # t        $ r5 t        j                  t        j
                  | j                              cY S w xY wrq   )r\   r   diagrY   r:   r^   r   r   s    r   r@   z'GaussStandardConstant.covariance_matrix   sV    ~~	477433Q677 	4772774>>233	4s   !1 ;A/.A/c                     | j                   r2t        j                  t        j                  | j                              S d S rP   )r\   r   r}   r^   r   r   s    r   correlation_matrixz(GaussStandardConstant.correlation_matrix   s)    37>>rwwrwwt~~./KtKr   NF)rQ   rR   rS   __doc__r   randomr[   r   rT   r;   rg   rm   ro   rs   rw   r{   r@   r   r/   r   r   rV   rV   Z   s    
 yy 
# + +


=  
 4 4 L Lr   rV   c                   L   e Zd ZdZdddej
                  j                  ej                  j                  fdZ	ddZ
ed        Zed        Zed	        Zdd
Zd dZddZd Zd Zd ZddZd Zd Zd!dZd!dZed        Zed        Zd Zd Zd Zd Zed        Z d Z!d Z"y)"GaussFullSamplera  Multi-variate normal distribution with zero mean.

    Provides methods to `sample` from and `update` a multi-variate
    normal distribution with zero mean and full covariance matrix.

    :param dimension: (required) define the dimensionality (attribute
        ``dimension``) of the normal distribution. If ``dimension`` is a
        vector, it sets the diagonal of the initial covariance matrix.

    :param lazy_update_gap=0: is the number of iterations to wait between
        the O(n^3) updates of the sampler. All values <=1 behave
        identically.

    :param constant_trace='': 'arithmetic'/'aeigen' or 'geometric'
        or 'geigen' (geometric mean of eigenvalues) are available to be
        constant.

    :param randn=np.random.randn: is used to generate N(0,1) numbers.

    :param eigenmethod=np.linalg.eigh: function returning eigenvalues
        and -vectors of symmetric matrix

    >>> import cma, numpy as np
    >>> g = cma.sampler.GaussFullSampler(np.ones(4))
    >>> z = g.sample(1)[0]
    >>> assert g.norm([1,0,0,0]) == 1
    >>> g.update([[1., 0., 0., 0]], [.9])
    >>> g.update_now()
    >>> assert g.norm([1,0,0,0]) == 1
    >>> g.update([[4., 0., 0.,0]], [.5])
    >>> g.update_now()
    >>> g *= 2
    >>> assert cma.utilities.math.Mh.equals_approximately(g.variances[0], 17)
    >>> assert cma.utilities.math.Mh.equals_approximately(g.D[-1]**2, 17)

    TODO
    ----

    o Clean up CMAEvolutionStrategy attributes related to sampling
    (like usage of B, C, D, dC, sigma_vec, these are pretty
    substantial changes). In particular this should become
    compatible with any StatisticalModelSampler. Plan: keep B, C,
    D, dC for the time being as output-info attributes,
    DONE: keep sigma_vec (55 appearances) as a class.

    o combination of sigma_vec and C:
       - update sigma_vec with y (this is wrong: use "z")
       - rescale y according to the inverse update of sigma_vec (as
         if y is expressed in the new sigma_vec while C in the old)
       - update C with the "new" y.
r    Nc           	         	 t        |      | _        t        j                  |      }t        |      | j                  k(  sJ t        j                  |dz  t        j                  d| j                  z  t        j                  | j                        z        z        | _	        	 || _
        || _        |r|nt        j                  | _        || _        || _        t        j                   | j                        | _        	 t        j                  | j                        dz  | _        | j$                  j'                         }| j$                  |   | _        | j"                  d d |f   | _        	 d | _        d| _        d| _        d| _        d| _        d| _        d| _        y # t        $ r  || _        t        j
                  |      }Y w xY w)Nr8   g-C6?r   r   r   )rX   r   r   r<   rZ   r^   r}   exparangeClazy_update_gapconstant_traceinfcondition_limitr[   eigenmethodeyer,   r+   argsort_inverse_root_C_corr_condition_corr_condition_count_eigen_beta_diagonal_accelerationlast_update
count_tellcount_eigen)	r   r   r   r   r   r[   r   rY   idxs	            r   r   zGaussFullSampler.__init__   s|   	5 ^DN"$**Y"7 &'4>>999 ,a/ffdT^^3YYt~~67 88 9 	.,2Arvv
&';#%ffnn34# +,(+,(9  	5&DN"$'')"4	5s   %F %GGc                     |t        j                  | j                        }| j                  || j                  | j
                  | j                  | j                         y)zreset distribution while keeping all other parameters.

        If `standard_deviations` is not given, `np.ones` is used,
        which might not be the original initial setting.
        N)r   r   r[   r   )r   r^   r   r   r   r   r[   r   )r   rY   s     r   resetzGaussFullSampler.reset  sS     &"$''$.."9)&*&:&:%)%8%8 JJ"&"2"2	 	 	4r   c                 @    t        j                  | j                        S rP   )r   r}   r   r   s    r   r;   zGaussFullSampler.variances  s    wwtvvr   c                    | j                   | j                  k(  r*| j                  dk\  s| j                  dk  r| j                  S | j                  | _         t        j
                  j                  | j                        | _        | j                  S )rC   r   g333333?)r   r   r{   r   r   r    condr   r   s    r   rD   zGaussFullSampler.corr_condition  st     ++t/?/??!T%:%:S%@'''+/+;+;(!yy~~d.E.EF###r   c                 d    t        d| j                  dz  dz
  dz   f      | _        | j                  S )zbeta from Algorithm 1 line 16 in https://direct.mit.edu/evco/article/28/3/405/94999/Diagonal-Acceleration-for-Covariance-Matrixr   r   r8   )ry   rD   r   r   s    r   beta_diagonal_accelerationz+GaussFullSampler.beta_diagonal_acceleration  s8     ,/43F3F3Ka3ORS3S/T+U(///r   c                    | j                  |       | j                  || j                        }|r_|du r| j                  }n|}t	        |      D ]>  }t        ||   dz        }ddk  s|| j                  dz   kD  s,||xx   ||dz  z  z  cc<   @ t        j                  | j                  | j                  |z  j                        j                  }|S NTr8   r   rG   r`   r   )r6   r[   r   rO   r   r&   r   r?   r,   r+   r(   )	r   ra   r   rb   rc   rd   re   rf   arys	            r   rg   zGaussFullSampler.sample$  s    (jj0d"yy"3ZQ^q5B$!66FdRWn,F   ffTVVdffsl--.00
r   c                    t        j                  |d      }t        j                  |      }t        j                  |d   d         sJ t	        |      t	        |      k(  sJ | xj
                  d|z   t        |      z
  z  c_        t        j                  |dk        d   D ]i  }| j                  ||         }t        j                  |      sJ ||xx   t	        ||         |dz   dz  z  z  cc<   t        j                  ||         riJ  | xj
                  t        j                  ||j                  z  |      z  c_        | xj                  dz  c_        y)aB  update/learn by natural gradient ascent.

        The natural gradient used for the update is::

            np.dot(weights * vectors.T, vectors)

        and equivalently::

            sum([outer(weights[i] * vec, vec)
                 for i, vec in enumerate(vectors)], axis=0)

        Details:

        - The weights include the learning rate and ``-1 <= sum(
          weights[idx]) <= 1`` must be `True` for ``idx = weights > 0``
          and for ``idx = weights < 0``.

        - The content (length) of ``vectors`` with negative weights
          is changed!

        Tcopyr   r   &.>r8   N)r   arrayr<   isfiniterX   r   r&   nonzerors   r?   r(   r   r   vectorsweightsc1_times_delta_hsigmakrs   s         r   r3   zGaussFullSampler.update6  s   , ((7.**W%{{71:a=)))7|s7|+++!++c'l::GaK(+A
 99WQZ(D;;t$$$AJ#gaj/TD[1,<<<J;;wqz*** , 	"&&799,g661r   c                    || j                   }| j                  | j                  |z   k  s%|| j                  | j                  z
  cxk(  rdk(  ry ny| j                          | j	                          | j                  | _        t
        rt        t        t        | j                  ddd| j                  dz
  f   | j                  ddddf   z  d            dkD        rlt        d       t        | j                         t        t        | j                  ddd| j                  dz
  f   | j                  ddddf   z  d             yyy)a{  update internal variables for sampling the distribution
        with the current covariance matrix C.

        This method is O(dim^3) by calling ``_decompose_C``.

        If ``lazy_update_gap is None`` the lazy_update_gap from init
        is taken. If ``lazy_update_gap < 0`` the (possibly expensive)
        update is done even when the model seems to be up to date.
        Nr   r   gư>zB is not orthogonal)r   r   r   _updateC_decompose_C_assertions_quadraticr"   absr&   r,   r   printr+   )r   r   s     r   r6   zGaussFullSampler.update_nowa  s)    ""22OOOd..@@t1A1AAFQF G?? SSq!DNNQ.../&&AB-()*., *-/3*4 &5 '($&&M#dffQ$..1"4 445q!"uEqIJ&5 r   c                      y rP   r/   r   s    r   r   zGaussFullSampler._updateC~  s    r   c                 0   t        j                  | j                        }| j                  |   | _        | j                  dd|f   | _        t	        | j                        t        | j                        f| j                  d   | j                  d   fk(  sJ y)z4sort columns of B and D according to the values in DNr   r   )r   r   r+   r,   rz   ry   )r   r   s     r   _sortBDzGaussFullSampler._sortBD  sn    jj 3DFFS[)dffQi-DDDDr   c                 |   | j                   | j                   j                  z   dz  | _         | j                  }	 | j                  | j                         \  | _        | _        t        | j                  dk        r!t        dt        | j                        z        	 | xj                  dz  c_        t        t        j                  | j                              sJ ddk  r| j                          | j                          	 | j                  sd}n| j                  dv s| j                  j                  d      r$dt        j                   | j"                        z  }n3| j                  j                  d      rGt        j$                  t        j                   t        j&                  | j"                                     }n| j                  j                  d	      r#dt        j                   | j                        z  }n| j                  j                  d
      rGt        j$                  t        j                   t        j&                  | j                                     }n1t)        dt+        | j                        z  dd| j                         d}|dk7  r*| xj                   |z  c_         | xj                  |z  c_        | xj                  dz  c_        t        t        j                  | j                              sJ d| _        ddk  rrt        j:                  | j                  | j                  z  | j                  j                        | _        | j<                  | j<                  j                  z   dz  | _        yy# t,        $ r" t        dt+        | j                        z        w xY w# t0        $ r}t)        dt3        |      z   dz          t        |      dz  }t5        | j6                        D ]  }| j                   |   |xx   |z  cc<    |dz  |z   dz  | _        | j9                          Y d}~1d}~ww xY w)zeigen-decompose self.C thereby updating self.B and self.D.

        self.C is made symmetric.

        Know bugs: if update is not called before decompose, the
        state variables can get into an inconsistent state.

        r8   r   zLcovariance matrix was not positive definite with a minimal eigenvalue of %e.r   rG   )r   T)armeangeoaeiggeigz6trace normalization option setting '%s' not recognizedr   )
class_namemaxwarns	iterationz1Value '%s' not allowed for constant trace settingr   Nz3covariance matrix eigen decomposition failed with 
z/
Consider to reformulate the objective function   )r   r(   r+   r   r,   r"   
ValueErrorrz   r   allr   r   r   limit_conditionr   
startswithr   r;   r   logr	   reprr:   r   	Exceptionstrr   r   r   r?   inverse_root_C)r   D_oldsemin_di2re   s         r   r   zGaussFullSampler._decompose_C  s\    &&46688#q(0	(!--dff5NDFDF466Q; 8:=dff+FG G  " !r{{466*+++1u  "r**A((I59L9L9W9WXf9gBGGDNN33A((33U<t~~(> ??@A((33F;BGGDFFO+A((33F;tvv 778A!"Z"&t':':";#<-?!W[WgWgi A Av!!FFsNFr{{466*+++#'D  6"$&&$&&$&&(("CD#'#6#69L9L9N9N#NRS"SD  " r !TW[\`\o\oWp!pqqrG  	 Fa&BCD
 %j!mG4>>*q	!' +Qh(3.DF	 s&   A!N+  FM= =+N(+	P;4A<P66P;c                    || j                   }n|dk  rt        d|z        t        j                  |      r| j                  |k  ry| j
                  d   dz  || j
                  d   dz  z  z
  |dz
  z  }|dk  rt        d| j                  ||fz        t        | j                        D ]  }| j                  |   |xx   |z  cc<    | xj
                  dz  c_        | xj
                  |z  c_        | xj
                  dz  c_        y)	a  bound condition number to `limit` by adding eps to the trace.

        This method only changes the sampling distribution, but not the
        underlying covariance matrix.

        We add ``eps = (a - limit * b) / (limit - 1)`` to the diagonal
        variances, derived from ``limit = (a + eps) / (b + eps)`` with
        ``a, b = lambda_max, lambda_min``.

        >>> import cma
        >>> es = cma.CMAEvolutionStrategy(3 * [1], 1, {'CMA_diagonal_decoding':False, 'verbose':-9})
        >>> _ = es.optimize(cma.ff.elli)
        >>> assert es.sm.condition_number > 1e4
        >>> es.sm.limit_condition(1e4 - 1)
        >>> assert es.sm.condition_number < 1e4

        Nr   z*condition limit was %f<=1 but should be >1r   r8   r   zcond=%e, limit=%e, eps=%er   )
r   r   r   r   r{   r+   RuntimeWarningr   r   r   )r   limitr   re   s       r   r   z GaussFullSampler.limit_condition  s    $ =((EaZI$% & &{{5!T%:%:e%Cvvbz1}utvvay!|33	B!8 !<&&s3"4 5 5 t~~&AFF1IaLCL '1#3r   c                 f   | j                          t        j                  |      rG| xj                  |z  c_        | xj                  |dz  z  c_        	 | xj
                  |dz  z  c_        yt        t        j                  |      j                        dk(  r:| xj                  t        j                  ||      z  c_        | j                          yt        |j                        dk(  r&| xj                  |z  c_        | j                          yt        t        |            # t        $ r Y yw xY w)a(  multiply ``self.C`` with ``factor`` updating internal states.

        ``factor`` can be a scalar, a vector or a matrix. The vector
        is used as outer product and multiplied element-wise, i.e.,
        ``multiply_C(diag(C)**-0.5)`` generates a correlation matrix.

        Details:
        r   r   r8   N)r   r   isscalarr   r+   r   r:   rX   r<   shapeouterr   r   r   ru   s     r   
multiply_CzGaussFullSampler.multiply_C  s     	;;vFFfFFFfck!F##vs{2# F#))*a/FFbhhvv..F!#FFfFS[)) " s   D$ $	D0/D0c                 (    | j                  |       | S z``sm *= factor`` is a shortcut for ``sm = sm.__imul__(factor)``.

        Multiplies the covariance matrix with `factor`.
        r   ru   s     r   rw   zGaussFullSampler.__imul__      
 	r   c                     t        j                  | j                  | j                  z  | j                  j                        }|r| j                          |S )a]  return associated linear transformation.

        If ``B = sm.to_linear_transformation()`` and z ~ N(0, I), then
        np.dot(B, z) ~ Normal(0, sm.C) and sm.C and B have the same
        eigenvectors. With `reset=True`, ``np.dot(B, sm.sample(1)[0])``
        obeys the same distribution after the call.

        See also: `to_unit_matrix`
        r   r?   r,   r+   r(   r   r   r   tfs      r   to_linear_transformationz)GaussFullSampler.to_linear_transformation  9     VVDFFTVVOTVVXX.JJL	r   c                     t        j                  | j                  | j                  z  | j                  j                        }|r| j                          |S )ab  return inverse of associated linear transformation.

        If ``B = sm.to_linear_transformation_inverse()`` and z ~
        Normal(0, sm.C), then np.dot(B, z) ~ Normal(0, I) and sm.C and
        B have the same eigenvectors. With `reset=True`,
        also ``sm.sample(1)[0] ~ Normal(0, I)`` after the call.

        See also: `to_unit_matrix`
        r   r   s      r    to_linear_transformation_inversez1GaussFullSampler.to_linear_transformation_inverse$  r   r   c                     | j                   S rP   r   r   s    r   r@   z"GaussFullSampler.covariance_matrix3      vvr   c                     | j                   j                         }t        |j                  d         D ].  }|||f   dz  }|dd|fxx   |z  cc<   ||ddfxx   |z  cc<   0 ||j                  z   dz  }|S )7return correlation matrix of the distribution.
        r   r   Ng       @)r   r   r   r   r(   )r   cre   facs       r   r   z#GaussFullSampler.correlation_matrix7  su     FFKKMqwwqz"AAqD'3,CadGsNGadGsNG # WOr   c                     | j                  d       t        j                  | j                        dz  }| j                  | _        | j                          |S )"re-scale" C to a correlation matrix and return the scaling
         factors as standard deviations.

         See also: `to_linear_transformation`.
        r   r   )r6   r   r}   r   r   r   r   	sigma_vecs     r   to_correlation_matrixz&GaussFullSampler.to_correlation_matrixC  sE     	GGDFFOS(	((r   c                 x    | j                   |   |   | j                   |   |   | j                   |   |   z  dz  z  S )6return correlation between variables i and j.
        r   r   r   re   js      r   correlationzGaussFullSampler.correlationO  s=     vvay|tvvay|dffQil:S@@@r   c                     t        j                  | j                  | j                  t        j                  | j                  j                  |      z        S ).apply linear transformation ``C**0.5`` to `x`.)r   r?   r,   r+   r(   rk   s     r   rm   zGaussFullSampler.transformT  s3    vvdffdffrvvdffhh'::;;r   c                      ddk  r j                   qt        j                   j                   j                  z   j                  j
                         _          j                    j                   j
                  z   dz   _         t        j                   j                   |      S  fd} ||      }t        j                  t        j                  |            s%t        j                  dj                  ||             |S )7apply inverse linear transformation ``C**-0.5`` to `x`.   rG   r8   c                     t        j                  j                  t        j                  j                  j                  |       j                  z        S rP   )r   r?   r,   r(   r+   )rl   r   s    r   invz/GaussFullSampler.transform_inverse.<locals>.inv`  s4    66$&&"&&1"5">??r   zinv(x={0}) = {1} is not finite)r   r   r?   r,   r+   r(   r   r   r#   r$   r%   )r   rl   r   xinverses   `   r   ro   z"GaussFullSampler.transform_inverseX  s    6##+')vvdfftvvotvvxx'H$(,(<(<t?S?S?U?U(UYZ'Z$66$..22	@ q6vvbkk(+,MM:AA!XNOr   c                     t        | j                        t        | j                        f| j                  d   | j                  d   fk(  sJ | j                  d   | j                  d   z  dz  S )Nr   r   r8   )rz   r+   ry   r   s    r   r{   z!GaussFullSampler.condition_numberl  sZ    DFFS[)dffQi-DDDDr
TVVAY&**r   c                     t        t        j                  | j                  j                  |      | j
                  z  dz        dz  S a  compute the Mahalanobis norm that is induced by the
        statistical model / sample distribution, specifically by
        covariance matrix ``C``. The expected Mahalanobis norm is
        about ``sqrt(dimension)``.

        Example
        -------
        >>> import cma, numpy as np
        >>> sm = cma.sampler.GaussFullSampler(np.ones(10))
        >>> x = np.random.randn(10)
        >>> d = sm.norm(x)

        `d` is the norm "in" the true sample distribution,
        sampled points have a typical distance of ``sqrt(2*sm.dim)``,
        where ``sm.dim`` is the dimension, and an expected distance of
        close to ``dim**0.5`` to the sample mean zero. In the example,
        `d` is the Euclidean distance, because C = I.
        r8   r   )r&   r   r?   r,   r(   r+   rk   s     r   rs   zGaussFullSampler.normq  s5    & BFF46688Q'$&&0145s::r   c                     d}|||z  | j                   d   z  | j                  d   z  z
  ||||z  | j                   d   z  | j                  d   z  z   g}|D cg c]
  } ||       }}| t        c c}w )N
   r   )r+   r,   NotImplementedError)r   r   sigmar   r   Xrl   Fs           r   !inverse_hessian_scalar_correctionz2GaussFullSampler.inverse_hessian_scalar_correction  s    C%K$&&)+dffQi77C%K$&&)+dffQi7791aQqT1	!! s   A1rP   )NFr   r   )#rQ   rR   rS   r   r   r   r[   r    r!   r   r   rT   r;   rD   r   rg   r3   r6   r   r   r   r   r   rw   r   r   r@   r   r   r   rm   ro   r{   rs   r  r/   r   r   r   r      s   2h "# "!%yyYY^^%N4  $ $ 0 0
$)VK:EATF$L*6   	 	
A
<( + +;*"r   r   c                       e Zd ZdZdej
                  j                  dfdZd Ze	d        Z
ddZddZd	 Zd
 ZddZddZe	d        Ze	d        Zd Zd Zd Zd Ze	d        Zd Zy)GaussDiagonalSamplera-  Multi-variate normal distribution with zero mean and diagonal
    covariance matrix.

    Provides methods to `sample` from and `update` a multi-variate
    normal distribution with zero mean and diagonal covariance matrix.

    Arguments to `__init__`
    -----------------------

    `standard_deviations` (required) define the diagonal of the
    initial  covariance matrix, and consequently also the
    dimensionality (attribute `dim`) of the normal distribution. If
    `standard_deviations` is an `int`, ``np.ones(standard_deviations)``
    is used.

    `constant_trace='None'`: 'arithmetic' or 'geometric' or 'aeigen'
    or 'geigen' (geometric mean of eigenvalues) are available to be
    constant.

    `randn=np.random.randn` is used to generate N(0,1) numbers.

    >>> import cma, numpy as np
    >>> s = cma.sampler.GaussDiagonalSampler(np.ones(4))
    >>> z = s.sample(1)[0]
    >>> assert s.norm([1,0,0,0]) == 1
    >>> s.update([[1., 0., 0., 0]], [.9])
    >>> assert s.norm([1,0,0,0]) == 1
    >>> s.update([[4., 0., 0.,0]], [.5])
    >>> g *= 2

    TODO
    ----

    o DONE implement CMA_diagonal with samplers

    o Clean up CMAEvolutionStrategy attributes related to sampling
    (like usage of B, C, D, dC, sigma_vec, these are pretty
    substantial changes). In particular this should become
    compatible with any StatisticalModelSampler. Plan: keep B, C,
    D, dC for the time being as output-info attributes,
    keep sigma_vec (55 appearances) either as constant scaling or
    as a class. Current favorite: make a class (DONE) .

    o combination of sigma_vec and C:
       - update sigma_vec with y (this is wrong: use "z")
       - rescale y according to the inverse update of sigma_vec (as
         if y is expressed in the new sigma_vec while C in the old)
       - update C with the "new" y.
    NoneFc                 \   	 t        |      | _        t        j                  |      }| j                  t        |      k(  sJ t        |      | j                  k(  sJ |dz  | _        	 || _        || _        || _	        d| _
        y # t        $ r || _        t        j
                  |      }Y w xY w)Nr8   r   )rX   r   r   r<   rZ   r^   r   r   r[   r\   r   )r   r   r   r[   r\   r2   rY   s          r   r   zGaussDiagonalSampler.__init__  s    
	5 ^DN"$**Y"7 ~~%8!9999&'4>>999$a'$,
"  	5&DN"$'')"4	5s   %B %B+*B+c                 ~    | j                  | j                  | j                  | j                  | j                         y)z>reset distribution while keeping all other parameters
        )r   r[   r\   N)r   r   r   r[   r\   r   s    r   r   zGaussDiagonalSampler.reset  s2     	dnn%)%8%8 JJ $ 	 	0r   c                     | j                   S rP   r   r   s    r   r;   zGaussDiagonalSampler.variances  r   r   c                 $   | j                  || j                        }|r_|du r| j                  }n|}t        |      D ]>  }t	        ||   dz        }ddk  s|| j                  dz   kD  s,||xx   ||dz  z  z  cc<   @ | j
                  dz  |z  }|S r   )r[   r   rO   r   r&   r   )r   ra   rb   rc   rd   re   rf   r   s           r   rg   zGaussDiagonalSampler.sample  s    jj0d"yy"3ZQ^q5B$!66FdRWn,F   ffckC
r   c                    t        j                  |d      }t        j                  |      }t        j                  |d   d         sJ t	        |      t	        |      k(  sJ | xj
                  d|z   t        |      z
  z  c_        t        j                  |dk        d   D ]i  }| j                  ||         }t        j                  |      sJ ||xx   t	        ||         |dz   dz  z  z  cc<   t        j                  ||         riJ  | xj
                  t        j                  ||dz        z  c_        | xj                  dz  c_
        y)a  update/learn by natural gradient ascent.

        The natural gradient used for the update of the coordinate-wise
        variances is::

            np.dot(weights, vectors**2)

        Details: The weights include the learning rate and
        ``-1 <= sum(weights[idx]) <= 1`` must be `True` for
        ``idx = weights > 0`` and for ``idx = weights < 0``.
        The content of `vectors` with negative weights is changed.
        Tr   r   r   r   r8   N)r   r   r<   r   rX   r   r&   r   rs   r?   r   r   s         r   r3   zGaussDiagonalSampler.update  s    ((7.**W%{{71:a=)))7|s7|+++!++c'l::GaK(+A
 99WQZ(D;;t$$$AJ#gaj/TD[1,<<<J;;wqz*** , 	"&&'1*--1r   c                 .    | xj                   |z  c_         y)zmultiply `self.C` with `factor` updating internal states.

        `factor` can be a scalar, a vector or a matrix. The vector
        is used as outer product, i.e. ``multiply_C(diag(C)**-0.5)``
        generates a correlation matrix.Nr   ru   s     r   r   zGaussDiagonalSampler.multiply_C  s     	&r   c                 (    | j                  |       | S r   r   ru   s     r   rw   zGaussDiagonalSampler.__imul__  r   r   c                 H    | j                   dz  }|r| j                          |S )ab  return associated linear transformation.

        If ``B = sm.to_linear_transformation()`` and z ~ N(0, I), then
        np.dot(B, z) ~ Normal(0, sm.C) and sm.C and B have the same
        eigenvectors. With `reset=True`, also ``np.dot(B, sm.sample(1)[0])``
        obeys the same distribution after the call.

        See also: `to_unit_matrix`
        r   r   r   r   s      r   r   z-GaussDiagonalSampler.to_linear_transformation&  s"     VVS[JJL	r   c                 H    | j                   dz  }|r| j                          |S )a_  return associated inverse linear transformation.

        If ``B = sm.to_linear_transformation_inverse()`` and z ~
        Normal(0, sm.C), then np.dot(B, z) ~ Normal(0, I) and sm.C and
        B have the same eigenvectors. With `reset=True`,
        also ``sm.sample(1)[0] ~ Normal(0, I)`` after the call.

        See also: `to_unit_matrix`
        g      r  r   s      r   r   z5GaussDiagonalSampler.to_linear_transformation_inverse5  s"     VVT\JJL	r   c                 \    | j                   rt        j                  | j                        S d S rP   )r\   r   r}   r   r   s    r   r@   z&GaussDiagonalSampler.covariance_matrixD  s    "&..rwwtvv:d:r   c                 \    | j                   rt        j                  | j                        S dS )r   N)r\   r   r   r   r   s    r   r   z'GaussDiagonalSampler.correlation_matrixH  s"     *.rvvdnn%ATAr   c                 l    | j                   dz  }t        j                  | j                        | _         |S )r   r   )r   r   r^   r   r   s     r   r   z*GaussDiagonalSampler.to_correlation_matrixN  s+     FFCK	(r   c                      y)r   r   r/   r   s      r   r   z GaussDiagonalSampler.correlationX  rE   r   c                 &    | j                   dz  |z  S )r   r   r   rk   s     r   rm   zGaussDiagonalSampler.transform]  s    vvs{Qr   c                 &    || j                   dz  z  S )r   r   r   rk   s     r   ro   z&GaussDiagonalSampler.transform_inversea  s    4663;r   c                 X    t        | j                        t        | j                        z  S rP   )ry   r   rz   r   s    r   r{   z%GaussDiagonalSampler.condition_numbere  s    466{S[((r   c                 d    t        t        j                  |      dz  | j                  z        dz  S r   )r&   r   r<   r   rk   s     r   rs   zGaussDiagonalSampler.normi  s*    & 2::a=!#dff,-s22r   Nr   r  )rQ   rR   rS   r   r   r   r[   r   r   rT   r;   rg   r3   r   rw   r   r   r@   r   r   r   rm   ro   r{   rs   r/   r   r   r  r    s    0d !'yy *0  " D ; ; B B

 ) )3r   r  )r   
__future__r   r   r   r#   utilities.python3for2r   numpyr   utilities.utilsr   r	   utilities.mathr
   r   
interfacesr   r   r   rV   r   r  r/   r   r   <module>r"     sp    A @  (  1 / DX~ C? CLLLL LL^e"| e"Nl3< l3r   