
    J-j<Y                     4    d Z ddlZddlZdZ	  G d de      Zy)u   Integer handling class `IntegerCentering` to be used in combination with CMA-ES.

Reference: Marty et al, LB+IC-CMA-ES: Two simple modiﬁcations of CMA-ES to
handle mixed-integer problems. PPSN 2024.
    NTc                   t    e Zd ZdZ	 	 ddZd ZddZd Zd Zd Z	dd	Z
d
 Zed        Zd Zd Zd ZddZy)IntegerCenteringuT  round values of int-variables that are different from the int-mean.

    This callable class changes a population of solutions in place, in
    particular rounding some of the integer variables. The call does not
    guaranty to round any or all integer variables. The class assumes that
    the fitness function only interprets the rounded values of integer
    variables, that is, it assumes that int-variables change the fitness
    only if their rounded (genotype) value change. (This may easily become
    a wrong assumption if a geno-pheno transformation is applied). The
    class tries to correct for the bias introduced by rounding values.

    This class should generally be used in combination with a lower bound
    on the integer variables along the lines of ``min((0.2,
    mueff/dimension))``, as it is induced by passing a nonempty
    ``'integer_variables'`` option to `CMAEvolutionStrategy`. Applying
    lower bounds alone is generally more effective than applying integer
    centering alone.

    Class instances have no dynamically changing state variables!

    When integer variable indices are passed to `CMAEvolutionStrategy` via
    the ``'integer_variables'`` `CMAOptions`, an `IntegerCentering` class
    instance is created, and it is called in `CMAEvolutionStrategy.tell`
    before the update of the state variables of CMA, passing mu (genotypic)
    solutions, like ``int_centering(self.pop_sorted[:self.sp.weights.mu],
    self.mean)`` . The call changes the `numpy` arrays of `self.pop_sorted`
    in place. The call tries to access the (phenotypic) bounds as defined
    in ``es.boundary_handler`` from the constructor argument. Hence it is
    expected to fail with a combination of ``bounds`` and
    ``fixed_variables`` set in `CMAOptions`.

    By default, integer centering is applied, e.g. with `fmin2` or
    `CMAEvolutionStrategy`, when the integer variable indices are given
    via the ``'integer_variables'`` option. Since v4.3.0, candidate
    solutions delivered by `CMAEvolutionStrategy.ask` have rounded values
    in all integer variable positions which can be switched off by setting
    `cma.evolution_strategy.round_integer_variables` to `False`.

    A simple example code:

    >>> import cma
    >>>
    >>> def int1_sphere(x):
    ...     return int(x[0] + 0.5 - (x[0] < 0))**2 + 1000 * (sum(xi**2 for xi in x[1:]))

    >>> es = cma.CMAEvolutionStrategy(2 * [2], 0.5,
    ...             {'integer_variables': [0], 'ftarget': 1e-9, 'verbose': -9})
    >>> es = es.optimize(int1_sphere)
    >>> # assert 'ftarget' in es.stop(), es.stop()  # fails sometimes (like 1%-ish)
    >>> # failure is less likely with options ``'tolfun': 0, 'tolfunhist': 0, 'tolflatfitness': 60``

    The following pseudocode shows a direct use case to explicitly see
    how/where integer centering is applied, namely before the state
    variables are updated in `tell`:

    >>> import numpy as np

    >>> # set dimension dependent lower bound on sample standard deviations
    >>> es = cma.CMAEvolutionStrategy(2 * [2], 0.5,
    ...             {'minstd': [0.2, 0], 'popsize_factor': 1.5, 'ftarget': 1e-9, 'verbose': -9})
    >>> # when integer_variables were passed in the above options,
    >>> # we can inactivate the internal integer centering like
    >>> es.integer_centering = lambda *args: args[0] if args else None
    >>> ic = cma.integer_centering.IntegerCentering([0])
    >>> while not es.stop():
    ...     X = es.ask()
    ...     F = [int1_sphere(x) for x in X]
    ...     # change the mu best solutions in place
    ...     _ = ic([X[i] for i in np.argsort(F)[:es.sp.weights.mu]], es.mean)
    ...     es.tell(X, F, check_points=False)  # don't check for changes in X
    ...     # es.logger.add()
    ...     # es.disp()
    >>> # assert 'ftarget' in es.stop(), es.stop()  # fails sometimes (like 1%-ish)

    Details: The default `method2` was used in the below reference and, as
    of version 4.0.0, is activated in `CMAEvolutionStrategy` when
    `integer_variables` are given as option.

    Reference: Marty et al, LB+IC-CMA-ES: Two simple modiﬁcations of
    CMA-ES to handle mixed-integer problems. PPSN 2024.
