
    J-j                         d Z ddlmZmZmZ ddlZddlZddl	m
Z ddlmZ ddlmZ [[[ddZd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 G d de      Zy)zLA collection of variable boundaries (AKA box constraints) handling classes.
    )absolute_importdivisionprint_functionN   )utils)rglen)#BoxConstraintsLinQuadTransformationc                     dD ]  	 t                  dk(  r|rt                d}d <   t        j                            r!t         fdt                  D              r|rt                d}d <       |t         fdt                  D              st        d        S # t        $ r |rt                d}    g <   Y w xY w)zreturn ``[lower_bounds, upper_bounds]`` such that each of them

    is either a nonempty `list` or `None`.

    `copy` only makes a shallow copy.

    On input, `bounds` must be a `list` of length 2.
    r   r   r   FNc              3   n   K   | ],  }   |   d u xs t        j                     |           . y wN)npisfinite.0jboundsis     b/Users/jameslopez/projects/TradingBot25/.venv/lib/python3.12/site-packages/cma/boundary_handler.py	<genexpr>z#normalize_bounds.<locals>.<genexpr>!   sB      ,/- q	!$EBKKq	!,E(EE-s   25c              3   \   K   | ]#  }   |   d z  t         j                  z  k(   % yw)N)r   infr   s     r   r   z#normalize_bounds.<locals>.<genexpr>(   s4      )G5E *01"q2669I)I5Es   ),zOlower/upper is +inf/-inf and therefore no finite feasible solution is available)	lenlist	TypeError_utilsis_allr   any
