
    i\5                     B   S r SSKrSSKrSSKrSSKrSSKrSSKJr  SSKJ	r	J
r
   SSKJr  SSKJr  / S	Qr " S
 S\
R(                  5      rSS jrS rS r " S S\5      rSS jr\R6                  " \SS9rg! \ a     SSKrS r\R                  R                  r Nkf = f)zB
Support for random optimizers, including the random-greedy path.
    N)deque   )helperspaths)choices)seedc                     [        U5      n[        R                  R                  X Vs/ s H  o3U-  PM	     snSS9$ s  snf )Nr   )psize)sumnprandomchoice)
populationweightsnormws       V/var/www/html/banglarbhumi/venv/lib/python3.13/site-packages/opt_einsum/path_random.pyrandom_choicesr      s<    7|yy
.IA4x.IPQRR.Is   =
)RandomGreedyrandom_greedyrandom_greedy_128c                       \ rS rSrSrSS jr\S 5       r\S 5       r\R                  S 5       rS r
S	 rS
 rS rS rSrg)RandomOptimizer   a%  Base class for running any random path finder that benefits
from repeated calling, possibly in a parallel fashion. Custom random
optimizers should subclass this, and the ``setup`` method should be
implemented with the following signature::

    def setup(self, inputs, output, size_dict):
        # custom preparation here ...
        return trial_fn, trial_args

Where ``trial_fn`` itself should have the signature::

    def trial_fn(r, *trial_args):
        # custom computation of path here
        return ssa_path, cost, size

Where ``r`` is the run number and could for example be used to seed a
random number generator. See ``RandomGreedy`` for an example.


Parameters
----------
max_repeats : int, optional
    The maximum number of repeat trials to have.
max_time : float, optional
    The maximum amount of time to run the algorithm for.
minimize : {'flops', 'size'}, optional
    Whether to favour paths that minimize the total estimated flop-count or
    the size of the largest intermediate created.
parallel : {bool, int, or executor-pool like}, optional
    Whether to parallelize the random trials, by default ``False``. If
    ``True``, use a ``concurrent.futures.ProcessPoolExecutor`` with the same
    number of processes as cores. If an integer is specified, use that many
    processes instead. Finally, you can supply a custom executor-pool which
    should have an API matching that of the python 3 standard library
    module ``concurrent.futures``. Namely, a ``submit`` method that returns
    ``Future`` objects, themselves with ``result`` and ``cancel`` methods.
pre_dispatch : int, optional
    If running in parallel, how many jobs to pre-dispatch so as to avoid
    submitting all jobs at once. Should also be more than twice the number
    of workers to avoid under-subscription. Default: 128.

Attributes
----------
path : list[tuple[int]]
    The best path found so far.
costs : list[int]
    The list of each trial's costs found so far.
sizes : list[int]
    The list of each trial's largest intermediate size so far.

See Also
--------
RandomGreedy
Nc                     US;  a  [        S5      eXl        X l        X0l        [        R
                  " U5      U l        X@l        XPl        / U l	        / U l
        [        S5      [        S5      S.U l        SU l        g )N)flopsr   z.`minimize` should be one of {'flops', 'size'}.infr   )
ValueErrormax_repeatsmax_timeminimizer   get_better_fnbetterparallelpre_dispatchcostssizesfloatbest_repeats_start)selfr    r!   r"   r%   r&   s         r   __init__RandomOptimizer.__init__U   sn    ,,MNN&  ))(3 (

#ElE%LA	    c                 H    [         R                  " U R                  S   5      $ )z$The best path found so far.
        ssa_path)r   ssa_to_linearr*   r,   s    r   pathRandomOptimizer.pathg   s     ""499Z#899r/   c                     U R                   $ N)	_parallelr3   s    r   r%   RandomOptimizer.parallelm   s    ~~r/   c                 N   [        U SS5      (       a  U R                  R                  5         Xl        SU l        USL a  S U l        g USL a  SSKJn  U" 5       U l        SU l        g [        U[        R                  5      (       a  SSKJn  U" U5      U l        SU l        g Xl        g )N_managing_executorFTr   )ProcessPoolExecutor)
