Ë
    ~\;j\5  ã                   óB  — d Z ddlZddlZddlZddlZddlZddlmZ ddlm	Z	m
Z
 	 ddlmZ ddlmZ g d	¢Z G d
„ de
j(                  «      Zdd„Zd„ Zd„ Z G d„ de«      Zdd„Z ej6                  ed¬«      Zy# e$ r  ddlZd„ Zej                  j                  ZY Œkw xY w)zB
Support for random optimizers, including the random-greedy path.
é    N)Údequeé   )ÚhelpersÚpaths)Úchoices)Úseedc                 óˆ   — t        |«      }t        j                  j                  | |D �cg c]  }||z  ‘Œ	 c}d¬«      S c c}w )Nr   )ÚpÚsize)ÚsumÚnpÚrandomÚchoice)Ú
populationÚweightsÚnormÚws       ú_G:\00. PROJECTS\API\Inventory\templateJSON\kerjaOCR\Lib\site-packages\opt_einsum/path_random.pyÚrandom_choicesr      s>   € Ü�7‹|ˆÜ�y‰y×Ñ 
ÁÓ.IÁ¸A¨q°4«xÀÑ.IÐPQÐÓRÐRùÒ.Is   ª?
)ÚRandomGreedyÚrandom_greedyÚrandom_greedy_128c                   óz   — e Zd ZdZdd„Zed„ «       Zed„ «       Zej                  d„ «       Zd„ Z	d„ Z
d	„ Zd
„ Zd„ Zy)ÚRandomOptimizeraÙ  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                 óþ   — |dvrt        d«      ‚|| _        || _        || _        t	        j
                  |«      | _        || _        || _        g | _	        g | _
        t        d«      t        d«      dœ| _        d| _        y )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__zRandomOptimizer.__init__U   sx   € àÐ,Ñ,ÜÐMÓNÐNà&ˆÔØ ˆŒØ ˆŒÜ×)Ñ)¨(Ó3ˆŒØ ˆŒØ(ˆÔàˆŒ
ØˆŒ
Ü# E›l´E¸%³LÑAˆŒ	àˆÕó    c                 óF   — t        j                  | j                  d   «      S )z$The best path found so far.
        Ússa_path)r   Ússa_to_linearr)   ©r+   s    r   ÚpathzRandomOptimizer.pathg   s   € ô ×"Ñ" 4§9¡9¨ZÑ#8Ó9Ð9r-   c                 ó   — | j                   S ©N)Ú	_parallelr1   s    r   r$   zRandomOptimizer.parallelm   s   € à�~‰~Ðr-   c                 ó:  — t        | dd«      r| j                  j                  «        || _        d| _        |du rd | _        y |du rddlm}  |«       | _        d| _        y t        |t        j                  «      rddlm}  ||«      | _        d| _        y || _        y )NÚ_managing_executorFTr   )ÚProcessPoolExecutor)
