
    J-j                        d Z ddlmZmZmZ ddlZddlZddl	Z
ddlZddlmZmZmZ ddlmZ ddlmZmZ ddlmZ dd	lmZmZ [[[ ej>                  d
d       d Z d Z!d Z" G d de#      Z$ G d de#      Z% G d dejL                        Z' G d de(      Z)d Z*d Z+d Z,d Z-d Z. G d de#      Z/d Z0 G d  d!e#      Z1d" Z2 G d# d$e#      Z3y)%zOA collection of (nonlinear) constraints handling classes and helper functions.
    )absolute_importdivisionprint_functionN)logical_and
logical_orlogical_not   )utils)Mhmoving_average)Logger)BestSolution2BestFeasibleSolutiononcez``import moarchiving`` failed.*messagec                 &    t        d | D              S )Nc              3   .   K   | ]  }|d kD  r|nd   ywr   N .0gis     e/Users/jameslopez/projects/TradingBot25/.venv/lib/python3.12/site-packages/cma/constraints_handler.py	<genexpr>z_g_pos_max.<locals>.<genexpr>   s     3UrR!Vr"Us   )maxgvalss    r   
_g_pos_maxr      s    3U333    c                 &    t        d | D              S )Nc              3   ,   K   | ]  }|d kD  s	|  ywr   r   r   s     r   r   z_g_pos_sum.<locals>.<genexpr>   s     ,EbR!VrEs   
sumr   s    r   
_g_pos_sumr%      s    ,E,,,r    c                 &    t        d | D              S )Nc              3   2   K   | ]  }|d kD  s	|dz    yw)r      Nr   r   s     r   r   z%_g_pos_squared_sum.<locals>.<genexpr>   s     /uQr1uus   

r#   r   s    r   _g_pos_squared_sumr)      s    /u///r    c                   "    e Zd ZdZefdZddZy)ConstrainedSolutionsArchiveai  Biobjective Pareto archive to store some Pareto optimal solutions
    for constrained optimization.

    The user can define the aggregator for the constraints values which
    is by default the sum of the positive parts.

    The Pareto archive is maintained in the `archive` attribute and the
    Pareto optimal solutions can be recovered in `archive.infos`.
c                     || _         d | _        d| _        d| _        	 dd l}|j                         | _        y # t
        $ r d}t        j                  |       Y y w xY w)Nr   
   zt``import moarchiving`` failed, hence convergence tracking is disabled. 
  'pip install moarchiving' should fix this.)	
aggregatorarchivecountmaxlenmoarchivingImportError	_warningswarn!BiobjectiveNondominatedSortedList)selfr.   r2   ms       r   __init__z$ConstrainedSolutionsArchive.__init__"   s`    $
	 #DDF  	OANN1		s   8  AANc                 Z   | xj                   dz  c_         | j                  | j                  |      }	 | j                  j                  ||g|       t        | j                        | j                  kD  r| j                  d   d   dkD  r)| j                  j                  | j                  d          n(| j                  j                  | j                  d          t        | j                        | j                  kD  ry y y # t        $ r  | j                  j                  ||g       Y w xY w)Nr	   infor   )r0   r/   r.   add	TypeErrorlenr1   remove)r7   fgr<   gaggs        r   updatez"ConstrainedSolutionsArchive.update/   s    

a
<<#??1%D,  !T 6 dll#dkk1<<?1%)LL''Q8LL''R(89	 dll#dkk1 $  ,  !T+,s   D &D*)D*N)__name__
__module____qualname____doc__r%   r9   rE   r   r    r   r+   r+      s     #- G:r    r+   c                   .    e Zd ZdZddZd Zed        Zy)PopulationEvaluatora  evaluate and store f- and g-values of a population in attributes F and G.

    If the g-function (`constraints`) has an `insert` method, `x`-values
    are "inserted" first.

    If the `constraints` function has a `true_g` attribute (assigned during
    the call) and ``offset_from_true_g is True``, population constraints
    values are corrected by an offset to guaranty that ``g >= 0`` if
    ``true_g > 0``. Named solutions are not offset.

    c                 <    || _         || _        || _        || _        y rF   )	objectiveconstraintsoffset_from_true_ginsert)r7   rN   rO   rQ   rP   s        r   r9   zPopulationEvaluator.__init__H   s     "&"4r    c                    || _         |D cg c]  }| j                  |       c}| _        | j                  rW	 |D ]  }| j                  j                  |        |j                         D ]   \  }}| j                  j                  |       " 	 	 t        | j                  d      st        |D cg c])  }| j	                  |      | j                  j                  f+ c}| _
        | j                  D cg c]  }|d   	 c}| _        | j                  D cg c]  }|d   	 c}| _        | j                  rt        t        | j                  d               D ]  }d}t        t        | j                              D ]K  }| j                  |   |   dkD  s| j                  |   |   |z   dk  s2| j                  |   |    }|dk\  rKJ  t        t        | j                              D ]2  }| j                  |   |   dkD  s| j                  |   |xx   |z  cc<   4  t!        j"                  t        t        | j                              D cg c]`  }t!        j"                  t!        j$                  | j                  |         t!        j$                  | j                  |         dkD     dk\        b c}      sJ |j                         D ]4  \  }}t'        | ||| j                  |      | j	                  |      d       6 | S c c}w # t        t        f$ r Y w xY wc c}w c c}w c c}w c c}w # t        $ r- |D cg c]  }| j	                  |       nc c}w c}| _        Y w xY w)a  `kwargs` are named solutions resulting in

    ::

            self.name['x'] = kwargs[name]
            self.name['f'] = self.objective(kwargs[name])
            self.name['g'] = self.constraints(kwargs[name])

        Store result in attributes `F` and `G`.
        true_gr   r	   )xrB   rC   )XrN   FrQ   rO   itemsAttributeErrorr?   hasattrrS   G_allGG_truerP   ranger@   npallasarraysetattr)	r7   rU   kwargsrT   namer[   joffsetis	            r   __call__zPopulationEvaluator.__call__N   s    -./Q$..#Q/;;A$$++A. %||~GD!$$++A.  .	:4++X6$$RSTRSQ4++A.0@0@0G0GHRSTDJ %)JJ/JqadJ/DF)-4A1Q44DK&&s466!9~.AF"3tvv;/;;q>!,q0TVVAYq\F5JQ5N&*ffQil]F#)Q;.; 0 #3tvv;/;;q>!,q0 FF1IaLF2L 0 / vv%*3tvv;%79%7  "vvbjj&;BJJt{{ST~<VYZ<Z&[_`&`a%79 : : :||~GD!D$a&*nnQ&7&*&6&6q&9!; < & G 0 #I. 
 U 049!  	63451ad&&q)15DF	6sZ   LAL	  L3 0.LL3 4L$L)A%L.	LLL3 3M) MM)(M)c                 p    t        j                  t        j                  | j                        dk  d      S )z or bias for equality constraintsr   axis)r^   meanr`   r[   r7   s    r   feasibility_ratiosz&PopulationEvaluator.feasibility_ratios   s'     wwrzz$&&)Q.Q77r    N)TF)rG   rH   rI   rJ   r9   rg   propertyrm   r   r    r   rL   rL   <   s&    
/b 8 8r    rL   c                        e Zd ZdZddZddZy)DequeCDFa  a queue of vectors with element-wise cdf computation.

    The `deque` is here used like a `list` with maximum length functionality,
    the (inherited) constructor takes `maxlen` as keyword argument (since Python 2.6).

    >>> import cma
    >>> d = cma.constraints_handler.DequeCDF(maxlen=22)
    >>> for i in range(5):
    ...     d.append([i])
    >>> ' '.join(['{0:.2}'.format(x) for x in
    ...                   [d.cdf(0, 0), d.cdf(0, 2), d.cdf(0, 2.1), d.cdf(0, 22.1), d.cdf(0, 4, 2)]])
    '0.1 0.5 0.6 1.0 0.75'

    Nc                    t        t        |xs t        |       t        |       f            }t        j                  t        | d      D cg c]
  }| |   |    c}      }t        j                  ||k  d||k(  z  z         S c c}w )zreturn ecdf(`val`) from the `i`-th element of the last `len_` values in self,

        in other words, the ratio of values in ``[v[i] for v in
        self[-len_:]]`` that are smaller than `val` where equality counts
        1/2.
        r         ?intminr@   r^   r`   r]   rk   )r7   rf   vallen_j0rd   datas          r   cdfzDequeCDF.cdf   sx     d'c$iT345zzubS!}=}!471:}=>wws
