
    i<                         S SK JrJr  S SKJr  S SKJr  S SKJr  S SK	J
r
  S SKJr  S SKJrJrJrJr  S SKJr  S S	KJr  \" S
5      r\(       a  S SKJr   " S S\5      rS\S\S\4S jr " S S5      r " S S5      rg)    )CallableIterator)Enum)Random)TYPE_CHECKING)
SortedList)choices_key)ConjectureDataConjectureResultStatus_Overrun)LazySequenceCopy)sort_keyz-inf)ConjectureRunnerc                   $    \ rS rSrSrSrSrSrSrg)DominanceRelation"   r             N)	__name__
__module____qualname____firstlineno__NO_DOMINANCEEQUALLEFT_DOMINATESRIGHT_DOMINATES__static_attributes__r       d/var/www/html/ai-image-ml/venv/lib/python3.13/site-packages/hypothesis/internal/conjecture/pareto.pyr   r   "   s    LENOr!   r   leftrightreturnc                    [        U R                  5      n[        UR                  5      nX#:X  a  [        R                  $ X2:  aE  [	        XS9nU[        R
                  :X  a  [        R                  $ U[        R                  :X  d   eU$ X#:  d   eU R                  UR                  :  a  [        R                  $ UR                  R                  U R                  5      (       d  [        R                  $ U R                  [        R                  :X  a7  UR                  b*  U R                  UR                  :w  a  [        R                  $ [        U R                  5      [        UR                  5      -   HZ  nU R                  R!                  U["        5      nUR                  R!                  U["        5      nXv:  d  MJ  [        R                  s  $    [        R
                  $ )a+  Returns the dominance relation between ``left`` and ``right``, according
to the rules that one ConjectureResult dominates another if and only if it
is better in every way.

The things we currently consider to be "better" are:

    * Something that is smaller in shrinking order is better.
    * Something that has higher status is better.
    * Each ``interesting_origin`` is treated as its own score, so if two
      interesting examples have different origins then neither dominates
      the other.
    * For each target observation, a higher score is better.

In "normal" operation where there are no bugs or target observations, the
pareto front only has one element (the smallest valid test case), but for
more structured or failing tests it can be useful to track, and future work
will depend on it more.)r#   r$   )r   nodesr   r   	dominancer   r   r   statustagsissubsetr   INTERESTINGinteresting_originsettarget_observationsgetNO_SCORE)r#   r$   left_key	right_keyresulttarget
left_scoreright_scores           r"   r(   r(   )   s   & 

#H%I &&&2&555$444
 .;;;;;M  {{U\\! ---::tyy)) ---
 	v)))$$0##u'?'?? ---d../#e6O6O2PP--11&(C
//33FHE#$111	 Q +++r!   c                       \ rS rSrSrS\SS4S jrS\\-  \	-  S\
4S jrS	\\/S4   SS4S
 jrS\S\
4S jrS\\   4S jrS\S\4S jrS\4S jrS\SS4S jrSrg)ParetoFronth   a  Maintains an approximate pareto front of ConjectureData objects. That
is, we try to maintain a collection of objects such that no element of the
collection is pareto dominated by any other. In practice we don't quite
manage that, because doing so is computationally very expensive. Instead
we maintain a random sample of data objects that are "rarely" dominated by
any other element of the collection (roughly, no more than about 10%).

Only valid test cases are considered to belong to the pareto front - any
test case with a status less than valid is discarded.

Note that the pareto front is potentially quite large, and currently this
will store the entire front in memory. This is bounded by the number of
valid examples we run, which is max_examples in normal execution, and
currently we do not support workflows with large max_examples which have
large values of max_examples very well anyway, so this isn't a major issue.
In future we may weish to implement some sort of paging out to disk so that
we can work with larger fronts.

Additionally, because this is only an approximate pareto front, there are
scenarios where it can be much larger than the actual pareto front. There
isn't a huge amount we can do about this - checking an exact pareto front
is intrinsically quadratic.