getattr	_executorshutdownr8   r;   concurrent.futuresr<   
isinstancenumbersNumber)r,   r%   r<   s      r   r%   r9   q   s     4-u55NN##%!"'u!DNt>02DN&*D#h//>0:DN&*D# "r/   c              #     #    [        5       U l        U H  n[        U R                  5      U R                  :  a8  U R                  R	                  U R
                  R                  " X$/UQ76 5        M^  U R                  R                  5       R                  5       v   M     U R                  (       a>  U R                  R                  5       R                  5       v   U R                  (       a  M=  gg7f)zVLazily generate results from an executor without submitting all jobs at once.
        N)	r   _futureslenr&   appendr>   submitpopleftresult)r,   repeatstrial_fnargsrs        r   _gen_results_parallel%RandomOptimizer._gen_results_parallel   s       A4==!D$5$55$$T^^%:%:8%N%NO--'')0022	  mm--'')0022 mmms   C*C0.C0c                 f    U R                   b$  U R                   H  nUR                  5         M     g g r7   )r>   rE   cancel)r,   fs     r   _cancel_futuresRandomOptimizer._cancel_futures   s(    >>%]]
 # &r/   c                     [         er7   )NotImplementedError)r,   inputsoutput	size_dicts       r   setupRandomOptimizer.setup   s    !!r/   c                 P  ^^ U R                  XU5        U R                  b  [        R                  " 5       nU R                  XU5      u  mmU R                  [        U R                  5      -   nX`R                  -   n[        Xg5      nU R                  b  U R                  UTT5      n	OUU4S jU 5       n	U	 H  u  pnU R                  R                  U5        U R                  R                  U5        U R                  XU R                  S   U R                  S   5      nU(       a*  XR                  S'   XR                  S'   XR                  S'   U R                  c  M  [        R                  " 5       WU R                  -   :  d  M    O   U R                  5         U R                   $ )Nc              3   6   >#    U  H  nT" U/TQ76 v   M     g 7fr7    ).0rN   