cTS[&99:: >s   Bc                    t        t        |xs t        |       t        |       f            }t        j                  t        | d      D cg c]  }| |   	 c}      }t        j                  ||k  d||k(  z  z         S c c}w )z9return ECDF at `val` in case this is a `deque` of scalarsr   rr   rs   )r7   rv   rw   rx   rd   ry   s         r   cdf1zDequeCDF.cdf1   sr    d'c$iT345zzE2#qM:Mq47M:;wws
cTS[&99:: ;s   A?r   )rG   rH   rI   rJ   rz   r|   r   r    r   rp   rp      s    	;;r    rp   c                       e Zd ZdZddZy)
LoggerListz list of loggers with plot methodc                    ddl }ddl m} |j                  dddd       |j                         j	                  d	       t        |       D ]  \  }}t        j                         5  t        j                  d
d       |j                  dd|dz   d       ddd       |j                          t        |j                  j                        dkD  s|j                  j                  d   dkD  st        |j                  j                        D ]  \  }}|t        |j                  j                        dz
  k  r(|j                  t        |      |d   t        |             |dk(  sY|j                  t!        |t#        |t        |      f            dd        |dk(  sVt%        j&                  |j                        }t)        dt%        j"                  ||dkD           f      }	t+        j,                  |j.                  d      dk\  r|j1                  d|	       |j1                  d|	        y# 1 sw Y   xY w)z9versatile plot method, argument list positions may changer   N)pyplot   r(   r	   F)frameon   ignorez'Adding an axes using the same argumentsr   r=   rg333333?)color	linewidth&.>z3.3symlog)	linthresh)
linthreshy)
matplotlibr   subplotgcfset_figheight	enumerater4   catch_warningsfilterwarningsplotr@   ry   shapeTtextstrr   ru   r^   absr   r
   version_diff__version__yscale)
r7   moving_window_widthr   pltrf   loggerrd   dvmin_vals
             r   r   zLoggerList.plot   s   , 	Aq!U+	""4IAv))+((;deAq!a%7 , KKM6;;$$%)fkk.?.?.BQ.F%fkkmm4DAq3v{{}}-11Q2A7Av38KSQRV7T3U!V'*d ! <	 5 6v{{+A!4!A#"89G))**@*@%HAM

8w
?

8
@) )++s   %0H44H>	N)r   )rG   rH   rI   rJ   r   r   r    r   r~   r~      s    *Ar    r~   c                 "    | j                   dgz   S Nr   )rC   ss    r   _log_gr      s    33!9r    c           	      B   t        | j                        D cg c],  \  }}|d|dkD  z  z   dz
  dt        j                  |      z  z   . c}}t	        | j                        t        j
                  t        j                  | j                        dkD        z   gz   S c c}}w )Nrr   r         ?皙?)r   rC   r^   tanhr@   anyr`   )r   rf   r   s      r   _log_feas_eventsr      s    GPQRQTQT~ ~eaArAv%bggbk(99~ QSSBFF2::acc?Q#67789 9 s   1Bc           	          t        j                  t        j                  dt        j                  | j                  | j
                  dn| j
                  z
                    }t        j                  |dg      S )zOfor active constraints, lam is generally positive because Dg and Df are opposedr   r   )r^   log10maximumr   lamlam_opthstackr   r   s     r   _log_lamr      sO    
D"&&qyy7H!aii)X"YZ[A99aVr    c                     t        j                  t        j                  | j                  d            }t        j                  |dg      S )Nr   r   )r^   r   r   mur   r   s     r   _log_mur      s2    
ADD$'(A99aVr    c                 r    t        d | j                  D              r| j                  S t        j                  S )Nc              3   &   K   | ]	  }|d k    ywr   r   r   s     r   r   z_log_feas_f.<locals>.<genexpr>   s     ,"bAg   )r_   rC   rB   r^   nanr   s    r   _log_feas_fr      s&    ,,,1338"&&8r    c                   <    e Zd ZdZddZd	dZed        Zd Zd Z	y)
CountLastSameChangesa  An array/list of successive same-sign counts.

    ``.same_changes[i]`` counts how often the same sign was successively
    observed during ``update(..., i, change)``. When the sign flips,
    ``.same_changes[i]`` is reset to 1 or -1.

    `init` needs to be called before the class instance can be used.
    A valid use case is ``lsc = CountLastSameChanges().init(dimension)``.

    TODO: parameters may need to depend on population size?
    Nc                 @    d | _         || _        	 	 d | _        d | _        y rF   )same_changesparentchi_exponent_thresholdchi_exponent_factor)r7   r   s     r   r9   zCountLastSameChanges.__init__   s*     D-&*##' `r    c                     |s| j                   |dgz  | _         |s| j                  d| j                  z   | _        |s| j                  d| j                  z  | _        | S )z/do not overwrite user-set values unless `force`r   r(      )r   r   	dimensionr   )r7   r   forces      r   initzCountLastSameChanges.init   sg    D%%- )QCDD//7 +,dnn*<D'D,,4 ()4+F+F'FD$r    c                 ,    t        | j                        S rF   )r@   r   rl   s    r   r   zCountLastSameChanges.dimension   s    4$$%%r    c                 |    || j                   |   z  dk  rd| j                   |<   | j                   |xx   |z  cc<   | S )z>update ``same_changes[i]`` count based on the sign of `change`r   )r   )r7   rf   changes      r   rE   zCountLastSameChanges.update   sE    D%%a((1,#$Da !&r    c                     | j                   |   }t        j                  |      }||| j                  z  z  }|||z  dkD  z  }| j                  |z  t        | j                  ||z  f      z  S )a  return value to be added to exponent from change count.

        return a positive/negative value (or zero) when the last change was
        respectively postive/negative.

        The value is zero for the first `chi_exponent_threshold` same changes
        and increases linearly for the next `chi_exponent_threshold` same changes
        and then stays at the threshold value as long as the change does not
        flip sign.
        r   )r   r^   signr   r   ru   )r7   rf   r   r   s       r   shape_exponentz#CountLastSameChanges.shape_exponent   st     a GGAJ	Q,,,,	QUQY''!+c43N3NPQTUPU2V.WWWr    rF   F)
