
    J-jǠ                     N   d Z ddlmZmZmZ [[[dZdZddlZddlZddl	m
Z
 ddlZ	 ddlmZ d	d
lmZ d	dlmZ d	dlmZ d Zd Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Zd Z d Z! G d de      Z" G d de      Z#y# e$ r d ZY vw xY w)zIFitness surrogate model classes and handler for incremental evaluations.
    )absolute_importdivisionprint_functionzNikolaus HansenzBSD 3-clauseN)defaultdict
kendalltauc                     t        | |      d fS N)_kendall_tau)xys     `/Users/jameslopez/projects/TradingBot25/.venv/lib/python3.12/site-packages/cma/fitness_models.py_kendalltaur      s    Aq!4''       )utils)LoggerDummy)DefaultSettingsc           	         d}t        |       t        |      k(  sJ t        j                  |       t        j                  |      }} d}t        t        |             D ]  }ddk  rkt        j                  | |   | d| z
        }t        j                  ||   |d| z
        }|t        ||z        z  }|sX||t        |dk(  |dk(  z        z  z  }st        |      D ]b  }|t        j                  | |   | |   z
        t        j                  ||   ||   z
        z  z  }|sF||| |   | |   k(  z  ||   ||   k(  z  z  }d  |dz  t        |       t        |       dz
  z  z  }ddk  riddlm}	  |	| |      d   }
t        j                  |
      rB|
|dt        |       z  z
  k  s|
|dt        |       z  z   kD  rt        j                  d	||
fz         |S )
aK  return Kendall tau rank correlation coefficient.

    Implemented only to potentially remove dependency on `scipy.stats`.

    This

    >>> import numpy as np
    >>> from cma.fitness_models import _kendall_tau
    >>> kendalltau = lambda x, y: (_kendall_tau(x, y), 0)
    >>> # from scipy.stats import kendalltau  # incomment if not available
    >>> for dim in np.random.randint(3, 22, 5):
    ...     x, y = np.random.randn(dim), np.random.randn(dim)
    ...     t1, t2 = _kendall_tau(x, y), kendalltau(x, y)[0]
    ...     # print(t1, t2)
    ...     assert np.isclose(t1, t2)

          ?r   r      Ng       @   r   z tau=%f not close to stats.tau=%f)lennpasarrayrangesignsumscipy.statsr   isfinitewarningswarn)r   r   equal_value_contributionsidxdyjtaur   ts              r   r   r      s   $  %q6SV::a="**Q-qA	A3q6]q51"1&B1"1&BR"WA'-R1Wq4I0JJJ1XRWWQqTAaD[)BGGAaD1Q4K,@@@+1QqTQqT\BadaPQdlSSA   b&CFc!fqj)
*C	Av*q!Q;;q>3SV##q3SV+;';@C8KLJr   c                     ddk  rt        | |      }|S 	 t        | |      d   }t        j                  |      sd}|S # t        $ r d}Y &w xY w)zAreturn rank correlation coefficient between data `x` and `y`
    r   r   r   )r   r   	TypeErrorr   r    )r   r   r)   s      r   kendall_taur-   C   sb     
Av1a  J	a#A&C {{3CJ	  	C	s   = A
Ac                   2    e Zd ZdZd ZdZdZdZdZdZ	dZ
dZy	)
SurrogatePopulationSettingsr   c           
      P    t        t        dt        d|z  d| z  f      f            S )N   g333333?      ?)intmaxmin)popsi
nevaluateds     r   <lambda>z$SurrogatePopulationSettings.<lambda>S   s'    #c2sC*<LdUZl;[7\2].^*_r   r   g333333?r      FTN)__name__
__module____qualname__minimum_model_size	n_for_taumodel_max_size_factortau_truth_thresholdtau_truth_threshold_correctionmin_evals_percentmodel_sort_globallyreturn_true_fitnesseslogging_push r   r   r/   r/   Q   s8    _I%&"  Lr   r/   c                   :    e Zd ZdZ	 	 	 ddZ G d de      Zd Zy)SurrogatePopulationa4
  surrogate f-values for a population.

    See also `__call__` method.

    What is new:

    - the model is built with >=3 evaluations (compared to LS-CMA and lmm-CMA)
    - the model is linear at first, then diagonal, then full
    - the model uses the fitness ranks as weights for weighted regression.

    >>> import cma
    >>> import cma.fitness_models as fm
    >>> from cma.fitness_transformations import Function as FFun  # adds evaluations attribute
    >>> # fm.Logger, Logger = fm.LoggerDummy, fm.Logger
    >>> surrogate = fm.SurrogatePopulation(cma.ff.elli)

    Example using the ask-and-tell interface:

    >>> for ifun, fun in enumerate([cma.ff.elli, cma.ff.sectorsphere]):
    ...     for irun in range(7):
    ...         assert irun < 4  # measure best of four
    ...         es = cma.CMAEvolutionStrategy(5 * [1], 2.2,
    ...                     {'CMA_injections_threshold_keep_len': 1,
    ...                         'ftarget':1e-9, 'verbose': -9, 'seed':3 + irun})
    ...         fitfun = FFun(fun)
    ...         surrogate = fm.SurrogatePopulation(fitfun)
    ...         while not es.stop():
    ...             X = es.ask()
    ...             es.tell(X, surrogate(X))  # surrogate evaluation
    ...             es.inject([surrogate.model.xopt])
    ...             # es.disp(); es.logger.add()  # ineffective with verbose=-9
    ...         # print(irun, fitfun.evaluations)  # was: (sig=2.2) 12 161, 18 131, 18 150, 18 82, 15 59, 15 87, 15 132, 18 83, 18 55, 18 68, 19 231 75, 
    ...         assert 'ftarget' in es.stop(), es.result.asdict
    ...         if ifun == 0:
    ...             if fitfun.evaluations < 20:
    ...                 break
    ...         if ifun == 1:
    ...             if fitfun.evaluations < 90:
    ...                 break

    Example using the ``parallel_objective`` interface to `cma.fmin`:

    >>> for fitfun, evals in [[FFun(cma.ff.elli), 22], [FFun(cma.ff.ellirot), 40]]:
    ...     surrogate = fm.SurrogatePopulation(fitfun)
    ...     inject_xopt = fm.ModelInjectionCallback(surrogate.model)  # must use the same model
    ...     xopt, es = cma.fmin2(None, 5 * [1], 2.2,
    ...                      {'CMA_injections_threshold_keep_len': 1,
    ...                       'ftarget':1e-12, 'verbose': -9},
    ...                      parallel_objective=surrogate,
    ...                      callback=inject_xopt)
    ...     # print(fitfun.evaluations)
    ...     assert fitfun.evaluations == es.result.evaluations
    ...     assert es.result[1] < 1e-12
    ...     assert es.result[2] < evals
    >>> # fm.Logger = Logger

    Nc                     || _         |r|n	t               | _        t        t	               d|       | _        d| _        d| _        t        | g d      | _	        t        | j                  dg      | _
        y)z

        If ``model is None``, a default `LQModel` instance is used. By
        setting `self.model` to `None`, only the `fitness` for each
        population member is evaluated in each call.

        r9   r   )tau0tau1zevaluated ratiolabelseigenvaluesN)fitnessLQModelmodelr/   localssettingscountevaluationsLoggerloggerlogger_eigenvalues)selfrO   rQ   r?   r@   s        r   __init__zSurrogatePopulation.__init__   s]     #U
3FHaF
T*MN"(m_"Er   c                   l    e Zd ZdZd Zd Zd ZddZ	 	 ddZd Z	e
d	        Ze
d
        Ze
d        Zy)%SurrogatePopulation.EvaluationManagera  Manage incremental evaluation of a population of solutions.

        Evaluate solutions, add them to the model and keep track of which
        solutions were evaluated.

        Uses `model.add_data_row` and `model.eval`.

        Details: for simplicity and avoiding the copy construction, we do not
        inherit from `list`. Hence we use ``self.X`` instead of ``self``.

        c                 ~    || _         t        |      dgz  | _        t        |      t        j                  gz  | _        y)z6all is based on the population (list of solutions) `X`FN)Xr   	evaluatedr   nanfvalues)rY   r^   s     r   rZ   z.SurrogatePopulation.EvaluationManager.__init__   s1    DF Vug-DNq6RVVH,DLr   c                 @    || j                   |<   d| j                  |<   y)z"add fitness(self.X[i]), not in useTN)ra   r_   )rY   r%   fvals      r   add_evalz.SurrogatePopulation.EvaluationManager.add_eval   s    "DLLO $DNN1r   c                    | j                   |   r$t        d|| j                  t        |       fz         || j                  |         | j
                  |<   d| j                   |<    || j                  |   | j
                  |          y)z=add fitness(self.X[i]) to model data, mainly for internal usezi=%d, evals=%d, len=%dTN)r_   
ValueErrorrU   r   r^   ra   )rY   r%   rO   	model_adds       r   evalz*SurrogatePopulation.EvaluationManager.eval   su    ~~a  !9Q@P@PRUVZR[<\!\]]%dffQi0DLLO $DNN1dffQia1r   Nc                    |t        t        | j                              }t        | j                        t        | j                        k(  sJ | j                  |k  s8t        j                  d| j                  |t        | j                        fz         || j                  z
  | _        |D ]6  }| j                  |k\  r n| j                  |   r$| j                  |||       8 | j                  |k  rZ| j                  t        | j                        k  r8t        j                  d| j                  |t        | j                        fz         y| j                  |k(  s.| j                  t        | j                        cxk(  r|k  sJ  J yy)aA  evaluate unevaluated entries of X[idx] until `number` entries are
            evaluated *overall*.

            Assumes that ``sorted(idx) == list(range(len(self.X)))``.

            ``idx`` defines the evaluation sequence.

            The post condition is ``self.evaluations == min(number, len(self.X))``.
            Nz/Expected evaluations=%d < number=%d, popsize=%dz2After eval: evaluations=%d < number=%d, popsize=%d)	r   r   r^   r_   rU   r!   r"   last_evaluationsrh   )rY   numberrO   rg   idxr%   s         r   eval_sequencez3SurrogatePopulation.EvaluationManager.eval_sequence   sT    {CK(t~~&#dff+555##f,O!%!1!163tvv; GH I$*T-=-=$=D!##v-~~a(IIa)4	  ##f,1A1ACK1OMM"V%)%5%5vs466{$K#L M##v-1A1AS[1YSY1YYY1YYY1Y-r   c                 z   |r.| j                   t        | j                        k(  r| j                  S | j                  D cg c]
  } ||       }}|t	        j
                  | j                        }t	        j                  |      r+t	        j
                  |      }|D cg c]
  }||z
  |z    c}S |S c c}w c c}w )zGreturn surrogate values of `model_eval` with smart offset.
            )rU   r   r^   ra   r   nanminr    )rY   
model_evaltrue_values_if_all_availablef_offsetr   F_modelm_offsetfs           r   surrogate_valuesz6SurrogatePopulation.EvaluationManager.surrogate_values   s     ,0@0@CK0O||#.2ff5fz!}fG599T\\2{{8$99W-9@AAHx/AA 6
 Bs   B3B8c                 ,    t        | j                        S )z8should replace ``len(self.X)`` etc, not fully in use yet)r   ra   rY   s    r   __len__z-SurrogatePopulation.EvaluationManager.__len__   s    t||$$r   c                 F    | j                   t        | j                        z  S r
   )rU   r   ra   rx   s    r   evaluation_fractionz9SurrogatePopulation.EvaluationManager.evaluation_fraction   s    ##c$,,&777r   c                 ,    t        | j                        S r
   )r   r_   rx   s    r   rU   z1SurrogatePopulation.EvaluationManager.evaluations   s    t~~&&r   c                 X    t        | j                        t        | j                        z
  S )z%number of not yet evaluated solutions)r   r^   r   r_   rx   s    r   	remainingz/SurrogatePopulation.EvaluationManager.remaining   s      tvv;T^^!444r   r
   )TN)r:   r;   r<   __doc__rZ   rd   rh   rm   rv   ry   propertyr{   rU   r~   rF   r   r   EvaluationManagerr\      sh    
		-
	%	2	Z8 MQ&*		% 
	8 
	8		' 
	'		5 
	5r   r   c                 
   | xj                   dz  c_         | j                  }| j                  j                  t	        |      z  |j                  j
                  kD  rW|j                  j
                  r|j                          | j                  j                  t	        |      z  |j                  _        t        j                  |      }|| _	        ddk  r|j                  | j                  j                  k  r|j                  | j                  j                  |j                  z
  | j                  |j                         | xj                  |j                  z  c_        |j!                  | j                  j"                  xs |j                         |j%                  |j&                  | j                  j(                        S ddk  rP| j                   d| j                  j*                  z   z  r*|j%                  |j&                  |j,                  d         S t/        dt1        t	        |      | j                  j2                  z  dz  d|j                  j4                  z  |j                  z
  f      z         }|j6                  rU|j                  dkD  r2t9        j:                  |D cg c]  }|j'                  |       c}      nd}|j                  || j                  |j                  |       |j!                  |       |j=                  | j                  j?                  t	        |      |j                              }|j@                  |k(  r| jB                  jE                  |       || j                  jF                  | j                  jH                  |jJ                  z  z
  k\  rn3|t/        t9        jL                  |dz              z  }	 |j6                  rU|j!                  | j                  j"                  xs |j                         |jO                         | jB                  jE                  |       | xj                  |j                  z  c_        | j                  dk(  rd	| _        | jB                  jE                  |j                  t	        |      z         | j                  jP                  r| jB                  jS                          |j%                  |j&                  | j                  j(                        S c c}w )
a;  return population f-values.

        Also update the underlying model. Evaluate at least one solution on the
        true fitness. The smallest returned value is never smaller than the
        smallest truly evaluated value.

        Uses (this may not be a complete list):
        `model.settings.max_absolute_size`, `model.settings.truncation_ratio`,
        `model.size`, `model.sort`, `model.eval`, `model.reset`, `model.add_data_row`,
        `model.kendall`, `model.adapt_max_relative_size`, relies on default value
        zero for ``max_absolute_size``.

        r   r   r   r   )rr   d   Nr9   g{Gz?)*rT   rQ   rS   r?   r   max_absolute_sizeresetrH   r   evalssizer=   rm   rO   add_data_rowrU   sortrC   rv   rh   rD   crazy_sloppyFr3   r4   rB   truncation_ratior~   r   argsortkendallr>   rj   rW   addr@   rA   r{   ceiladapt_max_relative_sizerE   push)rY   r^   rQ   r   number_evaluatedr   rl   r)   s           r   __call__zSurrogatePopulation.__call__  s    	

a


 ==..Q7%..:Z:ZZ~~///3}}/R/RUXYZU[/[ENN,#55a8
6zzDMM<<<##DMM$D$Duzz$Q$(LL%2D2DF  E$5$55 

4==<<Q@Q@QR--ejj$--:]:]^^6djjA(B(B$BC))%**uwwqz)JJq3A1P1P(PSV(V()ENN,K,K(Kejj(X(Z $[  [ \oo<AJJN"**Q7QejjmQ78PTC 0$,, % 2 2C9JJ'(-- 7 7A@Q@Q RSC%%)99$dmm77$--:f:fin  jC  jC  ;C  C  CBGG,<q,@$A BB oo  	

4==44I8I8IJ%%c*E---q #D))CF23==%%KK%%ejj$--2U2UVV3 8s   $S<)NNN)r:   r;   r<   r   rZ   objectr   r   rF   r   r   rH   rH   ^   s/    8v '+%)F.R5F R5hBWr   rH   c                       e Zd ZdZdZy)ModelInjectionCallbackSettingsr   g]tE?N)r:   r;   r<   sigma_distance_lower_thresholdsigma_factorrF   r   r   r   r   G  s    %&"Lr   r   c                       e Zd ZdZd Zd Zy)ModelInjectionCallbackzinject `model.xopt` and decrease `sigma` if `mean` is close to `model.xopt`.

    New, simpler callback class.

    Sigma decrease saves (only) 30% on the 10-D ellipsoid.
    c                 t    d| _         || _        t        |       | _        t	        t               d|       | _        y)z5sigma_distance_lower_threshold=0 means decrease neverFr   N)update_modelrQ   rV   rW   r   rR   rS   )rY   rQ   s     r   rZ   zModelInjectionCallback.__init__R  s.    !
Tl6vxDIr   c                    | j                   r:| j                  j                  |j                  |j                  j                         ddk  r@| j                  j
                  s*| j                  j                  d      j                          y |j                  | j                  j                  g       |j                  | j                  j                  |j                  z
        }| j                  j                  | j                  j                  |j                  dz  z  |j                   j"                  j$                  z         || j                  j                  |j                  dz  z  |j                   j"                  j$                  z  k  rS|xj&                  | j                  j(                  z  c_        | j                  j                  |      j                          y | j                  j                  |       j                          y )Nr   r   r   r   )r   rQ   add_data
pop_sortedfittypesrW   r   r   injectxoptmahalanobis_normmeanrS   r   Nspweightsmueffsigmar   )rY   esxdists      r   r   zModelInjectionCallback.__call__X  sO   JJrvvzz:6$****KKOOA##%
		4::??#$##DJJOObgg$=>DDrttSyPSUSXSXS`S`SfSffg4==??"$$)KbeemmNaNaaaHH222HKKOOE"'')KKOOUF#((*r   N)r:   r;   r<   r   rZ   r   rF   r   r   r   r   K  s    J+r   r   c                       e Zd ZdZy)Tauz/placeholder to store Kendall tau related thingsN)r:   r;   r<   r   rF   r   r   r   r   g  s    5r   r   c                     t        t        | j                  dz   | j                  j                  | j
                  dz   z  f            }t        | j
                  |f      S )z+truncate worst solutions for model buildingr9   r   )r3   r4   current_complexityrS   r   r   r5   )mns     r   _n_for_model_building_defaultr   j  sR    C%%)

++qvvz:< = 	>A{r   c                 @    t        j                  | j                        S r
   )r   r   Y)r   s    r   _sorted_index_defaultr   p  s    ::acc?r   c                   ^    e Zd ZdZdZdZ eddez
  dz  f      ZdZdZ	dZ
eZd	Zd
ZdZeZd Zy)LQModelSettingsNr9   g?r2   r   r   g?r      rF   Fc                    d| j                   cxk  rdk  sn t        d| j                   z        | j                  xs | j                  }d| j                  | j                   z  cxk  r|cxk  r| j                  k  sEn t        d| j                  t        | j                        | j                  | j                   fz        | S )Nr   r   z9need: 0 < truncation_ratio <= 1, was: truncation_ratio=%fzpneed max_relative_size_end=%f >= max_relative_size_init=%s >= min_relative_size/self.truncation_ratio=%f/%f >= 0)r   rf   max_relative_size_initmax_relative_size_endmin_relative_sizestr)rY   max_inits     r   	_checkingzLQModelSettings._checking  s    4((-A-K%%&' ' ..L$2L2L4))D,A,AAkXkQUQkQkk C++S1L1L-MtOeOegkg|g|}~  r   )r:   r;   r<   r   r   max_relative_size_factorr4   r    tau_threshold_for_model_increaser   r   r   n_for_model_building
max_weightdisallowed_typesf_transformationr   sorted_indexr   rF   r   r   r   r   s  sb    !#C!&;";q!@AB'*$8J(L
r   r   c                      e Zd ZdZdd gdd ggZeD  cg c]  }|d   	 c}} Z ee      Zed        Z		 	 	 	 	 d/d	Z
d
 Zd0dZed        Zed        Zed        Zed        Zed        Zd Zd Zd Zd Zd1dZd2dZdej2                  fdZdej2                  fdZd Zd Zd Zd Zd Z d Z!d Z"d  Z#d0d!Z$d" Z%d# Z&d$ Z'd% Z(d& Z)d' Z*ed(        Z+ed)        Z,ed*        Z-ed+        Z.ed,        Z/ed-        Z0ed.        Z1yc c}} w )3rP   aG  Up to a full quadratic model using the pseudo inverse to compute
    the model coefficients.

    The full model has 1 + 2n + n(n-1)/2 = n(n+3) + 1 parameters. Model
    building "works" with any number of data.

    Model size 1.0 doesn't work well on bbob-f10, 1.1 however works fine.

    TODO: change self.types: List[str] to self.type: str with only one entry

    >>> import numpy as np
    >>> import cma
    >>> import cma.fitness_models as fm
    >>> # fm.Logger, Logger = fm.LoggerDummy, fm.Logger
    >>> m = fm.LQModel()
    >>> for i in range(30):
    ...     x = np.random.randn(3)
    ...     y = cma.ff.elli(x - 1.2)
    ...     _ = m.add_data_row(x, y)
    >>> assert np.allclose(m.coefficients, [
    ...   1.44144144e+06,
    ...  -2.40000000e+00,  -2.40000000e+03,  -2.40000000e+06,
    ...   1.00000000e+00,   1.00000000e+03,   1.00000000e+06,
    ...  -4.65661287e-10,  -6.98491931e-10,   1.97906047e-09,
    ...   ], atol=1e-5)
    >>> assert np.allclose(m.xopt, [ 1.2,  1.2,  1.2])
    >>> assert np.allclose(m.xopt, [ 1.2,  1.2,  1.2])

    Check the same before the full model is build:

    >>> m = fm.LQModel()
    >>> m.settings.min_relative_size = 3 * m.settings.truncation_ratio
    >>> for i in range(30):
    ...     x = np.random.randn(4)
    ...     y = cma.ff.elli(x - 1.2)
    ...     _ = m.add_data_row(x, y)
    >>> print(m.types)
    ['quadratic']
    >>> assert np.allclose(m.coefficients, [
    ...   1.45454544e+06,
    ...  -2.40000000e+00,  -2.40000000e+02,  -2.40000000e+04, -2.40000000e+06,
    ...   1.00000000e+00,   1.00000000e+02,   1.00000000e+04,   1.00000000e+06,
    ...   ])
    >>> assert np.allclose(m.xopt, [ 1.2,  1.2,  1.2,  1.2])
    >>> assert np.allclose(m.xopt, [ 1.2,  1.2,  1.2,  1.2])

    Check the Hessian in the rotated case:

    >>> fitness = cma.fitness_transformations.Rotated(cma.ff.elli)
    >>> m = fm.LQModel(2, 2)
    >>> for i in range(30):
    ...     x = np.random.randn(4) - 5
    ...     y = fitness(x - 2.2)
    ...     _ = m.add_data_row(x, y)
    >>> R = fitness[1].dicMatrices[4]
    >>> H = np.dot(np.dot(R.T, np.diag([1, 1e2, 1e4, 1e6])), R)
    >>> assert np.all(np.isclose(H, m.hessian))
    >>> assert np.allclose(m.xopt, 4 * [2.2])
    >>> m.set_xoffset([2.335, 1.2, 2, 4])
    >>> assert np.all(np.isclose(H, m.hessian))
    >>> assert np.allclose(m.xopt, 4 * [2.2])

    Check a simple linear case, the optimum is not necessarily at the
    expected position (the Hessian matrix is chosen somewhat arbitrarily)

    >>> m = fm.LQModel()
    >>> m.settings.min_relative_size = 4
    >>> _ = m.add_data_row([1, 1, 1], 220 + 10)
    >>> _ = m.add_data_row([2, 1, 1], 220)
    >>> print(m.types)
    []
    >>> assert np.allclose(m.coefficients, [80, -10, 80, 80])
    >>> assert np.allclose(m.xopt, [22, -159, -159])  # [ 50,  -400, -400])  # depends on Hessian
    >>> # fm.Logger = Logger

    For results see:

    Hansen (2019). A Global Surrogate Model for CMA-ES. In Genetic and Evolutionary
    Computation Conference (GECCO 2019), Proceedings, ACM.

    lq-CMA-ES at http://lq-cma.gforge.inria.fr/ppdata-archives/pap-gecco2019/figure5/

    	quadraticc                     d| z  dz   S )Nr9   r   rF   ds    r   r8   zLQModel.<lambda>  s    A	r   fullc                 0    t        | | dz   z  dz        dz   S )Nr   r9   r   )r3   r   s    r   r8   zLQModel.<lambda>  s    3qAE{Q/!3r   r   c                 v      j                   rt         fd j                   D              S  j                  dz   S )z:degrees of freedom (nb of parameters) of the current modelc              3   \   K   | ]#  } j                   |   j                         % y wr
   )
complexitydim).0r*   rY   s     r   	<genexpr>z-LQModel.current_complexity.<locals>.<genexpr>  s'     HZ)tq)$((3Zs   ),r   )r   r4   r   rx   s   `r   r   zLQModel.current_complexity  s/     ::HTZZHHHxx!|r   Nc                 0   t        t               d|       j                         | _        g d| _        dg gz  \  | _        | _        | _        | _        | _	        | _
        t        | dgddg      | _        t        | dgd	
      | _        | j                          y)a  

        Increase model complexity if the number of data exceeds
        ``max(min_relative_size * df_biggest_model_type, self.min_absolute_size)``.

        Limit the number of kept data
        ``max(max_absolute_size, max_relative_size * max_df)``.

           )r^   r   r   Zcountshashes   logging_tracez||X[0]-X[1]||^2z||X[0]-Xopt||^2rL   rN   Modeleigenvalues)nameN)r   rR   r   rS   _fieldnamesr^   r   r   r   r   r   rV   rW   log_eigenvaluesr   )rY   r   r   r   r   r   s         r   rZ   zLQModel.__init__  s      (!T:DDFCCDt8@T[TO#4%68I%KL  &d]O+= ?

r   c                    | j                   D ]  }t        | |g         g | _        t        t              | _        d| _        	 d| _        | j                  j                  xs | j                  j                  | _        d| _        d| _        d| _        d| _        t!               | _        d\  | j"                  _        | j"                  _        y )Nlinearr   r   r   )r   setattrr   r   listtype_updates_typerT   rS   r   r   max_relative_size_coefficients_count_xopt_count_xoffsetnumber_of_data_last_addedr   r)   r   rY   r   s     r   r   zLQModel.reset	  s    $$DD$# %
'-
>
!%!E!E "=;; 	#% )*&5#' dhhjr   c                     t        j                  | j                  j                  d||| j                  kD  r| j                        S |      S )z&regression weights in decreasing orderr   )r   linspacerS   r   r   )rY   rk   s     r   sorted_weightszLQModel.sorted_weights  sD    {{4==33Q(.&499:L499( 	( &( 	(r   c                 B   t        | j                        dk  rddgS g }t        j                  | j                  d         | j                  d   z
  }t        j                  | j                  d         | j                  z
  }|t        |dz        t        |dz        gz  }|S )zBsome data of the current state which may be interesting to displayr9   r   r   )r   r^   r   r   r   r   )rY   traced1d2s       r   r   zLQModel.logging_trace   s     tvv;?q6MZZq	"TVVAY.ZZq	"TYY. 	#b!e*c"a%j))r   c                     t         | j                  | j                  d      | j                        | j                  z  | j
                  j                  f      S Nr   )r4   r   known_typesr   r   rS   r   rx   s    r   max_sizezLQModel.max_size-  sQ    9DOOD$4$4R$89$((C../MM335 6 	6r   c                 Z     | j                   | j                  d      | j                        S r   )r   r   r   rx   s    r   max_dfzLQModel.max_df3  s'    4tt//34TXX>>r   c                 ,    t        | j                        S )z+number of data available to build the modelr   r^   rx   s    r   r   zLQModel.size7       466{r   c                 `    t        | j                        rt        | j                  d         S d S )Nr   r   rx   s    r   r   zLQModel.dim<  s#    !$TVVs466!9~6$6r   c                    t        | j                        s*ddk  r$| j                  dk(  st        j                  d       yt        | j                        t        | j                  d         }}| j
                  ddd   D ]  }|| j                  j                  z   | j                  |   |      | j                  j                  z  k\  sJ|| j                  vsY|| j                  j                  vsr| j                  j                  |       || _        | j                          | j                  | j                  xx   |gz  cc<    y)z?model type/size depends on the number of observed data
        r   r   r   zempty model is not linearNr   r   )r   r^   _current_typer!   r"   r   rS   r   r   r   r   r   appendreset_Zr   rT   )rY   r   r   types       r   update_typezLQModel.update_type@  s     466{Avd00H<9:466{Cq	N1$$TrT*DDMM2226Kdood6KA6NQUQ^Q^QpQp6pp