c                 6   t        |      | _        | j                  j                  t               j	                         D ci c]  \  }}|dk7  s|| c}}       | j                  j                  dd       	 d| j                  d   cxk  rdk  sVn | j                  d   rdnd}t        j                  d	j                  | j                  d   |             || j                  d<   d
| _	        	 | j                  |      | _        d
| _        d
| _        d
| _        	 t        | dt!        |      z         | _        d| _        d| _        g | _        g | _        g | _        g | _        t4        | _        y
c c}}w # t$        $ r t'        dj                  |            w xY w)aI  `int_indices` can also be a `CMAEvolutionStrategy` or `CMAOptions` instance.
        `correct_bias` can be in [0, 1] indicating the fraction of the bias
        that should be corrected (but only up to the mean center).

        `repair_into_bounds` repairs all solutions before centering is
        applied. This does not guaranty solutions to be feasible after
        centering in the case when `np.round` can make a solution
        infeasible.

        Details: When the bias computation and correction is applied only
        to the better half of the population (as by default), the value of
        `correct_bias` must be smaller than 1 to move the mean toward a
        solution that has rank lambda/5 or worse, because ``w_{lambda/5}``
        equals roughly ``1/mu`` (``w_{lambda/3}`` equals roughly
        ``1/mu/2``).

        selfbounds_offsetg-q=r   correct_bias   TFzOcorrect_bias should be in [0, 1], the given value {0} is now interpreted as {1}Nmethodz*`method` argument must be 1 or 2, was: {0})dictparamsupdatelocalsitems
setdefault	_warningswarnformat	_int_maskget_int_indicesint_indices_has_bounds_lower_bounds_upper_boundsgetattrstrcenterAttributeError
ValueError_record_printmahalanobis0mahalanobis1last_changeslast_changes_iterationcentering_on)	r   r   r
   r   repair_into_boundskwargsnv	new_values	            c/Users/jameslopez/projects/TradingBot25/.venv/lib/python3.12/site-packages/cma/integer_centering.py__init__zIntegerCentering.__init___   s}   & 6lFHNN,<L,<DAqVAaC,<LM6	* DKK/414 $N ;INN L"F4;;~#>	JL +4DKK'L//<!!	.!$3v;(>?DK &(#(= M&  	.I$fVn. .	.s   E.
E.
E4 4$Fc                     	 | j                   d   j                  j                  |      S # t        $ r$ t        j
                   t        j
                  gcY S w xY w)zBreturn lower and upper bound on variable `i`, not in use.
        es)r   boundary_handler	get_bound	Exceptionnpinf)r   is     r+   boundzIntegerCentering.bound   sK    	%;;t$55??BB 	%VVGRVV$$	%s   '* *AAc                    |dk7  rt        dj                  |            | j                  | j                  S d| _        d| j                  vry	 | j                  d   j                  }	 |j                         rd| _        | j                  S # t
        $ r.}t        j                  dj                  |             Y d }~Xd }~ww xY w# t
        $ r9}t        j                  dj                  |             Y d }~| j                  S d }~ww xY w)NbothzTwhich={0} is invalid. Currently, only 'both' bounds can be checked with `has_bounds`Fr.   z>``bh = self.params['es'].boundary_handler`` failed with

  {0}Tz&``bh.has_bounds()`` failed with

  {0})	NotImplementedErrorr   r   r   r/   r1   r   r   