rG   rH   rI   rJ   r9   r   rn   r   rE   r   r   r    r   r   r      s1    
a & &Xr    r   c                 ,    ||||t        |      z   || dS )z>return dictionary with arg values, mainly there to unify names)rT   rB   rC   f_alg_alr0   r#   )r0   rT   rB   rC   r   s        r   constraints_info_dictr     s#    AD	M4 r    c                       e Zd ZdZddZd Zd Zd ZddZd Z	e
d	        Ze
d
        Ze
d        Ze
d        Zd Zd Zd Ze
d        Zd ZddZddZddZddZddZddZd Zy)AugmentedLagrangiana  Augmented Lagrangian with adaptation of the coefficients

    for minimization, implemented after Atamna et al FOGA 2017,
    Algorithm 1 and Sect 8.2, https://hal.inria.fr/hal-01455379/document.

    `cma.ConstrainedFitnessAL` provides a (more) user-friendly interface to
    the `AugmentedLagrangian` class.

    Input `dimension` is the search space dimension, boolean `equality`
    may be an iterable of length of number of constraints indicating the
    type for each constraint.

    Below, the objective function value is denoted as ``f = f(x)``, the
    constraints values as ``g = g(x) <= 0``, the penalties compute to
    ``penalties(x) = self(g(x)) = lam g + mu g^2 / 2`` (if g > -lam / mu) for
    each element of g, as returned by calling the instance with g as argument.

    The penalized "fitness" value ``f + sum(self(g))`` shall be minimized.
    lam and mu are the Lagrange multipliers or coefficients.

    An additional method, `set_coefficients` allows to initialize the
    Lagrange multipliers from data.

    A short example (and doctest):

    >>> import cma
    >>> from cma.constraints_handler import AugmentedLagrangian, PopulationEvaluator
    >>> m = 2  # number of constraints
    >>> def objective(x):
    ...     return sum(x[m:]**2) + sum((x[:m] - 1)**2) - m
    >>> def constraints(x):
    ...     return x[:m]
    >>> es = cma.CMAEvolutionStrategy(3 * [1], 1, {
    ...          'termination_callback': lambda es: sum(es.mean**2) < 1e-8})  #doctest: +ELLIPSIS
    (3_w,7)-aCMA-ES...
    >>> al = AugmentedLagrangian(es.N)  # lam and mu still need to be set
    >>> # al.chi_domega = 1.15  # is the new default, which seems to give better results than the original value
    >>> # al.lam, al.mu = ...  # we could set the initial Lagrange coefficients here
    >>> while not es.stop():
    ...     eva = PopulationEvaluator(objective, constraints)(es.ask(), m=es.mean)
    ...     al.set_coefficients(eva.F, eva.G)  # set lam and mu, not part of the original algorithm
    ...     al.update(eva.m['f'], eva.m['g'])
    ...     es.tell(eva.X, [f + sum(al(g)) for f, g in zip(eva.F, eva.G)])
    >>> if es.result.evaluations > 3100:
    ...     print("evaluations %d !< 3100. 1500 is normal, 2700 happens rarely" % es.result.evaluations)
    >>> assert 'callback' in es.stop()
    >>> assert len(eva.feasibility_ratios) == m
    >>> assert sum(eva.feasibility_ratios < 0) == sum(eva.feasibility_ratios > 1) == 0

    Details: the input `dimension` is needed to compute the default change
    rate `chi_domega` (if ``chi_domega is None``), to compute initial
    coefficients and to compare between h and g to update mu. The default
    dependency of `chi_domega` on the dimension seems to be however
    suboptimal. Setting ``self.chi_domega = 1.15`` as is the current
    default seems to give better results than the original setting.

    More testing based on the simpler `ConstrainedFitnessAL` interface:

    >>> import cma
    >>> for algorithm, evals in zip((0, 1, 2, 3), (2000, 2200, 1500, 1800)):
    ...     alf = cma.ConstrainedFitnessAL(cma.ff.sphere, lambda x: [x[0] + 1], 3,
    ...                                    find_feasible_first=True)
    ...     _ = alf.al.set_algorithm(algorithm)
    ...     alf.al.logging = False
    ...     x, es = cma.fmin2(alf, 3 * [1], 0.1, {'verbose':-9, 'seed':algorithm},  # verbosity+seed for doctest only
    ...                       callback=alf.update)
    ...     assert sum((es.mean - [-1, 0, 0])**2) < 1e-9, (algorithm, es.mean)
    ...     assert es.countevals < evals, (algorithm, es.countevals)
    ...     assert alf.best_feas.f < 10, (algorithm, str(alf.best_feas))
    ...     # print(algorithm, es.countevals, ) #alf.best_feas.__dict__)

c                    d| _         || _        d\  | _        | _        t	        j
                  d      | _        t	        j
                  |t              | _        d| _	        d| _
        t        d| j                  dz  z         | _        	 ddgz  \  | _        | _        d| _        d| _        	 t#               | _        	 t'        j(                  t              | _        t-        | j                  d	z   
      | _        	 t'        j(                  t1        j2                  t,        d| j                  z  d	z   
            | _        	 d| _        d| _        d| _        | j=                          | j?                          y)zBuse `set_algorithm()` and ``set_...()`` methods to change defaultsr   )NNFdtype   r	   r(   N   )r1   ) 	algorithmr   r   r   r^   array_initializedbool	_equalityk2dgammart   mucdf3_horizonrB   rC   r0   count_g_in_penalized_domainr   count_mu_last_same_changes_collectionsdefaultdictcountsrp   	g_history
