
    -ji-                    
   S SK Jr  S SKrS SKrS SKrS SKrS SKJr  \R                  " S\R                  -  5      r\R                  " \5      r\R                  " S5      \R                  -  r\R                  " S5      rSS jrSS jr\R$                  " S5      SS	 j5       rSS
 jr\R$                  " S5      SS j5       rSS jrSS jrSS jrSS jrSS jr   S           SS jjr  S           SS jjrg)    )annotationsNerf      c                .    [         R                  " X5      $ N)np	logaddexplog_plog_qs     Y/home/james-whalen/.local/lib/python3.13/site-packages/optuna/samplers/_tpe/_truncnorm.py_log_sumr   3   s    <<%%    c                b    U [         R                  " [         R                  " X-
  5      * 5      -   $ r	   )r
   log1pexpr   s     r   	_log_diffr   7   s$    288RVVEM22333r   i  c                    U S-  nUS:  a  S[         R                  " U* 5      -  nU$ US:  a  SS[         R                  " U5      -  -   nU$ SS[         R                  " U5      -  -
  nU$ )N;f?g;f      ?g;f?      ?)matherfcr   )axys      r   _ndtr_singler   ;   sr    	F
A;$))QB- H 
Z### H #		!$$Hr   c                *    SS[        U S-  5      -  -   $ )Nr   r   r   r   s    r   _ndtrr"   I   s    s1v:&&&r   c                P   U S:  a  [        U * 5      * $ U S:  a  [        R                  " [        U 5      5      $ SU S-  -  [        R                  " U * 5      -
  S[        R                  " S[        R                  -  5      -  -
  nSnSnSnSnSU S-  -  nSnS	n[	        X#-
  5      [
        R                  R                  :  aN  US-  nUnU* nXV-  nUSU-  S-
  -  nX7U-  U-  -  n[	        X#-
  5      [
        R                  R                  :  a  MN  U[        R                  " U5      -   $ )
N   i      r   r   g        r      r   )r   r   logpiabssys
float_infoepsilon)	r   log_LHS
last_totalright_hand_side	numeratordenom_factor
denom_conssignis	            r   _log_ndtr_singler5   N   s"   1uaR   3wxxQ((QTkDHHaRL(3!dgg+1F+FFGJOILQTJD	A
j*
+cnn.D.D
D	Q$
u"QUQY	)+l:: j*
+cnn.D.D
D TXXo...r   c                l    [         R                  " [        SS5      " U 5      R                  [        5      $ )Nr&   )r
   
frompyfuncr5   astypefloatr!   s    r   	_log_ndtrr:   i   s&    ==)1a03::5AAr   c                "    U S-  * S-  [         -
  $ )Nr   g       @)_norm_pdf_logC)r   s    r   _norm_logpdfr=   m   s    T7S=>))r   c                  ^ US:*  nU S:  nX#-  ) nSS jmSU4S jjnSS jn[         R                  " U [         R                  [         R                  S9nX   =nR                  (       a  T" XU   5      Xr'   X   =n	R                  (       a  U" XU   5      Xs'   X   =n
R                  (       a  U" XU   5      Xt'   [         R
                  " U5      $ )z3Log of Gaussian probability mass within an intervalr   c                >    [        [        U5      [        U 5      5      $ r	   )r   r:   r   bs     r   mass_case_left'_log_gauss_mass.<locals>.mass_case_leftz   s    1y|44r   c                   > T" U* U * 5      $ r	    )r   rA   rB   s     r   mass_case_right(_log_gauss_mass.<locals>.mass_case_right}   s    qb1"%%r   c                \    [         R                  " [        U 5      * [        U* 5      -
  5      $ r	   )r
   r   r"   r@   s     r   mass_case_central*_log_gauss_mass.<locals>.mass_case_central   s$     xxq	E1"I-..r   )
fill_valuedtyper   
np.ndarrayrA   rN   returnrN   )r
   	full_likenan
complex128sizereal)r   rA   	case_left
case_rightcase_centralrF   rI   outa_lefta_right	a_centralrB   s              @r   _log_gauss_massr\   q   s    
 QIQJ+,L5&/ ,,qRVV2==