* > >>

!!$'%)"!!$**-$7- +r   c                 `   t        | j                  d         }| j                  ddd   D ]m  }| j                  | j                  j
                  z   | j                  |   |      | j                  j                  z  k\  sT|| j                  j                  vsm n d}|| _	        | j                  S )zzone of the model `known_types`, depending on self.size.

        This may replace `types`, but is not in use yet.
        r   Nr   r   )
r   r^   r   r   rS   r   r   r   r   r  )rY   r   r  s      r   r  zLQModel.typeS  s    
 q	N$$TrT*D		DMM:::>Sdood>STU>VY]YfYfYxYx>xx > >> +
 D!!!!r   c                 6   t        | j                        | j                  kD  rt        | j                        | j                  j                  z  dz
  | j
                  | j                  j                  z  k\  r| j                  D ]  }t        | |      j                           t        | j                        | j                  kD  rUt        | j                        | j                  j                  z  dz
  | j
                  | j                  j                  z  k\  ryyyy)
deprecatedr   N)
r   r^   r   rS   r   r   r   r   getattrpopr   s     r   _prunezLQModel._pruneb  s    466{T]]*466{T]];;;a?4;;QUQ^Q^QpQpCpp((d#'') ) 466{T]]*466{T]];;;a?4;;QUQ^Q^QpQpCpp +p +r   c           	         t        | j                  t        | j                  | j                  | j
                  j                  z  | j
                  j                  z  f      z
        }|dk  ry| j                  D ]  }	 t        | |t        | |      d|           y# t        $ r/ t        | |      }t        |      D ]  }|j                           Y Yw xY w)z'prune data depending on size parametersr   N)r3   r   r4   r   r   rS   r   r   r   r   r	  r,   r   r
  )rY   remover   field_s        r   prunezLQModel.prunei  s    TYYdmm&*kkDMM4S4S&SVZVcVcVtVt&t&v "w w xQ;$$D dGD$$7&$AB %   d+vAIIK ' s   <B5CCc                    | j                  |      }|| j                  v rt        j                  d|rdndz          |syddk  r| j                  j                  d|       | j                  j                  d| j                  |             | j                  j                  d|       | j                  j                  d|       nt        j                  |g| j                  dkD  r| j                  gng z         | _        t        j                  | j                  |      g| j                  dkD  r| j                  gng z         | _        t        j                  |g| j                  dkD  r| j                  gng z         | _        t        j                  |g| j                  dkD  r| j                  gng z         | _	        | xj                  dz  c_        | j                  j                  d| j                         | j                  j                  d|       d| _        | j!                          |r| j#                          | j$                  j&                  r*| j$                  j'                  | j                        | _	        | S )	z1add `x` to `self` ``if `force` or x not in self``zx value already in Model, z!use `force` argument to force addznothing addedNr   r   r   r   )_hashr   r!   r"   r^   insertr   expand_xr   r   r   vstackrT   hstackr   r   r  r  rS   r   )rY   r   ru   r  forcehashs         r   r   zLQModel.add_data_roww  s   zz!}4;;MM67<3/S T6FFMM!QFFMM!T]]1-.FFMM!QFFMM!QYYs$**q.tvvhbIJDFYYa 01adffXUWXYDFYYs$**q.tvvhbIJDFYYs$**q.tvvhbIJDF