_functoolspartialg_allcount_callsr   logging_set_parameters_init_)r7   r   equalitys      r   r9   zAugmentedLagrangian.__init__]  s)   "&$'HHUO($7!!dnna&7"78;dV
+,(N*>*@'\"..s3!")<=(!--j.@.@RSVZVdVdRdgiRi.jk
Hr    c                 B    d| _         dd| j                  z  z  | _        | S )z$Atamna et al 2017 parameter settingsr   r(   r   k1r   
chi_domegarl   s    r   set_atamna2017z"AugmentedLagrangian.set_atamna2017z  s#    ft~~56r    c                 H    d| _         dd| j                  dz  z  z  | _        | S )z(Dufosse & Hansen 2020 parameter settingsr-   r(   g      ?rr   r   rl   s    r   set_dufosse2020z#AugmentedLagrangian.set_dufosse2020  s(    b4>>3#667r    c                    | j                   dk  r| j                          y| j                   dv r| j                          y| j                   dk(  r| j                          yt        dj	                  | j                               )z5set parameters based on the value of `self.algorithm`r   )r	   r   r   r(   z"Algorithm id {0} is not recognizedN)r   r   r   
ValueErrorformatrl   s    r   r   z#AugmentedLagrangian._set_parameters  se    >>Q!^^y(!^^q   "AHHXYYr    Nc                 n    || j                   S || j                   k7  r|| _         | j                          | S )zif algorithm not `None`, set it and return self,

        otherwise return current algorithm value which should be an integer.

        Values < 1 are the (new) default, 1 == Atamna et al 2017, 2 == modified 1.
        )r   r   )r7   r   s     r   set_algorithmz!AugmentedLagrangian.set_algorithm  s8     >>!$..(&DN  "r    c           	         t               | _        | j                  dkD  rk| j                  j                  t	        | t
        gdgd             | j                  j                  t	        | t        gddgd             | j                  j                  t	        | t        g| j                  d	nd
gd             | j                  j                  t	        | t        gdgd             | j                  j                  t	        | dt        gddgd             | j                  j                  t	        | t        gdgd             d| _        | j                  dv r0t	        ddd| j                  z  d| j                  z  g      | _        yyy)z,allow to reset the logger with a single callr   zconstraint values
outauglagg)	callableslabelsrc   zsign(gi) / 2 + izoverall feasibilityoutauglagfeasNzlg(abs(lambda))zlg(abs(lambda-lam_opt))outauglaglamzlg(mu)outauglagmurB   z
feasible f
outauglagfoutauglagfeasf)r	   r(   mu_conditionsz$\mu$ increasesz$\mu g^2 < %.0f |\Delta h| / n$z$|\Delta g| < |g| / %.0f$)r   )r~   loggersr   append_Loggerr   r   r   r   r   r   logger_mu_conditionsr   r   r   rl   s    r   r   zAugmentedLagrangian._init_  sw   !|<<!LL$7#8!-!/ 0 LL9I8J$69N#O!0!2 3 LL
-1\\-A)68#!% & LL	$,:M!C DLLck]$'#6\!K LLL$0>!1!3 4 )-D%~~',3O.>H8477BMD -E) (' r    c                 ,    t        | j                        S )z7number of constraints, raise `TypeError` if not set yet)r@   r   rl   s    r   r8   zAugmentedLagrangian.m  s     488}r    c                 v    	 t        | j                        S # t        $ r t        | j                        cY S w xY wrF   )r_   r   r?   r   rl   s    r   is_initializedz"AugmentedLagrangian.is_initialized  s8    	+t(()) 	+))**	+s    88c                 h    | j                   dS t        | j                  | j                   dkD  z        S )z3number of constraints with initialized coefficientsr   )r   r$   r   rl   s    r   count_initializedz%AugmentedLagrangian.count_initialized  s/     GGOqOT->->$''A+-N)OOr    c                     	 t        j                  | j                        j                  D cg c]-  }t        j                  t        j                  |      dk        / c}S c c}w # t
        $ r Y yw xY w)z@or bias for equality constraints, versatile interface may changer   N)r^   r`   r[   r   rk   rX   )r7   rC   s     r   rm   z&AugmentedLagrangian.feasibility_ratios  s\    	9;DFF9K9M9MN9MABGGBJJqMQ./9MNNN 		s"   +A' 2A"A' "A' '	A32A3c                     | j                   J t        j                  |      | _         t        j                  |      | _        t        j                  |t              | _        y)zinitialize attributes which depend on the number of constraints.

        This requires the `lam` attribute to be `None` and deletes all
        previously set or adapted `mu` coefficients.
        Nr   )r   r^   zerosr   r   r   )r7   r8   s     r   set_mzAugmentedLagrangian.set_m  sE     xx88A;((1+HHQd3r    c                     dD ]H  }t        | |      j                  dk7  st        | |t        j                  t        | |      d             J | j
                  j                  dk(  sJ y)z#in case the user set the attributes)r   r   floatr   r   N)getattrr   ra   r^   r   r   )r7   rc   s     r   _check_dtypesz!AugmentedLagrangian._check_dtypes  s[    !DtT"((G3dBHHWT4-@$PQ "   &&&000r    c                    ||c| _         | _        | j                  &t        | j                  | j                  dkD  z        ryt        j                  |      j                  }ddt        j                  |dkD  d      z  z   }| j                  | j                  t        |             nq| j                  j                  s[| j                  dd | j                  dd c| _        | _        t        j                  | j                   | j                  gz        | _        | j#                          t%        t'        t)        | j                        | j                  dk(        t'        |dkD  | j*                              }t        j,                  |      rt/        j0                  |      }t        j                  |D cg c]  }t/        j0                  |       c}      }t        j                  |D cg c]  }t/        j0                  |dz         c}      }t        j,                  |dk(        s0t        j,                  |dk(        st        j,                  |dk(        r9t3        j4                  dt7        |      d	t7        |      d	t7        |             t        j                  |dk\        r0t        j                  |dk\        rt        j                  |dk\        sJ d
|z  | j8                  z  |d|z  z   d|dz   z  z   z  }	t%        |t)        | j*                              }
t        j,                  |
      r+|| j8                  ||
   z  d|dz   z  z   z  | j                  |
<   t        j:                  |      dk  }t%        t%        t'        |t%        t)        | j*                        |dk              t'        | j                  dk(  | j                  |	kD              |      }t%        t%        t%        t)        |      t'        | j*                  |dkD              | j                  |	k        |      }t%        |t)        t'        ||                  }t        j<                  t%        ||            dk(  sJ t        j,                  |      rl| j                  |   dkD  }t        j,                  |      r3| j                  |   |xx   |	|   |   | j                  |   |   z  z  cc<   |	|   | j                  |<   t        j,                  |      r|	|   | j                  |<   t        j,                  |      r|	|   | j                  |<   ddk  r|	|   | j                  |<   d| j                  t%        |t'        | j>                  d| j8                  z   kD  t        j:                  |      dk              <   yt        | j                        r/t        | j                  dkD        rt3        j4                  d       yyyc c}w c c}w )aH  compute initial coefficients based on some f- and g-values.

        The formulas to set the coefficients::

            lam = iqr(f) / (n * iqr(g))
            mu = 2 * iqr(f) / (5 * n * (iqr(g) + iqr(g**2)))

        are taken out of thin air and not thoroughly tested. They are
        additionally protected against division by zero.

        Each row of `G` represents the constraints of one sample measure.

        Set lam and mu until a population contains more than 10% infeasible
        and more than 10% feasible at the same time. Afterwards, this at least...?...
        Nr   r=   r(   r	   ri   gziqr(f), iqr(G), iqr(G**2)) == z, 皙?gư>gdy=r      r   Tg?zCoefficients are already fully initialized. This can (only?) happen if
the coefficients are set before the `_initialized` array.) rV   r[   r   r_   r   r^   r`   r   rk   r   r  r@   r   lam_oldmu_oldr   r8   r  _and_or_not
isequalityr   _Mhiqrr4   r5   r   r   r   r$   r0   )r7   rV   r[   sign_averageidxdfrC   dGdG2mu_new	idx_inequiscloseidx1idx2idx3iidx1s                   r   set_coefficientsz$AugmentedLagrangian.set_coefficients  s     A773t'8'8DGGaK'H#IJJqMOOAAA 66688JJs1v""(((,TWWQZ%DL$+ "43D3D2E)E FD3tD--.1=|d*DOO<> 66#;B3ASWWQZ34B**Q7QcggadmQ78CvvbAg"&&q/RVVC1H5ESQSWVYZ\V]_bcf_ghi66"'?rvvbAg266#(;KKKb[4>>1R$*_uPRUVPVGW5WXFS$t"78Ivvi &(DNNR	],JUVX[\V\M],]&^# ff\*c1GS!%d4??&;\S=P!QS Atww/?@B !"D T$w-"%doo|c7I"JL"&''F"24 #&'D T#dD/23D66$tT*+q000vvd|)66%=HHTN5)VD\%-@4774=QVCW-WW) &tvvd| &tvvd| &tAv%c{LP d3DJJT^^9K,K,.FF<,@3,F)H I J""#DGGaK(8NNLM )9#K 47s   4W)*W.c                     	 t        | j                         | j                  S # t        $ rD t        j                  | j
                  | j                  rdndgz        | _        Y | j                  S w xY w)zAbool array, `True` if `i`-th constraint is an equality constraintTF)r@   r   r?   r^   r`   r8   rl   s    r   r   zAugmentedLagrangian.isequality+  sa    	V ~~  	VZZ$..$e1T(TUDN~~	Vs   # ?A0/A0c                 4   	 | xj                   | j                  |z  d| j                  z  kD  z  c_         t	        t        |            D ]#  }| j                  |   j                  ||          % | j                  dgt        |      z  S t        | j                        t        | j                        k(  sJ t        |      t        | j                        k7  r,t        dt        |      t        | j                        fz        | j                  j                  dk(  sJ t        t        | j                        | j                  |z  d| j                  z  k        }t        |      r:t        j                  |d      }| j                  |    | j                  |   z  ||<   | xj                   dz  c_        t	        t        |            D cg c]3  }| j                  |   ||   z  d| j                  |   z  ||   d	z  z  z   5 c}S # t        $ r Y w xY wc c}w )
zreturn `list` of AL penalties for constraints values in `g`.

        Penalties are zero in the optimum and can be negative down to
        ``-lam**2 / mu / 2``.
        r=   g        z.len(g) = %d != %d = # of Lagrange coefficientsr   T)copyr	   rr   r(   )r   r   r   r?   r]   r@   r   r  r   r   r   r  r  r   r^   r   r   )r7   rC   rf   r$  s       r   rg   zAugmentedLagrangian.__call__4  s   	,,!b488m0KK, s1vAJJqM  1& 884#a&= 488}DGG,,,q6S]"M #ADHH67 8 8~~##v---4'1rDHH})DEs8&Ahhsm^dggcl2AcFAs1v(&A ad"S4771:%5!a%??&( 	(!  		 (s   2H 
8H	HHc                     t        d| j                  dz  z         }|| j                  j                  |||dz  z         cxk  xr d|z
  k  nc  }|xr ||   | j                  |   z  dkD  S )zEprovisorial function to correct mu plus condition, original is `True`r	   rr   r(   rw   r   )rt   r   r   rz   rC   )r7   rC   rf   	thresholdncpluss         r   muplus2zAugmentedLagrangian.muplus2O  so     DNNC''( 2 211q1u9 2 EUIUU-1q	)A--r    c                 b    || j                   j                  |      cxk  xr
 d|z
  k  }|S c }|S )zFprovisorial function to correct mu minus condition, original is `True`r	   )r   rz   )r7   rC   rf   r5  ress        r   muminus2zAugmentedLagrangian.muminus2U  s:    $..,,Q/?!i-? 
 @ 
r    c                     ||   dkD  ry||   | j                   |   z  | j                  |    kD  r.| j                  j                  || j                        }||kD  r	 yy)zreturn `True` if mu should be increased, else `False`.

        TODO: because the stationary condition is g == 0, it seems
        unreasonable to always increase mu when g > 0?
        r   Tr4  F)r   r   r   rz   r   r7   rC   rf   r5  p_feass        r   muplus3zAugmentedLagrangian.muplus3[  sk     Q4!8Q4$''!*|+^^''0C0C'DF 	!! r    c                 p    | j                   j                  || j                        }||k  r
d||   kD  r	 yy)aM  return `True` if mu should be reduced, else `False`.

        If mu is large, the augmented function is steeper on the infeasible
        side. Consequently, typically g < 0 and, if the constraint is
        active, some solution will still be infeasible. If this is the
        case, we decrease mu.

        TODO: if more than 50% are infeasible, we may not want to decrease
        mu further? This usually does not happen, because we increase mu
        when g > 0. However, if the constraint is a nonsmooth 1/2^n sector,
        the feasiblity ratio goes inevitably to 1/2^n.
        r4  r   TF)r   rz   r   r=  s        r   muminus3zAugmentedLagrangian.muminus3m  s>     ##AD,?,?#@I!ad(Er    c                    | j                   |   j                  d| j                  z        dk(  ry||   | j                  |   z  | j                  |    kD  r.| j
                  j                  || j                        }||kD  r	 yy)z5return `True` if mu should be increased, else `False`r(   r4  r   TF)r   r|   r   r   r   r   rz   r   r=  s        r   muplus4zAugmentedLagrangian.muplus4  s    ::a=1T^^#349Q4$''!*|+^^''0C0C'DF	!! r    c                     ||   | j                   |   z  d| j                  |   z  k  r1| j                  |   j                  d| j                  z        dk  r	 yy)z3return `True` if mu should be reduced, else `False`r=   r(   r4  r	   TF)r   r   r   r|   r   )r7   rC   rf   r5  s       r   muminus4zAugmentedLagrangian.muminus4  sX    Q4$''!*rDHHQK//

1""$..(8"9A=Er    c                    | j                   j                  |       | j                  [	 | xj                  dz  c_        | j                  d| j                  dz  z   z  dk  r"t        j                  d| j                  z         y| j                  dk(  ry| j                          | j                  t        j                  | j                  dkD        rt        | j                        t        | j                        cxk(  rt        |      k(  sJ  J ddk  r=| j                  s1| j                  dk  r"t        j                  d	| j                  z         t        j                   |      | j                  z
  }|t#         | |            z   | j$                  z
  t#         | | j                              z
  }| j&                  j)                  t        | j                               t+        t        | j                              D ]  }| j,                  dkD  r| j                  dz   | j,                  z  s| j.                  rt1        | j                  |   ||   d
z  z  | j2                  t        j4                  |      z  | j6                  z  k        }t1        | j8                  t        j4                  ||         z  t        j4                  | j                  |         k        }| j.                  j;                  |dz
  dt        j                   t=        ||f      d|z   d|z   g      z  z          | j                  |   dk(  r=| j>                  |   sW||   | j                  |   z  | j                  |    kD  s1tA        jB                  | jD                        r| jD                  |   dkD  r7| j                  |xx   | j                  |   ||   z  | jF                  z  z  cc<   | j>                  |   s#| j                  |   dk  rd| j                  |<   | j>                  |   s(||   | j                  |   z  | j                  |    k  rC| jH                  dk(  r| j                  |   ||   d
z  z  | j2                  t        j4                  |      z  | j6                  z  k  sH| j8                  t        j4                  ||         z  t        j4                  | j                  |         k  r&| j                  |xx   | j                  dz  z  cc<   | j                  |xx   | j                  z  cc<   +| jH                  d
k(  ri| j                  |   ||   d
z  z  | j2                  t        j4                  |      z  | j6                  z  k  sH| j8                  t        j4                  ||         z  t        j4                  | j                  |         k  rn| jJ                  d|z  xx   dz  cc<   | jM                  ||      s| j                  |xx   | j                  dz  z  cc<   | jJ                  d|z  xx   dz  cc<   9| jJ                  d|z  xx   dz  cc<   | jO                  ||      sg| jJ                  d|z  xx   dz  cc<   | j                  |xx   | j                  z  cc<   | jH                  dv r| jQ                  ||      rU| j                  |xx   | j                  dd| j&                  jS                  |d      jU                  |      z   z  z  z  cc<   | jW                  ||      s-| j                  |xx   | j                  dd| j&                  jS                  |d      jU                  |      z
  z  z  z  cc<   | jH                  dk(  r| jY                  ||      rU| j                  |xx   | j                  dd| j&                  jS                  |d      jU                  |      z   z  z  z  cc<   | j[                  ||      s| j                  |xx   | j                  dd| j&                  jS                  |d      jU                  |      z
  z  z  z  cc<   at]        dj_                  | jH                               | xj                  dz  c_        t        j`                  | j                  dk\  | j>                  z         sJ ||c| _        | _	        | xjD                  dz  c_"        | j,                  dkD  rd| j                  | j,                  z  sJ| jb                  D ]  }|je                           | j.                  xr | j.                  je                          yyy# t        $ r d| _        Y 	8w xY w)a  f is a scalar, g is a vector.

        Update Lagrange multipliers based on Atamna et al 2017. f and g are
        supposed to have been computed from the distribution mean.

        Details: do nothing if Lagrange coefficients `lam` were not yet set.
        Nr	   rr   zDno update for %d calls (`lam` and `mu` need to be initialized first)r   r  r   g?zBchi_omega=%f as by default, however values <<1.1 may not work wellr(   g?r   g      ?g      @z%d:muup0z%d:muup1z
%d:mudown0z
%d:mudown1)r   r   g      пr=   r   z!algorithm number {0} is not known)3r   r  r   _count_noupdaterX   r4   r5   r8   r  rC   r^   r   r   r@   r0   r   r`   r$   rB   r   r   r]   r   r
  r   r   r   r   r   r>   r   r   r
   is_r   r   r   r   r8  r;  r?  rE   r   rA  rC  rE  NotImplementedErrorr   r_   r  push)	r7   rB   rC   dgdhrf   condk1condk2r   s	            r   rE   zAugmentedLagrangian.update  s    	a 88)$$)$ ##q4+?+?+D'DEI  :<@<P<P Q R66Q;66"&&1"5txx=CL:CF:::::AvdjjT__t-Cc"&// 2 3A'BSa\!DFF*Sdff->>B++00TWW>3txx=)<<!#TZZ!^t||,KPTPiPi!$''!*qtQw"6266":9MPTP^P^9^"^_F!$''BFF2a5M"9BFF466!9<M"MNF--11!c'D2::!$ff%5!6vsV| TDV =V 3V W771:???1%1
):dhhqk\)I		$"B"BCtGgGghiGjmnGnHHQK4771:!#4t{{#BBKq)dhhqkAo"#DHHQKq)adTWWQZ.?488A;,.N >>Q&wwqzAaD!G+dggr
.BT^^.SS"&&A-/"&&2CC
doot&;;

doo5
^^q(wwqzAaD!G+dggr
.BT^^.SS"&&A-/"&&2CCJN3q83<<1- GGAJ$//4*??J KK
Q71<7L1$45:5==A. KKq(89Q>9 GGAJ$//9J^^v-||Aq)
doo ;;BB1aHWWXYZA[ 9\ '] ]
q!,
doo ;;BB1bIXXYZ[B\ 9] '^ ^
^^q(||Aq)
doo ;;BB1aHWWXYZA[ 9\ '] ]
q!,
doo ;;BB1bIXXYZ[B\ 9] '^ ^
 ..Q/5vdnn/EG Gq *t JJ!OJvvtxx1}7888A((A-(<<!DJJ$=,, '%%J$*C*C*H*H*J %>_ " )'($)s   e# #e76e7r   rF   )r  )g?)gffffff?)g?)rG   rH   rI   rJ   r9   r   r   r   r   r   rn   r8   r  r  rm   r  r  r/  r   rg   r8  r;  r?  rA  rC  rE  rE   r   r    r   r   r     s    GP:

	ZE8   + +
 P P  	41HMT  (6.$*^Kr    r   c                 .    | j                  dd      d   S )z"avoid unpicklable lambda constructr	   r   )	sigma_fac)ask)ess    r   _get_favorite_solutionrS    s    66!q6!!$$r    c                       e Zd ZdZeeefZdddedefdZ	d Z
d Zd Zd	 Zdd
Zed        Zd Zd Zd ZddZed        Zd ZddZd Zd Zy)ConstrainedFitnessALa  Construct an unconstrained objective function from constraints.

    This class constructs an unconstrained "fitness" function (to be
    minimized) from an objective function and an inequality constraints
    function (which returns a list of constraint values). An
    equality constraint ``h(x) == 0`` must be expressed as two inequality
    constraints like ``[h(x) - eps, -h(x) - eps]`` with ``eps >= 0``.
    Non-positive values <= 0 are considered feasible.

    The `update` method of the class instance needs to be called after each
    iteration. Depending on the setting of `which`, `update` may call
    ``get_solution(es)`` which shall return the solution to be used for the
    constraints handling update, by default ``_get_favorite_solution ==
    lambda es: es.ask(1, sigma_fac=0)[0]``. The additional evaluation of
    objective and constraints is avoided by the default ``which='best'``,
    using the best solution in the current iteration.

    `find_feasible_first` optimizes to get a feasible solution first, which
    only works if no equality constraints are implemented. For this reason
    the default is `False`.

    Minimal example (verbosity set for doctesting):

    >>> import cma
    >>> def constraints(x):  # define the constraint
    ...     return [x[0] + 1, x[1]]  # shall be <= 0
    >>> cfun = cma.ConstrainedFitnessAL(cma.ff.sphere, constraints,
    ...                                 find_feasible_first=True)
    >>> es = cma.CMAEvolutionStrategy(3 * [1.1], 0.1,
    ...                   {'tolstagnation': 0, 'verbose':-9})  # verbosity for doctest only
    >>> es = es.optimize(cfun, callback=cfun.update)
    >>> x = es.result.xfavorite

    The best `x` return value of `cma.fmin2` may not be useful, because
    the underlying function changes over time. Therefore, we use
    `es.result.xfavorite`, which is still not guarantied to be a feasible
    solution. Alternatively, `cfun.best_feas.x` contains the best evaluated
    feasible solution. However, this is not necessarily expected to be a
    good solution, see below.

    >>> assert sum((x - [-1, 0, 0])**2) < 1e-9, x
    >>> assert es.countevals < 2200, es.countevals
    >>> assert cfun.best_feas.f < 10, str(cfun.best_feas)
    >>> # print(es.countevals, cfun.best_feas.__dict__)

    To find a final feasible solution (close to `es.result.xfavorite`) we
    can use the current `CMAEvolutionStrategy` instance `es`:

    >>> x = cfun.find_feasible(es)  # uses es.optimize to find (another) feasible solution
    >>> assert constraints(x)[0] <= 0, (x, cfun.best_feas.x)
    >>> assert cfun.best_feas.f < 1 + 2e-6, str(cfun.best_feas)
    >>> assert len(cfun.archives) == 3
    >>> assert cma.ConstrainedFitnessAL(cma.ff.sphere, constraints, archives=False).archives == []

    Details: The fitness, to be minimized, is changing over time such that
    the overall minimal value does not indicate the best solution.

    The construction is based on the `AugmentedLagrangian` class. If, as by
    default, ``self.finding_feasible is False``, the fitness equals ``f(x)
    + sum_i (lam_i x g_i + mu_i x g_i / 2)`` where ``g_i = max(g_i(x),
    -lam_i / mu_i)`` and lam_i and mu_i are generally positive and
    dynamically adapted coefficients. Only lam_i can change the position of
    the optimum in the feasible domain (and hence must converge to the
    right value).

    When ``self.finding_feasible is True``, the fitness equals to ``sum_i
    (g_i > 0) x g_i^2`` and omits ``f + sum_i lam_i g_i`` altogether.
    Whenever a feasible solution is found, the `finding_feasible` flag is
    reset to `False`.

    `find_feasible(es)` sets ``finding_feasible = True`` and uses
    `es.optimize` to optimize `self.__call__`. This works well with
    `CMAEvolutionStrategy` but may easily fail with solvers that do not
    consistently pass over the optimum in search space but approach the
    optimum from one side only. This is not advisable if the feasible
    domain has zero volume, e.g. when `g` models an equality like
    ``g = lambda x: [h(x), -h(x)]``.

    An equality constraint, h(x) = 0, cannot be handled like h**2 <= 0,
    because the Augmented Lagrangian requires the derivative at h == 0 to
    be non-zero. Using abs(h) <= 0 leads to divergence of coefficient mu
    and the condition number. The best way is apparently using the two
    inequality constraints [h <= 0, -h <= 0], which seems to work perfectly
    well. The underlying `AugmentedLagrangian` class also accepts equality
    constraints.

NbestFc	                    || _         || _        || _        || _        || _        || _        t        | _        || _        d| _	        | j                          	 |D cg c]  }t        |       c}| _        yc c}w # t        $ r@ |r4t        j                  D cg c]  }t        |       nc c}w c}| _        Y yg | _        Y yw xY w)a  constructor with lazy initialization.

        If ``which in ['mean', 'solution']``, `get_solution` is called
        (with the argument passed to the `update` method) to determine the
        solution used to update the AL coefficients.

        If `find_feasible_first`, only the constraints are optimized until
        the first (fully) feasible solution is found.

        `logging` is the iteration gap for logging constraints related
        data, in `AugmentedLagrangian`. 0 means no logging and negative
        values have unspecified behavior.

        `archives` are the aggregator functions for constraints for
        non-dominated biobjective archives. By default, the second
        objective is ``max(g_+)``, ``sum(g_+)`` or ``sum(g_+^2)``,
        respectively. ``archives=True`` invokes the same behavior.
        ``archives=False`` or an empty `tupel` prevents maintaining
        archives.

        TN)funrO   r   get_solutionwhichfinding_feasibler)   find_feasible_aggregatorr   omit_f_calls_when_possible_resetr+   archivesr?   rU  archive_aggregators)	r7   rX  rO   r   rZ  find_feasible_firstrY  r   r_  s	            r   r9   zConstrainedFitnessAL.__init__S  s    : &"(
 3(:%*.'	#IQR#8=RDMR 	#!5!I!I!K!I GJ!<S!A!I!K !#	#s6   A9 A4+A9 4A9 9CB)(C8CCc                     d | _         g | _        g | _        g | _        d| _        t               | _        t               | _        t               | _	        d| _
        d| _        g | _        y r   )_alrV   r[   F_plus_sum_al_Gfoffsetr   best_augr   	best_feasbest_f_plus_gposr   count_updates_set_coefficient_countsrl   s    r   r^  zConstrainedFitnessAL._reset  s[    !&-/ -')$r    c                 D    | j                          | j                          y)zreset dynamic componentsN)r^  _reset_archivesrl   s    r   resetzConstrainedFitnessAL.reset  s    r    c                     t        | j                        D ]'  \  }}t        |j                        | j                  |<   ) y rF   )r   r_  r+   r.   )r7   rf   as      r   rl  z$ConstrainedFitnessAL._reset_archives  s0    dmm,DAq:1<<HDMM! -r    c                 0    g g g c| _         | _        | _        y rF   )rV   r[   rd  rl   s    r   _reset_arraysz"ConstrainedFitnessAL._reset_arrays  s    /12r,,r    c                 H    || j                   d   }t        d |D              S )z@return True if last evaluated solution (or `gvals`) was feasibler=   c              3   &   K   | ]	  }|d k    ywr   r   r   s     r   r   z4ConstrainedFitnessAL._is_feasible.<locals>.<genexpr>  s     +Ur27Ur   )r[   r_   )r7   r   s     r   _is_feasiblez!ConstrainedFitnessAL._is_feasible  s%    =FF2JE+U+++r    c                     | j                   sM| j                  rAt        | j                        | _         | j                  | j                  | j                   _        | j                   S )z$`AugmentedLagrangian` class instance)rc  r   r   r   rl   s    r   alzConstrainedFitnessAL.al  sD     xxDNN*4>>:DH||'#'<< xxr    c                 <    | j                   j                  ||       y)zset AL coefficientsN)rv  
set_mu_lam)r7   r   r   s      r   rx  zConstrainedFitnessAL.set_mu_lam  s    2s#r    c                     || _         y)z&set search space dimension explicitelyN)r   )r7   r   s     r   
initializezConstrainedFitnessAL.initialize  s	    "r    c                 j   | j                   s| j                  t        |             | xj                  dz  c_        | xj                  | j                  |      gz  c_        | j                  | j                  d         rd| _        nr| j                  rf| xj                  t        j                  gz  c_        | xj                  t        j                  gz  c_        | j                  | j                  d         S | xj                  | j                  |      gz  c_        | j                  | j                  d         }| xj                  | j                  d   t        |      z   gz  c_        | j!                  || j                  d   | j                  d   |       | j                  d   | j"                  z
  S )zreturn AL fitness, append f and g values to `self.F` and `self.G`.

        If `self.finding_feasible`, `fun(x)` is not called and ``f = np.nan``.
        r	   r=   F)r   rz  r@   r   r[   rO   rt  r[  rV   r^   r   rd  r\  rX  rv  r$   _update_bestre  )r7   rT   r   s      r   rg   zConstrainedFitnessAL.__call__  sD   
 ~~OOCF#A4##A&''TVVBZ($)D!""FFrvvhF  RVVH, 00<<488A;-wwtvvbz"c$i!7 88!TVVBZT:##B'$,,66r    c           	         d| _          | |j                  j                         | j                   r|r|| j                  c| _        }| j                   rt	        fd|j                         D              s|j                         }|j                  ||D cg c]
  } | |       c}       | j                  |       |j                  j                          | j                   r| j                          | j                   r#t	        fd|j                         D              s|r| _        | j                  j                  | j                   rKt        j                  dj!                  | j                  j                  dnd|j                                      | j                  j                  )| j                   sJ | j                  | j                   f       | j                  j                  S c c}w )aT  find feasible solution by calling ``es.optimize(self)``.

        Return best ever feasible solution `self.best_feas.x`.
        See also `self.best_feas.info`.

        `aggregator`, defaulting to `self.find_feasible_aggregator`, is the
        constraints aggregation function used as objective function to be
        minimized. `aggregator` takes as input all constraint values and
        returns a value <= 0 if and only if the solution is feasible.

        Terminate when either (another) feasible solution was found or any
        of the `termination` keys is matched in `es.stop()`.
    Tc              3   H   K   | ]  t        fd D                yw)c              3   (   K   | ]	  }|k(    y wrF   r   )r   r8   r   s     r   r   z?ConstrainedFitnessAL.find_feasible.<locals>.<genexpr>.<genexpr>  s     7T1Qs   N)r   )r   r   terminations    @r   r   z5ConstrainedFitnessAL.find_feasible.<locals>.<genexpr>  s%      4H=F 587T7T4T=Fs   "zQConstrainedFitnessAL.find_feasible:  No {0}feasible solution found, stop() == {1}znew  )r[  result	xfavoriter\  r   stoprQ  tellrE   r   r>   rq  rg  rT   r4   r5   r   )r7   rR  r  r.   aggregator_rU   rT   s     `    r   find_feasiblez"ConstrainedFitnessAL.find_feasible  s     !%RYY  !  =GIfIf:-{'' 4H=?WWY4H 1HFFHQ/QDGQ/0B		((&&( '' 4H=?WWY4H 1H 0;->>#t'<'<NN KKQ6)-)9)9)Ev2rwwyLZ[ ~~+t/D/Dmt~~W[WlWlFmmD~~ 0s   G,