"Most" of the time we should be relatively close to the true pareto front,
say within an order of magnitude, but it's not hard to construct scenarios
where this is not the case. e.g. suppose we enumerate all valid test cases
in increasing shortlex order as s_1, ..., s_n, ... and have scores f and
g such that f(s_i) = min(i, N) and g(s_i) = 1 if i >= N, then the pareto
front is the set {s_1, ..., S_N}, but the only element of the front that
will dominate s_i when i > N is S_N, which we select with probability
1 / N. A better data structure could solve this, but at the cost of more
expensive operations and higher per element memory use, so we'll wait to
see how much of a problem this is in practice before we try that.
randomr%   Nc                 J    Xl         / U l        [        S S9U l        S U l        g )Nc                 ,    [        U R                  5      $ N)r   r'   )ds    r"   <lambda>&ParetoFront.__init__.<locals>.<lambda>   s    (177+r!   )key)_ParetoFront__random _ParetoFront__eviction_listenersr   front_ParetoFront__pending)selfr;   s     r"   __init__ParetoFront.__init__   s'    NP!3=+4

 37r!   datac                 l   UR                   [        R                  :  a  g[        U[        5      (       a   eUR                  5       n[        U[        5      (       a   eU R                  (       d  U R                  R                  U5        gXR                  ;   a  gU R                  R                  U5        U R                  b   e Xl        [        U R                  5      n/ nU R                  R                  U5      nSnUS-   [        U5      :  a  US:  a  U R                  R                  US-   [        U5      5      nUR                  U5      n[        X5      nU[         R"                  :w  d   eU[         R$                  :X  a  UR'                  U5        SnOUS-  nUS-   [        U5      :  a  US:  a  M  U/n	US:  Ga8  [        U	5      S:  Ga(  UR)                  X@R                  R+                  SU5      5        X$   nSn
SnU[        U	5      :  a  X   n[        X{5      nU[         R$                  :X  aD  U
(       d  Sn
XyU'   US-  nOU	S   X   sX'   U	S'   U	R                  5         UR'                  U5        O@U[         R"                  :X  a  UR'                  U5        O<U[         R,                  :X  a  O'US-  nU[        U	5      :  a  M  U	R'                  U5        US-  nUS:  a  [        U	5      S:  a  GM(  U H  nU R/                  U5        M     XR                  ;   SU l        $ ! SU l        f = f)zAttempts to add ``data`` to the pareto front. Returns True if
``data`` is now in the front, including if data is already in the
collection, and False otherwiseFTNr   r   
   )r)   r   VALID
isinstancer   	as_resultrE   addrF   r   indexlenrC   	randrangepopr(   r   r   r   appendswaprandintr   _remove)rG   rJ   rE   	to_removeifailuresj	candidatedom
dominatorsalready_replacedvs               r"   rQ   ParetoFront.add   s    ;;%dH----~~dH----zzJJNN4 :: 	

t~~%%%R	"!N %TZZ0E
 13I 

  &A Ha%#e*$BMM++AE3u:>!IIaL	0/?????+:::$$Y/ HMH a%#e*$B  Jq&S_r1

1mm33Aq9:!H	#( #j/)"A#I1C/>>>//3,,5qMFA !+2 * :JM:b> 'NN,!((+ 1 A AA!((3 1 7 77Q- #j/)0 %%i0QA q&S_r1D Q ::%!DNTDNs    C1L* 9DL* +L* ;'L* *	L3fc                 :    U R                   R                  U5        g)zRegister a listener function that will be called with data when it
gets removed from the front because something else dominates it.N)rD   rV   )rG   rd   s     r"   on_evictParetoFront.on_evict  s     	!!((+r!   c                     [        U[        [        45      (       d  gUR                  5       n[        U[        5      (       a  gX R
                  ;   $ )NF)rO   r
   r   rP   r   rE   )rG   rJ   r4   s      r"   __contains__ParetoFront.__contains__  sA    $1A BCC!fh''##r!   c                 ,    [        U R                  5      $ r>   )iterrE   rG   s    r"   __iter__ParetoFront.__iter__  s    DJJr!   r[   c                      U R                   U   $ r>   )rE   )rG   r[   s     r"   __getitem__ParetoFront.__getitem__  s    zz!}r!   c                 ,    [        U R                  5      $ r>   )rS   rE   rm   s    r"   __len__ParetoFront.__len__  s    4::r!   c                      U R                   R                  U5        XR                  La  U R                   H  nU" U5        M     g g ! [         a     g f = fr>   )rE   remove
ValueErrorrF   rD   )rG   rJ   rd   s      r"   rY   ParetoFront._remove  sU    	JJd# ~~%..$ / &  		s   A 
AA)__eviction_listeners	__pending__randomrE   )r   r   r   r   __doc__r   rH   r
   r   r   boolrQ   r   rf   objectri   r   rn   intrq   rt   rY   r    r   r!   r"   r9   r9   h   s    !F7v 7$ 7j")99HD j" j"X,($4#5t#;< , ,
$ $D $ (#34  S %5  ,  r!   r9   c                   ,    \ rS rSrSrSS jrSS jrSrg)	ParetoOptimiseri#  a  Class for managing optimisation of the pareto front. That is, given the
current best known pareto front, this class runs an optimisation process
that attempts to bring it closer to the actual pareto front.

Currently this is fairly basic and only handles pareto optimisation that
works by reducing the test case in the shortlex order. We expect it will
grow more powerful over time.
Nc                 x    Xl         U R                   R                  c   eU R                   R                  U l        g r>   )_ParetoOptimiser__enginepareto_frontrE   )rG   engines     r"   rH   ParetoOptimiser.__init__-  s.    }}))555"&--"<"<
r!   c                   ^  [        5       n[        T R                  5      S-
  nS nUS:  Ga  T R                  R                  (       d  T R                  (       d   e[        U[        T R                  5      S-
  5      nT R                  U   n[        UR                  5      U;   a  US-  nM  XCLd   eUnU 4S jnT R                  R                  XES9nUR                  [        UR                  5      5        T R                  R                  R                  U5      nUS:  a  T R                  R                  (       d  M  g g g g )Nr   r   c                 x   > [        X5      [        R                  :X  a  TR                  R	                  U 5        gg)aO  Shrink to data that strictly pareto dominates the current
best value we've seen, which is the current target of the
shrinker.

Note that during shrinking we may discover other smaller
examples that this function will reject and will get added to
the front. This is fine, because they will be processed on
later iterations of this loop.TF)r(   r   r   rE   rY   )sourcedestinationrG   s     r"   allow_transition-ParetoOptimiser.run.<locals>.allow_transitionL  s3     [15F5U5UU
 JJ&&v.r!   )r   )r.   rS   rE   r   interesting_examplesminr	   choicesshrinkrQ   bisect_left)rG   seenr[   prevr5   r   shrunks   `      r"   runParetoOptimiser.run2  s   u 

Oa1fT]]??:::As4::*+AZZ]F6>>*d2Q%%%D$ ]]))&)TFHH[01 

  ,,V4AO 1fT]]???f?fr!   )__enginerE   )r   r   r%   N)r%   N)r   r   r   r   r}   rH   r   r    r   r!   r"   r   r   #  s    =
75r!   r   N)collections.abcr   r   enumr   r;   r   typingr   sortedcontainersr   %hypothesis.internal.conjecture.choicer	   #hypothesis.internal.conjecture.datar
   r   r   r   )hypothesis.internal.conjecture.junkdrawerr   'hypothesis.internal.conjecture.shrinkerr   floatr1   %hypothesis.internal.conjecture.enginer   r   r(   r9   r   r   r!   r"   <module>r      s~    /     ' =  G <=F <,$ <,-= <,BS <,~x xvF5 F5r!   