ValueError)r   copyr   s   ` @r   normalize_boundsr#      s     
	$6!9~"!&\F D q	 zz&)$ ,/"6!9-,/ )/ fF1I!9 S )G5:6!95E)G &G U V V+ . M!  	$fF1I		$s   %B11!CCc                    ||g}dt         j                   gdt         j                  gfD ]_  \  }}| |   |rt        |       } d}|g| |<   !t        | |         D ].  }| |   |   ||   rt        | |         | |<   d||<   || |   |<   0 a | S )zXreplace any None by inf or -inf.

    This code was never tested and is not in use.
    r   r   F)r   r   r   r   )r   r"   copy_iibvalr   s         r   none_to_infr(   .   s    
 D\FL1bff+.C":fF2Jvbz"Abz!}$":!%fRj!1F2J!&F2J #r
1 # / M    c                   "    e Zd ZdZd Zd Zd Zy)BoundDomainTransformar  create a `callable` with unbounded domain from a function with bounded domain,

    for example an objective or constraints function. The new "unbounded"
    `callable` maps ``x`` to ``function(self.transform(x))``, first
    "projecting" the input (e.g., candidate solutions) into the bounded
    domain with `transform` before to evaluate the result on the original
    function. The "projection" is smooth and differentiable, namely
    coordinate-wise piecewise linear or quadratic. The "projection" is not
    idempotent.

    Bounds are passed as ``boundaries = [lower_bounds, upper_bounds]``
    where each ``*_bounds`` can be `None`, or a scalar, or an iterable (a
    vector) whose values can be `None` too. If the iterable has fewer
    values than the solutions, the last value is recycled, if it has more
    values, trailing values are ignored.

    For example, ``boundaries = [None, [0, 0, None]]`` means no lower
    bounds and an upper bound of zero for the first two variables.

    Example:

    >>> import cma
    >>> fun = cma.boundary_handler.BoundDomainTransform(
    ...             cma.ff.sphere,  # is composed with fun.transform into fun
    ...             [[0.02, 0.01], None])  # boundaries for the "original" problem
    >>> x, es = cma.fmin2(fun, 3 * [0.5], 0.5, {'verbose':-9})
    >>> assert all(x - 1e-4 < [-0.03, -0.04, -0.04])  # x is in the unbounded domain
    >>> print("solution in the original (bounded) domain = {}"
    ...       .format(fun.transform(es.result.xfavorite)))
    solution in the original (bounded) domain = [0.02 0.01 0.01]

    The original function can be accessed and called via the attribute
    ``function`` like ``fun.function(...)``. For code simplicity,
    attributes of ``function`` are "inherited" to ``fun``.

    Details: the resulting function has a repetitive landscape with a
    period slightly larger than twice the boundary interval. The
    ``BoundDomainTransform(function,...)`` instance emulates the original function
    on attribute access by calling ``__getattr__``. To access shadowed
    attributes or for debugging, replace ``.attrname`` with
    ``.function.attrname``.
    c                 h    || _         t        |      | _        | j                  j                  | _        yzDreturn a callable that evaluates `function` only within `boundaries`N)functionBoundTransformboundary_handler	transformselfr.   
boundariess      r   __init__zBoundDomainTransform.__init__n   s)      .z :..88r)   c                 L     | j                   | j                  |      g|i |S r   r.   r1   r3   xargskwargss       r   __call__zBoundDomainTransform.__call__s   &    t}}T^^A.@@@@r)   c                 .    t        | j                  |      S zreturn ``getattr(self.function, name)`` when ``not hasattr(self, name)``.

        This emulates the `function` interface, kinda like blind inheritance.
        getattrr.   r3   names     r   __getattr__z BoundDomainTransform.__getattr__u       
 t}}d++r)   N)__name__
__module____qualname____doc__r5   r<   rD    r)   r   r+   r+   C   s    )T9
A,r)   r+   c                   (    e Zd ZdZd Zd Zd Zd Zy)_BoundDomainPenaltyzN[WIP early] function wrapper for penalty boundary handler, looks kinda complexc                 h    || _         t        |      | _        | j                  j                  | _        yr-   )r.   BoundPenaltyr0   repairr1   r2   s      r   r5   z_BoundDomainPenalty.__init__~   s)      ,Z 8..55r)   c                 L     | j                   | j                  |      g|i |S r   r7   r8   s       r   r<   z_BoundDomainPenalty.__call__   r=   r)   c                     t         )z&needs the mean and the fitness values?NotImplementedError)r3   s    r   callbackz_BoundDomainPenalty.callback   s    !!r)   c                 .    t        | j                  |      S r?   r@   rB   s     r   rD   z_BoundDomainPenalty.__getattr__   rE   r)   N)rF   rG   rH   rI   r5   r<   rT   rD   rJ   r)   r   rL   rL   |   s    X6
A",r)   rL   c                   v    e Zd ZdZdZ	 d ZddZd Zd ZddZ	ddZ
d	 Zd
 ZddZd ZddZd Zd ZddZy)BoundaryHandlerBasezquick hack versatile base class.

    To guaranty that modifications of the attribute `bounds` after this
    instance was already used are effective, the class attribute
    ``_bounds_dict`` must be reset like ``_bounds_dict = {}``.
    Fc                 &   t         j                  | _        |ddg fv rd| _        i | _        yt        |t        t
        f      rt        |      dk7  r t        dt        t        |            z        t        t        |      d      | _        i | _        y)a  `bounds` can be ``None`` or ``[lb, ub]``

        where ``lb`` and ``ub`` are either ``None`` or a vector (which can have
        ``None`` entries).

        On return, the ``bounds`` attribute of ``self`` are the bounds in a
        normalized form.

        To compute bounds for any dimension, the last entry of bounds is
        then recycled for variables with ``indices >= len(bounds[i]) for i
        in (0,1)``.

        NrJ      zbounds must be None, empty, or a list of length 2 where each element may be a scalar, list, array, or None; type(bounds) was: %sFr"   )rW   use_cached_valuesr   
isinstancetupler   r   r!   strtyper#   _bounds_dict)r3   r   s     r   r5   zBoundaryHandlerBase.__init__   s     "5!F!FdB^#DK 	4 fudm4Fq8H 57:4<7HIJ J +4<eDDK	4r)   c                      |r j                         sy fd}t        |      dz   }dD ]K  } j                  |rdnd      s j                  ||      } ||t        j                  |d      |k(  |       M y)z{set bounds away from ``at=0.5`` such that

        a repaired solution is always rounded into the feasible domain.
        Nc                 :   | dv sJ |        t        j                  |      syt        j                  |      d   D ]  }||vsd||<    t        j                  |      syt        t	        j
                  |          t        j                  t        j                  |      d         dz   f      }j                  | |      }t	        |      t	        |      k  r|dt	        |       }n\t	        |      t	        |      kD  rEt        j                  |t        j                  t	        |      t	        |      z
  t              g      }||xx   dd| z  z
  z  t        j                  dt        j                  ||               z  z  cc<   |j
                  | <   i _        y)z3idx is a `bool` index array of ``bound % 1 == 0.5``r   Nr   Fr   )dtyperY   )r   r    nonzeromaxr   r   
get_boundshstackzerosboolmaximumabsr`   )whichidxinteger_indicesr   	dimensionr   offsetr3   s         r   
set_boundszJBoundaryHandlerBase.amend_bounds_for_integer_variables.<locals>.set_bounds   sQ   F?)E)?66#;ZZ_Q'O+"CF ( 66#;SU!34VVBJJsOA$67!;= >I__UI6F6{SX%,3v;'Vs3x'iibhhs6{SX/ET&R ST3KAE	MV3bjjBFF6RU;DW6XXXK!'DKK "Dr)   r   r   upperlower)
has_boundsre   rf   r   mod)r3   rn   atrp   rq   ro   rl   r   s   `  `    r   "amend_bounds_for_integer_variablesz6BoundaryHandlerBase.amend_bounds_for_integer_variables   ss    
 doo&7	#* (1,	E??e7A__UI6FubffVQ/25G	 r)   c                 T    t        j                  |d         rdS t        |      dgz  S )zreturn penalty or list of penalties, by default zero(s).

        This interface seems too specifically tailored to the derived
        BoundPenalty class, it should maybe change.

        r           )r   isscalarr   )r3   	solutionsr:   r;   s       r   r<   zBoundaryHandlerBase.__call__   s)     kk)A,/sKS^se5KKr)   c                     | S )z;end-iteration callback of boundary handler (abstract/empty)rJ   )r3   r:   r;   s      r   updatezBoundaryHandlerBase.update   s    r)   c           	         |}| j                   |S dD ]  }| j                   |   t        |      D ]  }t        |t        | j                   |         dz
  g      }| j                   |   |   <d|z  ||   z  d|z  | j                   |   |   z  k  sa|rt	        j
                  |d      }d}| j                   |   |   ||<     |S )z^projects infeasible values on the domain bound, might be
        overwritten by derived class r   r   r   TrZ   F)r   r   minr   r   array)r3   r9   copy_if_changedr"   r&   r   rm   s          r   rO   zBoundaryHandlerBase.repair   s     ;;HB{{2&1X1c$++b/2Q678;;r?3'3b1Q42(T[[_S5I*IIHHQT2$;;r?3/AaD   r)   c                     |S )zhinverse of repair if it exists, at least it should hold
         ``repair == repair o inverse o repair``rJ   )r3   yr   s      r   inversezBoundaryHandlerBase.inverse   s	     r)   c                 p    |dv r| j                  d|      S |dv r| j                  d|      S t        d      )z:``get_bounds('lower', 8)`` returns the lower bounds in 8-D)rs   r   0r   )rr   r   1r   z)argument which must be 'lower' or 'upper')_get_boundsr!   )r3   rl   ro   s      r   rf   zBoundaryHandlerBase.get_bounds   sF    %%##Ay11''##Ay11HIIr)   c                    | j                   si | _        ||f| j                  v r| j                  ||f   S d|z  dz
  }|dz  dk(  sJ | j                  | j                  |   I|t        j                  z  t        j
                  |      z   | j                  ||f<   | j                  ||f   S g }t        |      D ]c  }|j                  | j                  |   t        |t        | j                  |         dz
  g                |d   N|t        j                  z  |d<   e t        j                  |      | j                  ||f<   | j                  ||f   S )zQib == 0/1 means lower/upper bound, return a vector of length
        `dimension` rY   r   r   )r[   r`   r   r   r   rh   rangeappendr   r   asarray)r3   r&   ro   sign_resr   s         r   r   zBoundaryHandlerBase._get_bounds  sE    %% "D	?d///$$b)_55B
ax1}};;$++b/"916"((9BU1UDr9o.$$b)_55y!AJJt{{2sAs4;;r?/Ca/G+H'IJK2w"&&.B " .0ZZ_2y/*  "i11r)   c                 0   d}||vrt        dj                  ||            | j                  }||dg dfv s
|d   |d   yt        |      D ]G  \  }}||dk(  r|dk(  s
|dk(  r|dk(  rd	|z  dz
  }|D ]  }|||z  t        j
                  k  s  y
 I y)z(return `True` if any variable is bounded)Nbothrs   rr   z-`which` parameter must be in {0} but was ={1}FrJ   r   r   rr   rs   rY   T)r!   formatr   	enumerater   r   )r3   rl   valid_whichsr   r&   boundr   bound_is           r   rt   zBoundaryHandlerBase.has_bounds  s    7$L!'e!<> >>Vr26q	!fQi&7"6*IB}aEW,aEW,FQJE &57?RVV+C ! + r)   c           	         | j                   ydD ]  }| j                   |   t        |      D ]  }|t        | j                   |         dz
  k(  r@| j                   |   |   ,dd|z
  z  | j                   |   |   z  t        j                  k(  r t        |t        | j                   |         dz
  g      }| j                   |   |   |dk(  r||   | j                   |   |   k  s|dk(  s||   | j                   |   |   kD  s  y  y)aI  return `True` if `x` is in bounds.

        >>> import numpy as np
        >>> import cma

        >>> b = cma.boundary_handler.BoundaryHandlerBase(bounds=[[-0.5], 0.2])
        >>> for n in [2, 4, 9]:
        ...     x = np.random.randn(n)
        ...     assert (all(-0.5 <= x) and all(0.2 >= x)) is b.is_in_bounds(x)

        Tr   r   r   r   F)r   r   r   r   r   r   )r3   r9   r&   r   rm   s        r   is_in_boundsz BoundaryHandlerBase.is_in_bounds.  s    ;;B{{2&1XDKKO,q00B*2q2vR);;rvvE1c$++b/2Q678;;r?3'/1W1B(<!<1W1B(<!<    r)   c           	      |   | j                   |S dD ]'  }| j                   |   t        |      D ]  }|t        | j                   |         dz
  k(  r@| j                   |   |   ,dd|z
  z  | j                   |   |   z  t        j                  k(  r t        |t        | j                   |         dz
  g      }| j                   |   |   |dk(  r||   | j                   |   |   k\  s|dk(  r||   | j                   |   |   k  r|rt        j                  |d      }d}| j                   |   |   ||<    * |S )ac  set out-of-bound values on bounds and return `x`.

        Make a copy when `x` is changed and ``copy is True``,
        otherwise change in place.

        >>> import numpy as np
        >>> import cma

        >>> b = cma.boundary_handler.BoundaryHandlerBase(bounds=[[0.1], 0.2])
        >>> assert all(0.1 <= b.into_bounds(np.random.randn(22)))
        >>> assert all(0.2 >= b.into_bounds(np.random.randn(11)))
        >>> b = cma.boundary_handler.BoundaryHandlerBase(bounds=[[-0.1], np.inf])
        >>> assert all(-0.1 <= b.into_bounds(np.random.randn(22)))
        >>> b = cma.boundary_handler.BoundaryHandlerBase(bounds=[[-0.1], [None]])
        >>> assert all(-0.1 <= b.into_bounds(np.random.randn(22)))
        >>> b = cma.boundary_handler.BoundaryHandlerBase(bounds=[-np.inf, 0.1])
        >>> assert all(0.1 >= b.into_bounds(np.random.randn(22)))

        r   r   r   r   TrZ   F)r   r   r   r   r   r   r   )r3   r9   r"   r&   r   rm   s         r   into_boundszBoundaryHandlerBase.into_boundsL  s?   ( ;;HB{{2&1XDKKO,q00++b/!,4R.4;;r?1+==G1c$++b/2Q678;;r?3'/1W1R)=!=1W1R)=!=.A D{{2s+!  $ r)   c           	      |   | j                   g S g }dD ]  }| j                   |   t        |      D ]}  }t        |t        | j                   |         dz
  g      }| j                   |   |   <|dk(  r||   | j                   |   |   k  s|dk(  s_||   | j                   |   |   kD  sx||gz  }  t	        |      S )zreturn index list of out-of-bound values in `x`.

        ``if bounds.idx_out_of_bounds`` evaluates to `True` if and only if
        `x` is out of bounds.
        r   r   r   )r   r   r   r   sorted)r3   r9   idxsr&   r   rm   s         r   idx_out_of_boundsz%BoundaryHandlerBase.idx_out_of_boundsv  s     ;;IB{{2&1X1c$++b/2Q678;;r?3'/1W1B(<!<1W1B(<!<A3;4   d|r)   c           	         | j                   !t        j                   t        j                  gS g }dD ]  }| j                   |   t        | j                   |         dk(  rd}n6| j                   |   t	        |t        | j                   |         dz
  f         }|j                  |$t        j                   t        j                  g|   n|        |S )z;return lower and upper bound of variable with index `index`Nr   r   r   )r   r   r   r   r   r   )r3   indexr   r&   bs        r   	get_boundzBoundaryHandlerBase.get_bound  s    ;;VVGRVV$$B{{2&#dkk"o*>!*CKKOCDKKO0Dq0H(I$JKJJ	(,qA  
r)   Nc           
      h   |	 | j                   }|sddggS t        t        |      d      }dD ]  }||   	dg||<    dD cg c]  }t	        ||          }}|d   |d   k7  r;d|vr7d|d   d   |d   d   fvr%t        j                  dj                  ||             g }	 t        t        |            D ]C  }|j                  |d   t        ||d   dz
  f         |d   t        ||d   dz
  f         g       E 	 |S # t        $ r Y w xY wc c}w # t        t        f$ r t        d	        w xY w)
zreturn boundaries in format ``[[lb0, ub0], [lb1, ub1], ...]``,
        as used by ``BoxConstraints...`` class.

        Use by default ``bounds = self.bounds``.
        NFrZ   r   r   r   r   zlower and upper bounds do not have the same length or length
 one or `None` as last element (the last element is always recycled).
Lengths are {0} = [len(b) for b in bounds={1}])zLboundaries must be provided in the form [scalar_of_vector, scalar_or_vector])r   AttributeErrorr#   r   r   	_warningswarnr   r   re   r   r   r   
IndexErrorprint)r3   r   r   lr   s        r   to_dim_times_twoz$BoundaryHandlerBase.to_dim_times_two  s{    > 4L>!!$v,U;Aay !Fq	  &,,VS^V,Q41Q4<AQJ4q	"vay}8. ,.NNB CI&FBS	U
 	3q6]&)CAaD1H$67"1Ic1adQh-&89; < # 3 "  - :& 	 ; <	s$   D D$AD 	DDD1)      ?g&.>T)r   r   )rF   rG   rH   rI   r[   r5   rw   r<   r}   rO   r   rf   r   rt   r   r   r   r   r   rJ   r)   r   rW   rW      s]     =48!HFL&
J2(*<(T*"r)   rW   c                   *     e Zd ZdZd fd	Zd Z xZS )	BoundNonezno boundariesc                 D    |
t               t        t        |   d        y r   )r!   superr   r5   r3   r   	__class__s     r   r5   zBoundNone.__init__  s     ,i'-r)   c                      y)NTrJ   r3   r9   s     r   r   zBoundNone.is_in_bounds  s    r)   r   )rF   rG   rH   rI   r5   r   __classcell__r   s   @r   r   r     s    .
r)   r   c                   :     e Zd ZdZd fd	ZddZd ZddZ xZS )r/   a  Handle boundaries by a smooth, piecewise linear and quadratic
    transformation into the feasible domain.

    >>> import numpy as np
    >>> import cma
    >>> from cma.boundary_handler import BoundTransform
    >>> from cma import fitness_transformations as ft
    >>> veq = cma.utilities.math.Mh.vequals_approximately
    >>> b = BoundTransform([0, None])
    >>> assert b.bounds == [[0], None]
    >>> assert veq(b.repair([-0.1, 0, 1, 1.2]), np.array([0.0125, 0.0125, 1, 1.2])), b.repair([-0.1, 0, 1, 1.2])
    >>> assert b.is_in_bounds([0, 0.5, 1])
    >>> assert veq(b.transform([-1, 0, 1, 2]), [0.9, 0.0125,  1,  2  ]), b.transform([-1, 0, 1, 2])
    >>> bounded_sphere = ft.ComposedFunction([
    ...         cma.ff.sphere,
    ...         BoundTransform([[], 5 * [-1] + [np.inf]]).transform
    ...     ])
    >>> o1 = cma.fmin(bounded_sphere, 6 * [-2], 0.5)  # doctest: +ELLIPSIS
    (4_w,9)-aCMA-ES (mu_w=2.8,w_1=49%) in dimension 6 (seed=...
    >>> o2 = cma.fmin(cma.ff.sphere, 6 * [-2], 0.5, options={
    ...    'BoundaryHandler': cma.boundary_handler.BoundTransform,
    ...    'bounds': [[], 5 * [-1] + [np.inf]] })  # doctest: +ELLIPSIS
    (4_w,9)-aCMA-ES (mu_w=2.8,w_1=49%) in dimension 6 (seed=...
    >>> assert o1[1] < 5 + 1e-8 and o2[1] < 5 + 1e-8
    >>> b = BoundTransform([-np.random.rand(120), np.random.rand(120)])
    >>> for i in range(0, 100, 9):
    ...     x = (-i-1) * np.random.rand(120) + i * np.random.randn(120)
    ...     x_to_b = b.repair(x)
    ...     x2 = b.inverse(x_to_b)
    ...     x2_to_b = b.repair(x2)
    ...     x3 = b.inverse(x2_to_b)
    ...     x3_to_b = b.repair(x3)
    ...     assert veq(x_to_b, x2_to_b)
    ...     assert veq(x2, x3)
    ...     assert veq(x2_to_b, x3_to_b)
    >>> for _ in range(5):
    ...     lb = np.random.randn(4)
    ...     ub = lb + 1e-7 + np.random.rand(4)
    ...     b = BoundTransform([lb, ub])
    ...     for x in [np.random.randn(4) / np.sqrt(np.random.rand(4)) for _ in range(22)]:
    ...         assert all(lb <= b.transform(x)), (lb, ub, b.__dict__)
    ...         assert all(b.transform(x) <= ub), (lb, ub, b.__dict__)

    Details: this class uses ``class BoxConstraintsLinQuadTransformation``

    c                 j    t         t        |   |       t        | j	                  |            | _        y)zArgument bounds can be `None` or ``bounds[0]`` and ``bounds[1]``
        are lower and upper domain boundaries, each is either `None` or
        a scalar or a list or array of appropriate size.

        N)r   r/   r5   r	   r   	bounds_tfr   s     r   r5   zBoundTransform.__init__  s,     	nd,V4<T=R=RSY=Z[r)   c                     |}| j                   | j                   d   | j                   d   |S t        j                  | j                  ||            S )z2transforms ``x`` into the bounded domain.
        r   r   )r   r   r   r   )r3   r9   r   r"   s       r   rO   zBoundTransform.repair  sM     ;;4;;q>#9#';;q>#9Hzz$..D122r)   c                 $    | j                  |      S r   )rO   r   s     r   r1   zBoundTransform.transform  s    {{1~r)   c                     | j                   | j                   d   | j                   d   |S t        j                  | j                  j	                  ||            S )z=inverse transform of ``x`` from the bounded domain.

        r   r   )r   r   r   r   r   )r3   r9   r   s      r   r   zBoundTransform.inverse  sN     ;;4;;q>#9#';;q>#9Hzz$..00ODEEr)   r   r   )	rF   rG   rH   rI   r5   rO   r1   r   r   r   s   @r   r/   r/     s    -\\3Fr)   r/   c                   >     e Zd ZdZd fd	ZddZd Zd Zd Z xZ	S )	rN   a  Compute a bound penalty and update coordinate-wise penalty weights.

    An instance must be updated each iteration using the `update` method.

    Details:

    - The penalty computes like ``sum(w[i] * (x[i]-xfeas[i])**2)``,
      where ``xfeas`` is the closest feasible (in-bounds) solution from
      ``x``. The weight ``w[i]`` should be updated during each iteration
      using the update method.

    Example how this boundary handler is used with `cma.fmin` via the
    options (`CMAOptions`) of the class `cma.CMAEvolutionStrategy`:

    >>> import cma
    >>> res = cma.fmin(cma.ff.elli, 6 * [0.9], 0.1,
    ...     {'BoundaryHandler': cma.BoundPenalty,
    ...      'bounds': [-1, 1],
    ...      'tolflatfitness': 10,
    ...      'fixed_variables': {0: 0.012, 2:0.234}
    ...     })  # doctest: +ELLIPSIS
    (4_w,8)-aCMA-ES (mu_w=2.6,w_1=52%) in dimension 4 (seed=...
    >>> if res[1] >= 13.76: print(res)  # should never happen

    Reference: Hansen et al 2009, A Method for Handling Uncertainty...
    IEEE TEC, with addendum, see
    https://ieeexplore.ieee.org/abstract/document/4634579
    https://hal.inria.fr/inria-00276216/file/TEC2008.pdf

    **todo**: implement a more generic interface, where this becomes a
    fitness wrapper which adds the desired penalty and the `update`
    method is used as callback argument for `fmin` like::

        f = cma.BoundPenalty(cma.ff.elli, bounds=[-1, 1])
        res = cma.fmin(f, 6 * [1], callback=f.update)

    where callback functions should receive the same arguments as
    `tell`, namely an `CMAEvolutionStrategy` instance, an array of the
    current solutions and their respective f-values. Such change is
    relatively involved. Consider also that bounds are related with the
    geno- to phenotype transformation.
    c                 V    t         t        |   |       d| _        d| _        g | _        y)zArgument bounds can be `None` or ``bounds[0]`` and ``bounds[1]``
        are lower  and upper domain boundaries, each is either `None` or
        a scalar or a `list` or `np.array` of appropriate size.
        r   FN)r   rN   r5   gammaweights_initializedhistr   s     r   r5   zBoundPenalty.__init__?  s*     	lD*62
#( 	r)   c                    |}| j                         rJ| j                  }|rt        j                  |d      }|d   t        j                  |d         r't        |      D ]  }t        |d   ||   f      ||<    nNt        |      D ]@  }t        |t        |d         dz
  g      }|d   |   (t        |d   |   ||   f      ||<   B |d   t        j                  |d         r(t        |      D ]  }t        |d   ||   f      ||<    |S t        |      D ]@  }t        |t        |d         dz
  f      }|d   |   (t        |d   |   ||   f      ||<   B |S )zssets out-of-bounds components of ``x`` on the bounds.

        TODO: unify with BoundaryHandlerBase.repair
        TrZ   r   r   )	rt   r   r   r   rz   r   re   r   r   )r3   r9   r   r"   r   r   r   s          r   rO   zBoundPenalty.repairM  sw    ??[[FHHQT*ay$;;vay)"1X"F1Iqt#45! & #1XCq	NQ$6 78!!9Q<3#&q	!ad';#<AaD & ay$;;vay)"1X"F1Iqt#45! & 	 #1XCq	NQ$6 78!!9Q<3#&q	!ad';#<AaD & r)   c                    | j                         s)t        j                  |d         rdS dgt        |      z  S t        j                  |d         }|r|g}	 t	        | j
                        }t        |j                        D ]  }|j                  |d        t        j                  |      }g }|D ]l  }|j                  r|n|j                  ||   d         }	| j                  |	      }
d}|j                  t        ||
|	z
  |z  dz  z        t        |      z         n |r|d   S |S # t        $ r | j
                  }Y w xY w)zreturns the boundary violation penalty for `x`,
        where `x` is a single solution or a list or np.array of solutions.

        r   ry   genor   rY   )rt   r   rz   r   r   r   r   fixed_valuesinsertr   r   
isidentityphenorO   r   sum)r3   r9   archivegpx_is_single_vectorr   r   penxixpheno	xinboundsfacs               r   r<   zBoundPenalty.__call__o  s1     ++ad+3?#Q?[[1.A	$EBOO,Q$ -JJu%E B ==Rbhhwr{67J.KFF+ICJJs5Y%73$>#BBCc"gMN  ,s1v44  	JJE	s   AD* *EEc                     t         )zcounts for each coordinate the number of feasible values in
        ``solutions`` and returns an `np.array` of length
        ``len(solutions[0])`` with the ratios.
        rR   )r3   r{   s     r   feasible_ratiozBoundPenalty.feasible_ratio  s
    
 "!r)   c           	      
   | j                   | j                   d   | j                   d   | S |j                  }ddk  r|j                  dz  t        j                  t        j
                  |j                        r||j                  gz  nVt        j
                  |j                  d         r|j                  n(t        |      D cg c]  }|j                  |   |    c}      z  }n&|j                  dz  |j                  j                  z  }|j                  |j                  j                  | j                  |j                  j                  |j                                    z
  |dz  z  }t        |      }dt!        |      z   }|d|z  dz     ||dz     z
  }	|	t        j                  |      z  }	t        j"                  |	      r"|	dkD  r| j$                  j'                  d|	       n\|	t        j(                  k(  rHt!        | j$                        dkD  r0| j$                  j'                  dt+        | j$                               n	 t!        | j$                        dd|z  |j,                  z  z   kD  r| j$                  j/                          t        j0                  | j$                        }
t3        d|j4                  j6                  j8                  d	z  |z        }t!        | j$                        dk(  rt;        d
      |j=                         rC| j>                  r|j@                  dk(  r(t        j                  |d|
z  gz        | _!        d| _        | j>                  rt        j                  tE        |      dt+        d|dz  |j4                  j6                  j8                  z        z  z
        }ddk  r| xjB                  t        jF                  |dkD  t        jH                  |dz        z  dz        |z  z  c_!        | jB                  | jB                  d|
z  kD  xx   t        jF                  d      |z  z  cc<   nddk  r_|dkD  j=                         rL| jB                  |dkD  xx   dt3        d|j4                  j6                  j8                  d	z  |z        z  z  cc<   n|j.                  }| jK                  |      }| xjB                  t        jF                  t        j*                  |dgz  d|z
  gd            t3        d|j4                  j6                  j8                  dz  |z        z  z  c_!        |xjL                  | j>                  rtO        | jB                        n|dgz  z  c_&        | S c c}w )a  updates the weights for computing a boundary penalty.

        Arguments
        =========
        ``function_values``:
            all function values of recent population of solutions
        ``es``:
            `CMAEvolutionStrategy` object instance, in particular
            mean and variances and the methods from the attribute
            `gp` of type `GenoPheno` are used.

        r   r         rY   r         g      $@a-  wrongful initialization, no feasible solution sampled. Reasons can be mistakenly set bounds (lower bound not smaller than upper bound) or a too large initial sigma0 or... See description of argument func in help(cma.fmin) or an example handling infeasible solutions in help(cma.CMAEvolutionStrategy). Tg       @   gUUUUUUտg?g333333?)axis
   g      ?)(r   Nsigmar   r   rz   Cr   sm	variancesmeanr   r   rO   r   r   r   r   r   r   r   re   popsizepopmedianr   spweightsmueffr!   r    r   	countiterr   rk   exptanhr   more_to_writer   )r3   function_valuesesr   r   varisdmeanfvals_lr'   dfitdampedistr{   rs                  r   r}   zBoundPenalty.update  s?    ;;4;;q>#9#';;q>#9KDD 6HHaK"((RTT9J1v:,.KKQ,@BDD9>q$BARTT!WQZ$B#E EE HHaK"%%//1E 255::dkk"%%++bgg2F&GHHESVJV 'U^AFaK 5q>1BGGEN";;saIIQ$BFF]s499~1IIQDII/tyy>B!a%2::!555IIMMO yy#1beemm))C/!34 tyy>Q U V V 99; 8 8BLLA<M!q4xj.1DJ'+D$##HHSZ!c!QVbeemm>Q>Q5Q.R*RRSE1u 

bffeai2775193E%E%JKTQQ
 

4::D01RVVG_d5JJ1QEAI??,

519%c!RUU]]5H5H35NQR5R.S)SS%
 FF	''	2

bffRVVQ!WcAg,>Q%GH#aQSQVQVQ^Q^QdQdgiQilmQmJnnn

0H0HD,aSVRWiW y %Cs   U0
r   r   )
rF   rG   rH   rI   r5   rO   r<   r   r}   r   r   s   @r   rN   rN     s%    )TD!5J"Sr)   rN   r   )rI   
__future__r   r   r   warningsr   numpyr   	utilitiesr   r   utilities.utilsr   transformationsr	   r#   r(   objectr+   rL   rW   r   r/   rN   rJ   r)   r   <module>r      s    @ @   & " @X~ D*7,6 7,r,& ,&k& kZ	# LF( LF\\& \r)   