c                 |    t        j                  | j                        }| j                  |   | j                  |   fS )zNreturn current best f, g, where best is determined by the Augmented Lagrangian)r^   	nanargminrd  rV   r[   )r7   rf   s     r   _best_fgzConstrainedFitnessAL._best_fg  s3     LL--.vvay$&&)##r    c                     | j                   dvr| j                  S  | | j                  |             | j                  d   | j                  d   fS )z@f, g values used to update the Augmented Lagrangian coefficients)rk   solutionr=   )rZ  r  rY  rV   r[   )r7   rR  s     r   
_fg_valueszConstrainedFitnessAL._fg_values  sG    ::11== Tr"#vvbz466":%%r    c           
         || j                  |      }t        | j                  ||||      }| j                  j	                  |d   ||       | j
                  j	                  |t        |D cg c]
  }|dkD  s	| c}      z   ||       | j                  |      r | j                  j	                  |||||       t        j                  |      r%| j                  D ]  }|j	                  |||        yyc c}w )z6keep track of best solution and best feasible solutionNr   r   r;   )rv  r   r   rf  rE   rh  r$   rt  rg  r^   isfiniter_  )r7   rT   rB   rC   r   r   r   ro  s           r   r|  z!ConstrainedFitnessAL._update_best  s    <771:D!$"2"2Aq!TBQvY1-$$Q1-G1RQb1-G)H%H!QOQNN!!!Qaa!8;;q>]]Aq! #  .Hs   ,