trial_argsrL   s     r   	<genexpr>+RandomOptimizer.__call__.<locals>.<genexpr>   s     @1hq.:.s   r   r   r1   )_check_args_against_first_callr!   timer[   r+   rF   r'   r    ranger>   rO   rG   r(   r$   r*   rT   r4   )r,   rX   rY   rZ   memory_limitt0r_startr_stoprK   trialsr1   costr   found_new_bestra   rL   s                 @@r   __call__RandomOptimizer.__call__   s[   ++FIF ==$B#zz&)D*%%DJJ7+++( >>%//:NF@@F %+ HD JJd#JJd# "[[TYYw5GSYIZ[N%)		'"$(		&!(0		*% )		b4==>P0P! %+$ 	yyr/   c                 ^    [        U SS5      (       a  U R                  R                  5         g g )Nr;   F)r=   r>   r?   r3   s    r   __del__RandomOptimizer.__del__   s'    4-u55NN##% 6r/   )r>   rE   r;   r8   r+   r*   r$   r'   r    r!   r"   r%   r&   r(   )    Nr   F   )__name__
__module____qualname____firstlineno____doc__r-   propertyr4   r%   setterrO   rT   r[   rn   rq   __static_attributes__r_   r/   r   r   r      sg    5l $ : :
   __" "63 
"'R&r/   r   c                    Sn/ nU (       aP  XR:  aK  [         R                  " U 5      u  pxpX;  d  X;  a  M1  UR                  XxX45        US-  nU (       a  XR:  a  MK  US:X  a  gUS:X  a  US   $ U Vs/ s H
  oS   S   PM     nnUS   nU(       a  U[        S[	        U5      5      -  nUS:X  a  U Vs/ s H  oU:X  a  SOSPM     nnO,U Vs/ s H  n[
        R                  " X-
  * U-  5      PM!     nn[        [        U5      US9u  nUR                  U5      u  pxpU H  n[         R                  " U U5        M     XxX4$ s  snf s  snf s  snf )aC  A contraction 'chooser' that weights possible contractions using a
Boltzmann distribution. Explicitly, given costs ``c_i`` (with ``c_0`` the
smallest), the relative weights, ``w_i``, are computed as:

    w_i = exp( -(c_i - c_0) / temperature)

Additionally, if ``rel_temperature`` is set, scale ``temperature`` by
``abs(c_0)`` to account for likely fluctuating cost magnitudes during the
course of a contraction.

Parameters
----------
queue : list
    The heapified list of candidate contractions.
remaining : dict[str, int]
    Mapping of remaining inputs' indices to the ssa id.
temperature : float, optional
    When choosing a possible contraction, its relative probability will be
    proportional to ``exp(-cost / temperature)``. Thus the larger
    ``temperature`` is, the further random paths will stray from the normal
    'greedy' path. Conversely, if set to zero, only paths with exactly the
    same cost as the best at each step will be explored.
rel_temperature : bool, optional
    Whether to normalize the ``temperature`` at each step to the scale of
    the best cost. This is generally beneficial as the magnitude of costs
    can vary significantly throughout a contraction.
nbranch : int, optional
    How many potential paths to calculate probability for and choose from
    at each step.

Returns
-------
cost, k1, k2, k12
r   r   Ng        )r   )heapqheappoprG   maxabsmathexpr   rf   popheappush)queue	remainingnbranchtemperaturerel_temperaturenr   rl   k1k2k12r   r'   cmincenergieschosenothers                     r   thermal_chooserr      se   F 	
AG
AK!MM%0"""5"*+	Q AK 	AvAvqz(/0fAYq\E08D s1c$i(( c3895adA)59 BGGADHHqx[;67G U1Xx8GFF+Db ue$  R- 1 : Hs   2E3E&Ec           	         [        [        [        U5      5      n[        U5      n[        [	        [        U5      5      5      nSnSnU  H  u  px[        R                  " XXGX5      u  pUR                  U5        UR                  U5        UR                  [        U5      5        UR                  U	5        XZ-  n[        U[        R                  " X5      5      nM     XV4$ )z3Compute the flops and max size of an ssa path.
    r   )listmap	frozensetsetrf   rF   r   calc_k12_flopsdiscardaddrG   r   r   compute_size_by_dict)r1   rX   rY   rZ   r   
total_costmax_sizeijr   flops12s              r   ssa_path_compute_costr     s     #i()FvFE#f+&'IJH++FI!W!!c&k"c
x!=!=c!MN  r/   c                 |    U S:X  a  Sn[        U 5        [        R                  " XX4U5      n[        XaX#5      u  pxXgU4$ )zKA single, repeatable, greedy trial run. Returns ``ssa_path`` and cost.
    r   N)random_seedr   ssa_greedy_optimizer   )	rN   rX   rY   rZ   	choose_fncost_fnr1   rl   r   s	            r   _trial_greedy_ssa_path_and_costr   3  sD     	Av	N((wWH&xKJD4r/   c                   F   ^  \ rS rSrSrSU 4S jjr\S 5       rS rSr	U =r
$ )r   iB  a  

Parameters
----------
cost_fn : callable, optional
    A function that returns a heuristic 'cost' of a potential contraction
    with which to sort candidates. Should have signature
    ``cost_fn(size12, size1, size2, k12, k1, k2)``.
temperature : float, optional
    When choosing a possible contraction, its relative probability will be
    proportional to ``exp(-cost / temperature)``. Thus the larger
    ``temperature`` is, the further random paths will stray from the normal
    'greedy' path. Conversely, if set to zero, only paths with exactly the
    same cost as the best at each step will be explored.
rel_temperature : bool, optional
    Whether to normalize the ``temperature`` at each step to the scale of
    the best cost. This is generally beneficial as the magnitude of costs
    can vary significantly throughout a contraction. If False, the
    algorithm will end up branching when the absolute cost is low, but
    stick to the 'greedy' path when the cost is high - this can also be
    beneficial.
nbranch : int, optional
    How many potential paths to calculate probability for and choose from
    at each step.
kwargs
    Supplied to RandomOptimizer.

See Also
--------
RandomOptimizer
c                 V   > Xl         X l        X0l        X@l        [        TU ]  " S0 UD6  g )Nr_   )r   r   r   r   superr-   )r,   r   r   r   r   kwargs	__class__s         r   r-   RandomGreedy.__init__b  s)    &."6"r/   c                     U R                   S:X  a  g[        R                  " [        U R                  U R                   U R
                  S9$ )zThe function that chooses which contraction to take - make this a
property so that ``temperature`` and ``nbranch`` etc. can be updated
between runs.
r   N)r   r   r   )r   	functoolspartialr   r   r   r3   s    r   r   RandomGreedy.choose_fni  sC     <<1  -1-=-=)-151E1EG 	Gr/   c                 F    [         nXX0R                  U R                  4nXE4$ r7   )r   r   r   )r,   rX   rY   rZ   fnrM   s         r   r[   RandomGreedy.setupw  s"    ,	>>4<<Hxr/   )r   r   r   r   )zmemory-removed-jitterg      ?T   )ru   rv   rw   rx   ry   r-   rz   r   r[   r|   __classcell__)r   s   @r   r   r   B  s-    ># G G r/   r   c                 *    [        S0 UD6nU" XX#5      $ )z
    r_   )r   )rX   rY   idx_dictrg   optimizer_kwargs	optimizers         r   r   r   }  s     0/0IVX<<r/   rt   )r    )r   r   Tr7   )ry   r   r~   r   rB   re   collectionsr    r   r   r   r   r   r   r   ImportErrornumpyr   __all__PathOptimizerr   r   r   r   r   r   r   r   r_   r/   r   <module>r      s          
!0* As&e)) s&lGT * 8? 8v= %%mE e  !S ))..K!s   A8 8#BB