has_bounds)r   whichbhes       r+   r9   zIntegerCentering.has_bounds   s    F?%%%+VE]4 4 '### t{{"	2T"33B	2~"--/#'    	2NN ''-vay2 2	2  	2NN ''-vay2 2	2s0   B )C 	C$C  C	D
$DD
c                     | j                   ;| j                  dt        j                  |      t        j                  z
        | _         | j                   S )zreturn lower bounds of dimension `dimension` or a scalar.

        `dimension` remains the dimension from the first call unless
        the ``_lower_bounds`` attribute is reset to `None`.
        lower)r   _set_boundsr2   zerosr3   r   	dimensions     r+   lower_boundszIntegerCentering.lower_bounds   F     %!%!1!1'HHY'"&&0"2D!!!    c                     | j                   ;| j                  dt        j                  |      t        j                  z         | _         | j                   S )zreturn upper bounds of dimension `dimension` or a scalar.

        `dimension` remains the dimension from the first call unless
        the ``_upper_bounds`` attribute is reset to `None`.
        upper)r   r?   r2   r@   r3   rA   s     r+   upper_boundszIntegerCentering.upper_bounds   rD   rE   c                    |dv sJ |       | j                         r| j                  d   j                  j                  |t	        |            |dd | j                  d   rjt        j                  |d      dk(  }||xx   |dk(  rdnd| j                  d   z  t        j                  dt        j                  ||               z  z  cc<   |S )	z!return in place modified `bounds`)r>   rG   r.   Nr   r	         ?r>   )	r9   r   r/   
get_boundslenr2   modmaximumabs)r   r:   boundsidxs       r+   r?   zIntegerCentering._set_bounds   s    **1E1*??D)::EEeSQW[YF1I{{?+ ffVQ'3.sUg%5$++o6 79;ArvvfUXkGZ9[ \ \rE   Nc                 J   |3t        | d      r| j                  | j                  S | j                  d   S t        |d      r*d| j                  vr|| j                  d<   |j                  }n|}g d}|D ]  }||v s||   } n |}d| j                  vr|| j                  d<   |S )zidetermine integer variable indices from es or es.opts or

        a variable index list or self.
        r   optsr.   )integer_variablesinteger_indicesr   )hasattrr   r   rT   )r   es_opts_indicesrT   namesnameindicess         r+   r   z IntegerCentering.get_int_indices   s    
 "m,1A1A1M ## 2{{=12 ?F+4;;&$3D!"''D"DGDt|t* 
 G+)0DKK&rE   c                     | |j                   |j                         t        j                  |j                  j
                  j                  |j                   d|j                  j
                  j                         |_        y)zchange `es.pop_sorted` and update `es.mean` accordingly.

        Not in use, as this must be ideally done in the middle of `tell`,
        that is, neither before nor after `tell`.
        r   N)	
pop_sortedmean_oldr2   dotspweightspositive_weightsmumean)r   r.   s     r+   callbackzIntegerCentering.callback   sR     	R]]BKK(&&77q)9)9:<rE   c                 H    | j                   t        d      | j                   S )Nzdimension is not known yet)r   r   )r   s    r+   int_maskzIntegerCentering.int_mask   s"    >>!9::~~rE   c                    | j                   s|S | j                  Ft        j                  t	        t        |            D cg c]  }|| j                  v  c}      | _        | j                  j                  dd      r| j                  |       | j                  ||       ddk  r/| j                  j                  dd      r| j                  |d       |S c c}w )az  round values of int-variables in `solution_list` and correct for bias.

        Return `solution_list`, however assignment is deprecated as
        `solution_list` is changed in place and, in particular, because we
        center usually only the first half of the population.

        Variables are only rounded if their rounded value is different from
        the mean. Bias correction is only applied if the rounded value is
        the same as the rounded value of the mean and only towards the
        rounded value of the mean, not away from it.

        None of these changes change the rounded variable value.

        Details: The bias correction could be applied directly to the mean
        after the mean update, as it probably does not have any relevant
        effect on the C update. This would require another call or passing
        the Delta mean in the return value.
    r&   F      )