ÚgetattrÚ	_executorÚshutdownr5   r7   Úconcurrent.futuresr8   Ú
isinstanceÚnumbersÚNumber)r+   r$   r8   s      r   r$   zRandomOptimizer.parallelq   s“   € ô �4Ð-¨uÔ5Ø�N‰N×#Ñ#Ô%à!ˆŒØ"'ˆÔà�uÑØ!ˆDŒNØà�tÑÝ>Ù0Ó2ˆDŒNØ&*ˆDÔ#Øä�h¤§¡Ô/Ý>Ù0°Ó:ˆDŒNØ&*ˆDÔ#Øð "ˆ�r-   c              #   óÈ  K  — t        «       | _        |D ]†  }t        | j                  «      | j                  k  r8| j                  j	                   | j
                  j                  ||g|¢­Ž «       Œ]| j                  j                  «       j                  «       –— Œˆ | j                  r8| j                  j                  «       j                  «       –— | j                  rŒ7yy­w)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_parallelz%RandomOptimizer._gen_results_parallel�   s¬   è ø€ ô ›ˆŒó ˆAÜ�4—=‘=Ó! D×$5Ñ$5Ò5Ø—‘×$Ñ$Ð%: T§^¡^×%:Ñ%:¸8ÀQÐ%NÈÒ%NÔOØØ—-‘-×'Ñ'Ó)×0Ñ0Ó2Ó2ð	 ð �mŠmØ—-‘-×'Ñ'Ó)×0Ñ0Ó2Ò2ð �m�mùs   ‚CC"Ã C"c                 ó`   — | j                   �"| j                  D ]  }|j                  «        Œ y y r4   )r:   rA   Úcancel)r+   Úfs     r   Ú_cancel_futureszRandomOptimizer._cancel_futures�   s(   € Ø�>‰>Ð%Ø—]”]�Ø—‘•
ñ #ð &r-   c                 ó   — t         ‚r4   )ÚNotImplementedError)r+   ÚinputsÚoutputÚ	size_dicts       r   ÚsetupzRandomOptimizer.setup¢   s   € Ü!Ð!r-   c                 óD  ‡‡— | j                  |||«       | j                  �t        j                  «       }| j                  |||«      \  ŠŠ| j                  t        | j                  «      z   }|| j                  z   }t        ||«      }| j                  �| j                  |‰‰«      }	nˆˆfd„|D «       }	|	D ]Ì  \  }
}}| j                  j                  |«       | j                  j                  |«       | j                  ||| j                  d   | j                  d   «      }|r-|| j                  d<   || j                  d<   |
| j                  d<   | j                  €Œ§t        j                  «       | j                  z   kD  sŒÌ n | j                  «        | j                   S )Nc              3   ó0   •K  — | ]  } ‰|g‰¢­Ž –— Œ y ­wr4   © )Ú.0rJ   Ú
trial_argsrH   s     €€r   Ú	<genexpr>z+RandomOptimizer.__call__.<locals>.<genexpr>¶   s   øè ø€ Ð@¹°1‘h˜qÐ. :Ö.¹ùs   ƒr   r   r/   )Ú_check_args_against_first_callr    ÚtimerU   r*   rB   r&   r   Úranger:   rK   rC   r'   r#   r)   rO   r2   )r+   rR   rS   rT   Úmemory_limitÚt0Úr_startÚr_stoprG   Útrialsr/   Úcostr   Úfound_new_bestrZ   rH   s                 @@r   Ú__call__zRandomOptimizer.__call__¥   sm  ù€ Ø×+Ñ+¨F°F¸IÔFð �=‰=Ð$Ü—‘“ˆBà#Ÿz™z¨&°&¸)ÓDÑˆ�*à×%Ñ%¬¨D¯J©J«Ñ7ˆØ˜4×+Ñ+Ñ+ˆÜ˜ Ó(ˆð �>‰>Ð%Ø×/Ñ/°¸À:ÓN‰Fä@¹Ó@ˆFó %+Ñ ˆH�d˜Dð �J‰J×Ñ˜dÔ#Ø�J‰J×Ñ˜dÔ#ð "Ÿ[™[¨¨t°T·Y±Y¸wÑ5GÈÏÉÐSYÑIZÓ[ˆNáØ%)�—	‘	˜'Ñ"Ø$(�—	‘	˜&Ñ!Ø(0�—	‘	˜*Ñ%ð —‘Ñ)´·	±	³¸bÀ4Ç=Á=Ñ>PÓ0PÙð! %+ð$ 	×ÑÔØ�y‰yÐr-   c                 óT   — t        | dd«      r| j                  j                  «        y y )Nr7   F)r9   r:   r;   r1   s    r   Ú__del__zRandomOptimizer.__del__Î   s$   € ä�4Ð-¨uÔ5Ø�N‰N×#Ñ#Õ%ð 6r-   )é    Nr   Fé€   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r,   Úpropertyr2   r$   ÚsetterrK   rO   rU   rf   rh   rX   r-   r   r   r      sg   „ ñ5ól ð$ ñ:ó ð:ð
 ñó ðð ‡_�_ñ"ó ð"ò63ò ò
"ò'óR&r-   r   c                 ót  — d}g }| rJ||k  rEt        j                  | «      \  }}}	}
||vs|	|vrŒ*|j                  |||	|
f«       |dz  }| r||k  rŒE|dk(  ry|dk(  r|d   S |D �cg c]
  }|d   d   ‘Œ }}|d   }|r|t        dt	        |«      «      z  }|dk(  r|D �cg c]  }||k(  rdnd‘Œ }}n)|D �cg c]  }t        j                  ||z
   |z  «      ‘Œ  }}t        t        |«      |¬«      \  }|j                  |«      \  }}}	}
|D ]  }t        j                  | |«       Œ |||	|
fS c c}w c c}w c c}w )a·  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ÚheappoprC   ÚmaxÚabsÚmathÚexpr   r^   ÚpopÚheappush)ÚqueueÚ	remainingÚnbranchÚtemperatureÚrel_temperatureÚnr   rd   Úk1Úk2Úk12r   r&   ÚcminÚcÚenergiesÚchosenÚothers                     r   Úthermal_chooserrˆ   Ô   s�  € ðF 	
€AØ€GÙ
�A˜’KÜ!ŸM™M¨%Ó0Ñˆˆb�"�cØ�YÑ "¨IÑ"5ØØ�‰˜˜b " cÐ*Ô+Ø	ˆQ‰ˆñ �A˜“Kð 	ˆA‚vØØˆA‚vØ�q‰zÐá(/Ó0©˜fˆV�A‰Y�q‹\¨€EÐ0Ø�‰8€Dñ Ø”s˜1œc $›iÓ(Ñ(ˆð �cÒÙ38Ó9±5¨a˜˜dš‘A¨Ñ)°5ˆÑ9ñ BGÓGÁ¸A”D—H‘H˜q 4™x˜[¨;Ñ6Õ7ÀˆÐGô œU 1›X¨xÔ8�G€FØŸ™ FÓ+Ñ€Dˆ"ˆb�#ó ˆÜ�‰�u˜eÕ$ð ð ��R˜ÐÐùò- 1ùò :ùò Hs   Á%D+ÂD0Â5#D5c           	      óÆ  — t        t        t        |«      «      }t        |«      }t        t	        t        |«      «      «      }d}d}| D ]”  \  }}t        j                  ||||||«      \  }	}
|j                  |«       |j                  |«       |j                  t        |«      «       |j                  |	«       ||
z  }t        |t        j                  |	|«      «      }Œ– ||fS )z3Compute the flops and max size of an ssa path.
    r   )ÚlistÚmapÚ	frozensetÚsetr^   rB   r   Úcalc_k12_flopsÚdiscardÚaddrC   rt   r   Úcompute_size_by_dict)r/   rR   rS   rT   r{   Ú
total_costÚmax_sizeÚiÚjr‚   Úflops12s              r   Ússa_path_compute_costr—     sÐ   € ô ”#”i Ó(Ó)€FÜ�vÓ€FÜ”Eœ#˜f›+Ó&Ó'€IØ€JØ€Hã‰ˆˆ1Ü×+Ñ+¨F°F¸IÀqÈ!ÈYÓW‰ˆˆWØ×Ñ˜!ÔØ×Ñ˜!ÔØ�‰”c˜&“kÔ"Ø�‰�cÔØ�gÑˆ
Ü�x¤×!=Ñ!=¸cÀ9Ó!MÓN‰ð ð �xÐÐr-   c                 ó„   — | dk(  rd}t        | «       t        j                  |||||«      }t        ||||«      \  }}|||fS )zKA single, repeatable, greedy trial run. Returns ``ssa_path`` and cost.
    r   N)Úrandom_seedr   Ússa_greedy_optimizer—   )	rJ   rR   rS   rT   Ú	choose_fnÚcost_fnr/   rd   r   s	            r   Ú_trial_greedy_ssa_path_and_costr�   3  sP   € ð 	ˆA‚vàˆ	ä�„Nä×(Ñ(¨°¸ÀIÈwÓW€HÜ& x°¸ÀÓK�J€Dˆ$à�T˜4ÐÐr-   c                   ó:   ‡ — e Zd ZdZdˆ fd„	Zed„ «       Zd„ Zˆ xZS )r   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                 ó\   •— || _         || _        || _        || _        t	        ‰| �  di |¤Ž y )NrX   )rœ   r}   r~   r|   Úsuperr,   )r+   rœ   r}   r~   r|   ÚkwargsÚ	__class__s         €r   r,   zRandomGreedy.__init__b  s1   ø€ ØˆŒØ&ˆÔØ.ˆÔØˆŒÜ‰ÑÑ"˜6Ó"r-   c                 ó˜   — | j                   dk(  ryt        j                  t        | j                  | j                   | j
                  ¬«      S )z­The 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~   r1   s    r   r›   zRandomGreedy.choose_fni  sC   € ð �<‰<˜1ÒØä× Ñ ¤Ø-1×-=Ñ-=Ø)-¯©Ø15×1EÑ1EôGð 	Gr-   c                 óL   — t         }|||| j                  | j                  f}||fS r4   )r�   r›   rœ   )r+   rR   rS   rT   ÚfnrI   s         r   rU   zRandomGreedy.setupw  s(   € Ü,ˆØ˜ 	¨4¯>©>¸4¿<¹<ÐHˆØ�4ˆxˆr-   )zmemory-removed-jitterg      ð?Té   )	rk   rl   rm   rn   r,   ro   r›   rU   Ú__classcell__)r¢   s   @r   r   r   B  s(   ø„ ñõ>#ð ñGó ðGör-   r   c                 ó.   — t        di |¤Ž} || |||«      S )z
    rX   )r   )rR   rS   Úidx_dictr_   Úoptimizer_kwargsÚ	optimizers         r   r   r   }  s#   € ô Ñ0Ð/Ñ0€IÙ�V˜V X¨|Ó<Ð<r-   rj   )r   )r¨   r   Tr4   )rn   r¤   rr   rv   r>   r]   Úcollectionsr   Ú r   r   r   r   r   r   r™   ÚImportErrorÚnumpyr   Ú__all__ÚPathOptimizerr   rˆ   r—   r�   r   r   r¥   r   rX   r-   r   Ú<module>r´      s­   ðñó Û Û Û Û Ý ç ð
!Ý0Ý*ò A€ôs&�e×)Ñ)ô s&ólGòT ò* ô8�?ô 8óv=ð &�I×%Ñ% mÀÔEÑ øðe ò !ÛòSð —)‘)—.‘.‚Kð!ús   ¦A9 Á9"BÂB