C67C6c           	         t        | j                        t        | j                        cxk(  rt        | j                        k(  san t	        j
                  dj                  t        | j                        t        | j                        t        | j                                     t        | j                        dk(  r1| j                  |t        j                  t        j                  g       y| j                  r.| j                  || j                  d   | j                  d          y| xj                  dz  c_        | j                  s)| j                  t        | j                  |                   | j                  j                   st        j"                  | j                        j%                         r| j                  j&                  }| j                  j)                  | j                  | j                         | j                  j&                  |kD  r | xj*                  | j                  gz  c_        | j-                  |      \  }}| j/                          t        j"                  |      r| j                  j1                  ||       | j                  |||       ddk  r.| j2                  r t        j"                  | j2                  j4                        r| j2                  j4                  }| j6                  rg }| j6                  D ]s  }t9        t        |j:                        dz
  dd      D ]K  }|j:                  |   d   dk  r|j:                  |   d   }	|	| j2                  j4                  k  sE||	gz  } s u |rt=        |      n| j>                  }|| j>                  k7  r tA        | j                  | j>                         || _        yyyy)a  update AL coefficients, may be used as callback to `OOOptimizer.optimize`.

        TODO: decide what happens when `__call__` was never called:
              ignore (as for now) or update based on xfavorite by calling self(xfavorite),
              assuming that update was called on purpose?
              When method is not best, it should work without even call self(xfavorite).
        zKlen(F, G, F_plus_sum_al_G) = ({0}, {1}, {2}) differ.This is probably a bug!r   Nr=   r	   r  r   )!r@   rV   r[   rd  r4   r5   r   	log_in_esr^   r   r[  ri  r   rz  r  rv  r  r  r_   r  r/  rj  r  rq  rE   rg  rB   r_  r]   r/   r   re  print)