randomized)r%   r   r2   asarrayrangerM   r   r   getrepairr   )r   solution_listrd   r4   s       r+   __call__zIntegerCentering.__call__   s    &     >>!ZZ27D	2B)D2BQ *+d.>.>)>2B)D EDN;;??/7KK& 	M4(6dkkoo&:EBKK%K8)Ds    Cc                    t        j                  |      }t        j                  |D cg c]  }t        j                  |      |k   c}d      }t        j                  |D cg c]  }t        j                  |      |kD   c}d      }t        j                  ||kD  ||      }g | _        |D ]  }| j
                  D ]  }t        j                  ||         ||   k7  sL| j                  d   s2||   dkD  s4t         j                  j                         ||   d||   z
  ||   z
  z  k  sn| j                  r:| j                  j                  | j                  d   j                  ||z
               t        j                  ||         ||<   | j                  s| j                  j                  | j                  d   j                  ||z
               | j                  d   | j                  d   }
}	| j                  j                  ||	|
g       | j                  j                  | j                  d   j                           |S c c}w c c}w )zsDEPRECATED (experimental and outdated) round values of int-variables in `solution_list` and reduce bias to the meanr   axisr   rJ   r	   r.   rK   )r2   roundrd   wherer#   r   r   randomrandr   r!   appendmahalanobis_normr"   r$   	countiter)r   rp   rd   m_intxmutated_down
mutated_upmaxmut_ratior4   n0n1s              r+   method1zIntegerCentering.method1  s   ww]K]e 3]KRSTWW=I=abhhqkE1=IPQR
xxz 9<TA%%HHQqTNeAh.4;;~3N!!_s*YY^^%Q1z!};L|\];^(__))00T1B1S1STUX\T\1]^HHQqTNQqT))00T1B1S1STUX\T\1]^!%!2!22!68I8I"8MB))00!R=33::4;;t;L;V;VW &  %  LIs   I$Ic                 ,	   d}| j                   rt        j                  |d      }t        j                  |      }	 t	        |d         }| j
                  d   rBt        j                  |      }	 t        j                  |      }	 t        j                  |      }		 t        |      D ]  \  }
}t        j                  |      }||k(  }|r| j                  |g       | j
                  d   r4	|||z
  dkD  z  ||z
  z  z  }	|||z
  dk  z  ||z
  z  z  }| ||z
  z  z  }|| | j                  z     || | j                  z  <    | j
                  d   rx| j
                  d   }d}|rddl
}ddl}| j                   |j                         }g }t        t        	            D ]g  \  }
\  }}}| j                  |
   s|dgz  } ||z  dk  r|| |z  |k  r	| |z  |z  ndgz  }A||z  dk  r|||z  | k  r	| |z  |z  ndgz  }b|dgz  }i | j                  dxx   |j                         |z
  z  cc<   |j                         }t        j                  t	                    }	fD ]  }| j                  |z  |z  dk  }t        j                   d	| ||   z  ||   z        ||<   ||u rCt        j"                  j%                         d
k  ret        j&                  |||z  dk  z   dk        rJ |||	|f        |rk| j                  dxx   j                         z
  z  cc<   t        j&                  |dz
  k        rt        j&                  |dz   |k\        sJ ||||z
  f       |r*| j                  t        j(                  |d      g      d   n|}|D ]2  }|t        j                  |      |k(  |||z
  z  dk  z  |z  ||z
  z  z  }4 | j                   rt        j                  |d      }t+        t	                    D 
cg c]   }
||
   ||
   z
  dz  dkD  r|
||
   ||
   z
  f" }}
|s| j
                  d   j,                  dz  s$t/        | j
                  d   j,                  |       |S #  |j                  t              | _        Y xY wc c}