a
1djj)1d#)*&JJL==))]]33DFF;DFr   c                    t        |      t        |      k7  r"t        dt        |      t        |      fz        t        j                  |      ddd   }|D ]  }| j	                  ||   ||   |        t        |      | _        | S )zFadd a sequence of x- and y-data, sorted by y-data (best last)
        z+input X and Y have different lengths %d!=%dNr   )r  )r   rf   r   r   r   r   )rY   r^   r   r  rl   r%   s         r   r   zLQModel.add_data  s     q6SVJcRSfVYZ[V\M]]^^jjmDbD!AadAaD6 ),Q&r   c                 :   | j                   t        | j                        k(  sJ |t        | j                        }|dk  r| S t        |t        | j                        f      } |t        |      D cg c]  }| j                  |    c}      }| j                  D ]A  }t        | |      }|D cg c]  }||   	 }}t        t        |            D ]
  }||   ||<    C t        | j                  d|       t        | j                  d|       k(  sJ yc c}w c c}w )zXold? sort last `number` entries TODO: for some reason this seems not to pass the doctestNr   )
r   r   r^   r5   r   r   r   r	  r   sorted)rY   rk   r   r%   rl   r   r  tmps           r   _sortzLQModel._sort  s   yyCK'''>[FQ;Kfc$&&k*+%-8-Qtvvay-89$$DD$'E%()S58SC)3s8_q6a %	 % DFF7FO$tvvgv(???? 9 *s   2D.Dc                    ||du r| j                   }t        || j                   f      }|dk  r| S || j                   k  r || j                  d|       }n || j                        }| j                  D ]  }t	        | |      }	 ||   |d|  ddk  rtt        | j                  d|       t        | j                  d|       k(  sJ t        | j                        }| j                  |       |t        | j                        k(  sJ yy# t
        $ r3 |D cg c]  }||   	 nc c}w }}t        |      D ]
  }||   ||<    Y w xY w)zsort last `number` entriesNTr   r   r   )
r   r5   r   r   r	  r,   r   r   r  r  )	rY   rk   r   rl   r   r  r%   r$   r   s	            r   r   zLQModel.sort  sD    >Vt^YYFfdii()Q;KDII$&&&/*C$&&/C$$DD$'E$!&sgv % 6w(F466'6?,CCCCTVVAJJvTVV$$$	   $'*+s!U1Xs++vA tE!H '$s   DED"! EEc                    t        | j                        t        | j                        k(  rb|| j                  j                  k  rHt        | j                  j                  | j                  j                  | j                  z  f      | _        y y y r
   )	r   r   r   rS   r   r5   r   r   r   )rY   r)   s     r   r   zLQModel.adapt_max_relative_size  so    tzz?c$"2"233dmm>l>l8l%($--*M*M $ F FI_I_ _*a &bD" 9m3r   c                 D    t        j                  | j                  d      S )Nr   )axis)r   r   r^   rx   s    r   xmeanzLQModel.xmean  s    wwtvvA&&r   c                 X    t        j                  |      | _        | j                          y r
   )r   r   r   r  )rY   offsets     r   set_xoffsetzLQModel.set_xoffset  s    

6*r   c                     t        j                  | j                  D cg c]  }| j                  |       c}      | _        d| _        d| _        yc c}w )zset x-values Z attributer   N)r   r   r^   r  r   r   r   rY   r   s     r   r  zLQModel.reset_Z  sC    tvv>v!T]]1-v>?#%  ?s   Ac                    t        j                  |      | j                  z   }t        j                  d|g      }d| j                  v rt        j                  |t        j
                  |      g      }d| j                  v rat        j                  |t        t        |            D cg c],  }t        t        |            D ]  }||k  s	||   ||   z   . c}}g      }|S c c}}w )Nr   r   r   )r   r   r   r  r   squarer   r   )rY   r   zr%   r(   s        r   r  zLQModel.expand_x  s    JJqMDMM)IIq!f$**$		1biil+,A#IIqc!f"f1uUXYZU[}!`ade`e1Q4!A$;};"fgh #gs   '!C#	C#c                    | j                   r]t        |      t        | j                  d         k7  r9t        dt	        |      t        | j                  d         t        |      fz        | j                   dk  ry	 | j
                  | j                  |         }t        j                  | j                  |      S # t        $ r' | j                  |      rJ | j                  |      }Y Ow xY w)zreturn Model value of `x`r   zx = %s must be of len %d != %d)rT   r   r^   rf   r   r   indexisinr  r   dotcoefficients)rY   r   r*  s      r   rh   zLQModel.eval  s    ::#a&Cq	N2= #ADFF1IA?@ A A::?	!tzz!}%A vvd''++  	!yy|##a A	!s   ;B9 9-C)(C)c                 l    |D cg c]$  }| j                   dk(  rdn| j                  |      & c}S c c}w )z3never used, return Model values of ``x for x in X``r   )rT   rh   )rY   r^   r   s      r   evalpopzLQModel.evalpop  s@     A ZZ1_$))A,6 	 s   )1c                 h   | j                  | ||             | j                  |k  r| j                  dd }| j                  t        | j                         || j                               t	        || j                  z
  dz        dt	        t        j                  | j                  d         | j                  d   z
  dz        z  k  rMt        j                  | j                  d         | j                  d   z
  dz  }| j                  | ||             | j                  |k  r| j                  | fS )zthis works very poorly e.g. on Rosenbrock

        ::

            x, m = Model().optimize(cma.ff.rosen, [0.1, -0.1], 13)

        TODO (implemented, next: test): account for xopt not changing.
        Nr9   gMbP?r   r   )r   rT   r   r   r   r   r   r^   )rY   rO   x0r   xopt_oldx_news         r   optimizezLQModel.optimize  s     	"gbk*jj5 yy|Hd499owtyy/ABHtyy(1,-sBJJtvvay<QTXTZTZ[\T]<]`a;a7b0bbDFF1I.:a?!!%8 jj5  yy$r   c           
      *   |rt        d      t        || j                  f      }|| j                  _        | j
                  | j                  _        | j                  j                  dk  r5d| j                  _        d\  | j                  _        | j                  _        yt        | j                  d| t        |      D cg c]   }| j                  | j                  |         " c}      | j                  _        | j                  j                  S c c}w )zGreturn Kendall tau between true F-values (Y) and model values.
        z%save model evaluations if implementedr   Nr   r   )NotImplementedErrorr5   r   r)   r   rT   resultpvaluer-   r   r   rh   r^   )rY   rk   rs   r%   s       r   r   zLQModel.kendall  s     %&MNNfdii()
88::>"DHHO,0)DHHL$((/"466'6?BG-#P-QDIIdffQi$8-#PRxx|| $Qs   ?%D
c                     | j                  |      }|| j                  v r| j                  j                  |      dz   S dS )z9return False if `x` is not (anymore) in the model archiver   F)r  r   r,  )rY   r   r  s      r   r-  zLQModel.isin  s9    zz!}.2dkk.At{{  &*LuLr   c                 V    | j                   j                  | j                  |            S r
   )r   r,  r  r'  s     r   r,  zLQModel.index$  s    {{  A//r   c                 2   t        |t              r|S t        |t        j                        r	 t	        |j                               S 	 t	        |      S # t        $ r t	        t        |            cY S w xY w# t        $ r t	        t        |            cY S w xY wr
   )

isinstancer3   r   ndarrayr  tobytesAttributeErrorbytesr,   tupler'  s     r   r  zLQModel._hash'  s    aH2::&&AIIK((&Aw	 " &E!H~%&
  &E!H~%&s#   A 
A6 A32A36BBc                 j    t        j                  |t        j                  | j                  |            S )z^caveat: this can be negative because hessian is not guarantied
        to be pos def.
        )r   r.  hessian)rY   r&   s     r   mahalanobis_norm_squaredz LQModel.mahalanobis_norm_squared8  s$     vvb"&&r233r   c                 D   t        j                  | j                        }t        d| j                  j                  |       f      }|r%|d|  }| j                  | j                  |z
        }n| j                         }|t        j                  |      |   j                  z  S )jreturn weighted Z, worst entries are clipped if possible.

        Z can be a vector or a matrix.
        r   N)
r   r   r   r4   rS   remove_worser   r   r   T)rY   r   rl   clipws        r   old_weighted_arrayzLQModel.old_weighted_array>  s    
 jj At}}11$789fu+C##DII$45A##%A2::a=%''''r   c                     | j                   j                  |       }| j                   j                  |       }|| j                  k  r|d| }| j	                  |      t        j                  |      |   j                  z  S )rH  N)rS   r   r   r   r   r   r   rJ  )rY   r   r   rl   s       r   weighted_arrayzLQModel.weighted_arrayL  sl    
 }}11$7mm((.$))et*C""4(2::a=+=+?+???r   c           
         	 t         j                  j                  | j                  | j                              j
                  | _        | j                  S # t         j                  j                  $ r}t        j                  d| j                  rt        | j                  d         ndt        | j                        t        | j                        t        |      fz         Y d}~| j                  S d}~ww xY w)zreturn Pseudoinverse, computed unconditionally (not lazy).

        `pinv` is usually not used directly but via the `coefficients` property.

        Should this depend on something and/or become lazy?
        zAModel.pinv(d=%d,m=%d,n=%d): np.linalg.pinv raised an exception %sr   r   N)r   linalgpinvrO  r   rJ  _pinvLinAlgErrorr!   r"   r   r   r^   _coefficientsr   rY   laerrors     r   rR  zLQModel.pinvW  s    		'(;(;DFF(CDFFDJ zz yy$$ 	'MM 4*.))DFF1ID../DFFG	7&& ' ' zz	's   AA C62A/C11C6c                 R   | j                   | j                  k  r| j                  | _         t        j                  | j                  | j                  | j                              | _        | j                  j                          | j                  j                          | j                  S )z4model coefficients that are linear in self.expand(.))r   rT   r   r.  rR  rO  r   rU  rW   r   r   rx   s    r   r/  zLQModel.coefficientsk  sv     ##djj0'+zzD$!#		43F3Ftvv3N!ODKK  %%'!!!r   c                     t        | j                  d         }t        | j                        }||dz   g| j                  D cg c]  } | j                  |   |       c}z   v sJ t        j                  ||f      }d|z  dz   }t        |      D ]  }||dz   kD  r+d| j                  v sJ | j                  ||z   dz      |||f<   nW||dz   k(  sJ | j                  |dz      dz  |||f<   t        t        j                  | j                  dd              dz  |||f<   |d|z  kD  sd| j                  v sJ | | j                  d   |      k(  sJ t        |dz   |      D ]%  }| j                  |   dz  x|||f<   |||f<   |dz  }'  |S c c}w )Nr   r   r9   r   r   r   r   )r   r^   r/  r   r   r   zerosr   r   r5   abs)rY   r   r   r  Hkr%   r(   s           r   rE  zLQModel.hessianu  s   q	N!!"QUGDDTDTUDTD4tt4Q7DTUUUUUHHaVEAIqA1q5y"djj000++AEAI6!Q$AEz!z++AE2S8!Q$bffT%6%6qr%:;<sB!Q$1q5y+++3DOOF3A6666q1uaA(,(9(9!(<q(@@AadGa1gFA )  # Vs   Fc                 R    | j                   dt        | j                  d         dz    S )Nr   r   )r/  r   r^   rx   s    r   bz	LQModel.b  s&      3tvvay>A#566r   c           
         | j                   | j                  k  r| j                  | _         | j                  s3| j                  d   d| j                  dd  z  z
  | _        | j
                  S 	 t        j                  t        j                  j                  | j                        | j                  dz        | j                  z
  | _        | j
                  S | j
                  S # t        j                  j                  $ r}t        j                  d| j                   xs dt#        | j$                        | j&                  t)        |      fz         t+        | d      s^| j                   rRt        j,                  | j                         | _        t        j0                  j3                  | j                         | _        Y d }~| j
                  S d }~ww xY w)Nr   r9   r   g       zAModel.xopt(d=%d,m=%d,n=%d): np.linalg.pinv raised an exception %sr   _xopt)r   rT   r   r^   r/  ra  r   r.  rQ  rR  rE  r_  r   rT  r!   r"   r   r   rU  r   r   hasattrrZ  _optrandomrandnrV  s     r   r   zLQModel.xopt  sQ   djj(#zzD::!VVAYT->->qr-B)BB
 zz>!#		t||(Ddffsl!SVZVcVc!cDJ zztzz yy,, 