AC,$$')== &&)'Z=A_$	**-i<I773<r   c                n   U S:  nU R                  5       n[        R                  " [        R                  " X   5      * 5      X!'   [        R                  " U 5      n[        R
                  " US:  5      =nS   R                  (       a%  [        R                  " SX$   [        -   -  5      * X4'   [        R
                  " US:  5      =nS   R                  (       a7  [        * [        R                  " [        R                  " X%   * 5      5      -  X5'   [        S5       H  n[        U5      nSUS-  -  [        -
  nXr-
  [        R                  " Xx-
  5      -  n	X9-  n[        R                  " [        R                  " U	5      S[        R                  " U5      -  :  5      (       d  M    O   X1==   S	-  ss'   U$ )
a  
Use the Newton method to efficiently find the root.

`ndtri_exp(y)` returns `x` such that `y = log_ndtr(x)`, meaning that the Newton method is
supposed to find the root of `f(x) := log_ndtr(x) - y = 0`.

Since `df/dx = d log_ndtr(x)/dx = (ndtr(x))'/ndtr(x) = norm_pdf(x)/ndtr(x)`, the Newton update
is x[n + 1] := x[n] - (log_ndtr(x) - y) * ndtr(x) / norm_pdf(x).

As an initial guess, we use the Gaussian tail asymptotic approximation:
    1 - ndtr(x) \simeq norm_pdf(x) / x
    --> log(norm_pdf(x) / x) = -1/2 * x**2 - 1/2 * log(2pi) - log(x)

First recall that y is a non-positive value and y = log_ndtr(inf) = 0 and
y = log_ndtr(-inf) = -inf.

If abs(y) is very small, we first derive -x such that z = log_ndtr(-x) and then flip the sign.
Please note that the following holds:
    z = log_ndtr(-x) --> z = log(1 - ndtr(x)) = log(1 - exp(y)) = log(-expm1(y)).
Recall that as long as ndtr(x) = exp(y) > 0.5 --> y > -log(2) = -0.693..., x becomes positive.

ndtr(x) = exp(y) \simeq 1 + y --> -y \simeq 1 - ndtr(x). From this, we can calculate:
    log(1 - ndtr(x)) \simeq log(-y) \simeq -1/2 * x**2 - 1/2 * log(2pi) - log(x).
Because x**2 >> log(x), we can ignore the second and third terms, leading to:
    log(-y) \simeq -1/2 * x**2 --> x \simeq sqrt(-2 log(-y)).
where we take the positive `x` as abs(y) becomes very small only if x >> 0.
The second order approximation version is sqrt(-2 log(-y) - log(-2 log(-y))).

If abs(y) is very large, we use log_ndtr(x) \simeq -1/2 * x**2 - 1/2 * log(2pi) - log(x).
To solve this equation analytically, we ignore the log term, yielding:
    log_ndtr(x) = y \simeq -1/2 * x**2 - 1/2 * log(2pi)
    --> y + 1/2 * log(2pi) = -1/2 * x**2 --> x**2 = -2 * (y + 1/2 * log(2pi))
    --> x = sqrt(-2 * (y + 1/2 * log(2pi))

For the moderate y, we use Eq. (13), i.e., standard logistic CDF, in the following paper:

- `Approximating the Cumulative Distribution Function of the Normal Distribution
  <https://jsr.isrt.ac.bd/wp-content/uploads/41n1_5.pdf>`__

The standard logistic CDF approximates ndtr(x) with:
    exp(y) = ndtr(x) \simeq 1 / (1 + exp(-pi * x / sqrt(3)))
    --> exp(-y) \simeq 1 + exp(-pi * x / sqrt(3))
    --> log(exp(-y) - 1) \simeq -pi * x / sqrt(3)
    --> x \simeq -sqrt(3) / pi * log(exp(-y) - 1).
g{Gzr   g       d   r%   r   g:0yE>)copyr
   r'   expm1
empty_likenonzerorS   sqrtr<   _ndtri_exp_approx_Cranger:   r   allr)   )
r   flippedzr   
small_indsmoderate_inds_
log_ndtr_xlog_norm_pdf_xdxs
             r   
_ndtri_exprq      sW   ^ %iG	A!*--.AJ
aAjjR((
!,11)G!HIIAG,,a055//"&&1CSBS9T2UU3Zq\
1~5 nz'B CC	66"&&*tbffQi//00  J"J Hr   c                   [         R                  " XU5      u  pn[         R                  " XU5      u  pnUS:  nU) n[        X5      nSS jnSS jn[         R                  " U 5      nX   =n	R
                  (       a  U" XU   X#   XS   5      X'   X   =n
R
                  (       a  U" XU   X$   XT   5      X'   XS:H     XS:H  '   X S:H     XS:H  '   [        R                  XU:H  '   U$ )a  
Compute the percent point function (inverse of cdf) at q of the given truncated Gaussian.

Namely, this function returns the value `c` such that:
    q = \int_{a}^{c} f(x) dx

where `f(x)` is the probability density function of the truncated normal distribution with
the lower limit `a` and the upper limit `b`.

More precisely, this function returns `c` such that:
    ndtr(c) = ndtr(a) + q * (ndtr(b) - ndtr(a))
for the case where `a < 0`, i.e., `case_left`. For `case_right`, we flip the sign for the
better numerical stability.
r   c                p    [        [        U5      [        R                  " U 5      U-   5      n[	        U5      $ r	   )r   r:   r
   r'   rq   qr   rA   log_mass	log_Phi_xs        r   ppf_leftppf.<locals>.ppf_left   s*    Yq\266!9x+?@	)$$r   c                v    [        [        U* 5      [        R                  " U * 5      U-   5      n[	        U5      * $ r	   )r   r:   r
   r   rq   rt   s        r   	ppf_rightppf.<locals>.ppf_right   s3     Yr]BHHaRL8,CD	9%%%r   r&   )
ru   rN   r   rN   rA   rN   rv   rN   rO   rN   )r
   
atleast_1dbroadcast_arraysr\   rc   rS   r   rQ   )ru   r   rA   rU   rV   rv   rx   r{   rX   q_leftq_rights              r   ppfr      s     mmA!$GA!!!!*GA!AIJq$H%& --
C,$$!&I,hFYZ= &&#Gz]AM8K_`F)CQKF)CQK((CQKJr   c                    U=(       d    [         R                  R                  5       n[         R                  " XX#5      R                  nUR                  SSUS9n[        X`U5      U-  U-   $ )z
This function generates random variates from a truncated normal distribution defined between
`a` and `b` with the mean of `loc` and the standard deviation of `scale`.
r   r&   )lowhighrS   )r
   randomRandomState	broadcastshapeuniformr   )r   rA   locscalerandom_staterS   	quantiless          r   rvsr     s_      :299#8#8#:L<<c)//D$$$>IyQ%'#--r   c                T   X-
  U-  n [         R                  " XU5      u  pn[        U 5      [        X5      -
  [         R                  " U5      -
  n[         R
                  " XU5      u  pn[         R                  " X:H  X:  X:  -  /[         R                  [         R                  * /US9$ )N)default)	r
   r}   r=   r\   r'   r~   selectrQ   inf)r   r   rA   r   r   rX   s         r   logpdfr     s     
EAmmA!$GA!
q/OA1
1BFF5M
AC!!!*GA!99afqu/0266BFF72CSQQr   )r   rN   r   rN   rO   rN   )r   r9   rO   r9   )r   rN   rO   rN   )r   rN   rO   rN   rM   )r   rN   rO   rN   )ru   rN   r   np.ndarray | floatrA   r   rO   rN   )r   r&   N)r   rN   rA   rN   r   r   r   r   r   znp.random.RandomState | NonerO   rN   )r   r&   )r   rN   r   r   rA   r   r   r   r   r   rO   rN   )
__future__r   	functoolsr   r*   numpyr
   optuna.samplers._tpe._erfr   re   r(   _norm_pdf_Cr'   r<   rf   _log_2r   r   	lru_cacher   r"   r5   r:   r=   r\   rq   r   r   r   rE   r   r   <module>r      sc  D #   
  ) iiDGG$+&iilTWW, 	!&4 T
 
'
 T/ /4B*$NEP*`   !15... 
. 	.
 /. .*   !RRR R 
	R
 R Rr   