w )ay  center (round) values of int-variables of solutions in `solution_list`.

        Elements of `solution_list` must accept boolean indexing like ``np.arrays``.

        Values are centered iff the centered value differs from the
        centered mean. If `correct_bias`, the introduced bias is amended by
        changing the other (noncentered) coordinates towards their
        int-center (which is the int-center of the mean) too, up to the
        fraction `correct_bias`.

        CAVEAT/TODO: the bias correction currently doesn't check bounds,
        hence it may push feasible solutions out-of-bounds by (i) centering
        single solutions and (ii) shifting coordinates towards their
        centered value during bias correction. In itself and overall, this
        may not be a problem, in particular when `repair` is applied before
        or after calling `method2`.
        Fr   rs   r   Ng        g      ?alphar	   g\(\?   alpha2gdy=Tcopyg^ 9^;r.   d   )r    r2   rd   ru   rM   r   r@   	enumeratero   rg   collectionstimealpha_timingsdefaultdictfloatzipminimumrw   rx   allarrayrm   r{   print)r   rp   rd   
repair_intmean0r|   dimbiasesmnegmposr4   r}   x_intismfrac
_time_coder   r   t0alphasbpr(   alphas2movesrR   m_int_repairedmean1biases2s                                r+   method2zIntegerCentering.method23  s   $ 
;;GGM2ES
 -"#;;~&XXc]F=88C=D@88C=DAm,DAqHHQKEE>C UG${{>*	Q/519==	Q/519==3$%!),,&+SD4==,@&AAsdT]]"#) -* ;;~& ;;~.DJ('' YY[$-c&$.E$FLAy1a==+2$QTEAIMD519q=s"KKQD1HrMD519q=s"KK2$ %G ""7+tyy{R/??+YY[ hhs6{+Gmmf,u4q8!zz!dUVC[-@5:-MN}		(84(?FF3&4-!"34q89V=@&$PT<UV ; & ""8,		b0@@,vvgo78vvgo78?#VWv-=<?? : & #kk288E+E*FGJ+0 "rxx{e+!^a%781<>!"%3a%79 : # ;;GGM2E9>s5z9J 99JAa58+a/%7 58eAh./9JG 9dkk$/99C?dkk$'117GDW L[-D-DU-K*N9s   .Q/ %R/Rc           
      :   | j                         s|S d}t        |d         }| j                  |      }| j                  |      }t	        |dd       D ]  \  }}t        j                  |      }t        j                  ||k  | j                        }	t        j                  ||kD  | j                        }
t
        j                  j                         dk  s"t        j                  |	|
z        r
J ||	|
f       t        j                  |	      r!|rt        j                  |d      }||	   ||	<   t        j                  |
      r!|rt        j                  |d      }||
   ||
<   |rt        j                  |      }t        j                  t        j                  |	||kD        t        j                  |
||k              }t        j                  |      r?||xx   ||   ||   z
  t
        j                  j                  t        |            z  z  cc<   |||<    |S )a  set values of int-variables of solutions of `solution_list` into bounds.

        Elements of `solution_list` are changed in place after passing them
        through ``np.asarray`` and `solution_list` is changed in place too.

        When ``randomized is True`` sample the value uniformly between the
        bound and the value center (the rounded bound) when the latter is
        feasible.
        Fr   Ngffffff?Tr   )r9   rM   rC   rH   r   r2   rl   logical_andrg   rw   rx   anyr   ru   
logical_orsum)r   rp   rk   r   r   lbsubsr4   r}   islowishighr   rR   s                r+   ro   zIntegerCentering.repair  s       -"#$$mA./DAq

1ANN1s7DMM:E^^AGT]];F99>>#d*"&&2H "5&K" "Hvve}.Au:%vvf~.AK&	mmBNN5%!)$D$&NN6519$EG66#;cFuSzAcF2biinnSX6NNNF M!- 0. rE   )r   TT)r7   )N)T)__name__
__module____qualname____doc__r,   r5   r9   rC   rH   r?   r   re   propertyrg   rq   r   r   ro    rE   r+   r   r      sf    Pb <@$(2)h% 0	"	"4<  
B,m^'rE   r   )r   warningsr   numpyr2   r%   objectr   r   rE   r+   <module>r      s(   
   Y|v |rE   