>MM #< $B #D$6$6 7 $		 #G	?.#. / #41dhh$&HHTXX$6	$&IIOODHH$=	zz
>s   +AC G<B:GGc                 ,    t        | j                        S )zsmallest f-values in data queue)r5   r   rx   s    r   minYzLQModel.minY  r   r   c                 f    t        t        j                  j                  | j                              S )z'eigenvalues of the Hessian of the model)r  r   rQ  eigvalsrE  rx   s    r   rN   zLQModel.eigenvalues  s"     bii''566r   )NNNNNr
   )TF)T)2r:   r;   r<   r   _complexitiesr   dictr   r   r   rZ   r   r   r   r   r   r   r   r  r  r  r  r   r   r   r   r  r   r   r"  r%  r  r  rh   r1  r6  r   r-  r,  r  rF  rM  rO  rR  r/  rE  r_  r   rg  rN   )r   cs   00r   rP   rP     s   Rh 
)*	346M "//A1Q4/Km$J  )-'+#'#'"4("( 
 
 6 6
 ? ?   7 78&"* <	   @$ 

 %6b
',
$ M
0&"4(	@  & " "  . 7 7  ,   7 7S 0s   D	rP   )$r   
__future__r   r   r   ___author____license__osr!   collectionsr   numpyr   r   r   r   ImportError	utilitiesr   rW   r   rV   utilities.utilsr   r   r-   r/   r   rH   r   r   r   r   r   r   rP   rF   r   r   <module>rv     s    @ @X~ 	  # (5  ) ?*X/ gW& gWR_ +V +86& 6o 6b7f b7  (((s   B B$#B$