r7   rR  r   rB   rC   
new_offsetfvalsro  rf   fvals
             r   rE   zConstrainedFitnessAL.update  s    466{c$&&kFS1E1E-FFNN 55;Vtvv;DFFS9M9M5N6PQ tvv;!NN2rvvx0"" NN2tvvbz466":6a~~OOCb 123ww%%"++dff*=*A*A*C))AGG$$TVVTVV4ww((1,,,1C1C0DD,r"1;;q>GGNN1a r1a 6dnnT^^5E5E)F ))J}}A"3qyy>A#5r2>99Q<?a/$ yy|A$.."2"22!dVOE! ? ' ,1SZdll
T\\)d(($,,7%DL+ *Gn6r    c                     t        |      }t        d |D              }	 |xj                  |r|nt        j                  |dk  rd|dz  z  n|gz  c_        y# t
        $ r Y yw xY w)a
  a hack to have something in the cma-logger divers plot.

        Append the sum of positive g-values and the number of infeasible
        constraints, displayed like 10**(number/10) (mapping [0, 10] to [1,
        10]) if number < 10, to `es.more_to_write`.
        c              3   &   K   | ]	  }|d kD    ywr   r   r   s     r   r   z1ConstrainedFitnessAL.log_in_es.<locals>.<genexpr>I  s     *"rAvr   r-   N)r%   r$   more_to_writer^   r   	Exception)r7   rR  rB   rC   g_posn_infeass         r   r  zConstrainedFitnessAL.log_in_esA  sj     1***	%RVV8@2hm!48!# #  		s   6A 	A"!A"rF   ))maxiter	maxfevalsN)rG   rH   rI   rJ   r   r%   r)   r`  rS  r9   r^  rm  rl  rq  rt  rn   rv  rx  rz  rg   r  r  r  r|  rE   r  r   r    r   rU  rU    s    Vn &z3EF%*4-.#^*I:,  $#7,% N $ $
&"9&vr    rU  )4rJ   
__future__r   r   r   warningsr4   collectionsr   	functoolsr   numpyr^   r   r  r   r  r   r  	utilitiesr
   utilities.mathr   r!  r   r   r   r	  optimization_toolsr   r   r   r   r%   r)   objectr+   rL   dequerp   listr~   r   r   r   r   r   r   r   r   rS  rU  r   r    r   <module>r     s    @ @  "   M M  5 % CX~ 	  )J K4-0#:& #:HF8& F8R;|!! ;>A A@999X6 9XvaK& aKF%V6 Vr    