a
    ^ŠÝg\0  ã                   @   s”   d dl Z d dlZd dlZd dlZe e¡Ze jddfdd„Z	e j
Z
ddd„Ze jddfd	d
„Zddd„Zddd„Zddd„Zddd„Zddd„ZdS )é    NFéÿÿÿÿc                 C   s*  t  d| j|f ¡ t ¡ }| j\}}t |¡}	tj|||	d}
t ||¡}|dkr\t ¡ }|rŒt  d| ¡ t 	¡ }||_
tj|||d}d}|D ]f}|jd }| |¡ | | |¡\}}||7 }|
 ||¡ | ¡  ||7 }t  d|t ¡ | f ¡ q”|
 ¡  t  dt ¡ | |f ¡ |
j|
jfS )	z¤Computes the exact KNN search results for a dataset that possibly
    does not fit in RAM but for which we have an iterator that
    returns it block by block.
    z%knn_ground_truth queries size %s k=%d©Úkeep_maxr   úrunning on %d GPUs©ÚcoÚngpur   ú%d db elements, %.3f szGT time: %.3f s (%d vectors))ÚLOGÚinfoÚshapeÚtimeÚfaissÚis_similarity_metricZ
ResultHeapÚ	IndexFlatÚget_num_gpusÚGpuMultipleClonerOptionsÚshardÚindex_cpu_to_all_gpusÚaddÚsearchÚ
add_resultÚresetÚfinalizeÚDÚI)ÚxqÚdb_iteratorÚkÚmetric_typer   r   Út0ÚnqÚdr   ZrhÚindexr   Úi0ÚxbiÚnir   r   © r'   úm/var/www/html/cobodadashboardai.evdpl.com/venv/lib/python3.9/site-packages/faiss/contrib/exhaustive_search.pyÚknn_ground_truth   s4    



r)   é   c                 C   s¦  | j \}}t|tjƒ}t |j¡}|r.t|ƒnt|ƒ}t|j	|ƒ}	t
 d|› d|	 ›d| ›d| ›¡ t ¡ }
| | |	¡\}}t ¡ |
 }|r¬|d dk s¢J ‚| d¡}d}d	}|d	urŽ|sÜ|d	d	…|	d
 f |k }n|d	d	…|	d
 f |k}| ¡ dkrŽt
 d| ¡  ¡ t ¡ }
t|tjƒr\|}|rDt |d ¡}nt ||j¡}| |¡ | | | |¡\}}}|r‚| d¡}t ¡ |
 }t
 d¡ t ¡ }
|r¬tjntj}|||	||ƒ}tj}||ƒ|_||ƒ|_|d	ur||ƒ|_||ƒ|_|| d¡ƒ|_||ƒ|_tj |d
 dd}| !||ƒ¡ |d }tj ||j"d}tj |dd}| #||ƒ||ƒ¡ t ¡ |
 }t
 d|d›d|d›d|d›d¡ |||fS )aA  GPU does not support range search, so we emulate it with
    knn search + fallback to CPU index.

    The index_cpu can either be:
    - a CPU index that supports range search
    - a numpy table, that will be used to construct a Flat index if needed.
    - None. In that case, at most gpu_k results will be returned
    zGPU search z queries with k=z is_binary_index=z
 keep_max=é   i €  Úint16r   Né   zCPU search remain %dÚcombineÚint64©Údtyper   ztimes z.3fzs Ús)%r   Ú
isinstancer   ÚIndexBinaryr   r   ÚintÚfloatÚminZntotalr
   Údebugr   r   ÚastypeÚsumÚnpZndarrayZIndexBinaryFlatr   r   Úrange_searchZCombinerRangeKNNint16ZCombinerRangeKNNfloatZswig_ptrr   r   ÚmaskÚD_remainÚviewÚ
lim_remainÚI_remainÚemptyZcompute_sizesr1   Zwrite_resultÚrange)r   Úr2Ú	index_gpuZ	index_cpuZgpu_kr!   r"   Úis_binary_indexr   r   r    r   r   Út1Út2r@   r=   Úxbr>   rA   ZCombinerRangeKNNZcombinerÚspZL_resÚnresZD_resZI_resÚt3r'   r'   r(   Úrange_search_gpu:   sp    	
 ÿ




þ





$rM   c                    s  | j \}}t ¡ }tj| dd} t ||¡}	|dkr<t ¡ }|rlt d| ¡ t 	¡ }
||
_
tj|	|
|d}d}dd„ t|ƒD ƒ}d	d„ t|ƒD ƒ}|D ]è}|j d }|dkrÖ| |¡ t| |||ƒ\}}}| ¡  n$|	 |¡ |	 | |¡\}}}|	 ¡  ||7 }t|ƒD ]R}|| ||d
   }}||kr
||  |||… ¡ ||  |||… ¡ q
||7 }t d|t ¡ | f ¡ q˜tjddd‰tjddd‰ ‡ fdd„|D ƒ}‡fdd„|D ƒ}dd„ |D ƒ}t|ƒ|ksâJ ‚tj|d
 dd}t |¡|d
d…< |t |¡t |¡fS )z§Computes the range-search search results for a dataset that possibly
    does not fit in RAM but for which we have an iterator that
    returns it block by block.
    Úfloat32r0   r   r   r   r   c                 S   s   g | ]}g ‘qS r'   r'   ©Ú.0Z_ir'   r'   r(   Ú
<listcomp>­   ó    z&range_ground_truth.<locals>.<listcomp>c                 S   s   g | ]}g ‘qS r'   r'   rO   r'   r'   r(   rQ   ®   rR   r-   r	   r/   c                    s"   g | ]}|g krt  |¡nˆ ‘qS r'   ©r;   Úhstack©rP   Úi)Úempty_Dr'   r(   rQ   Å   rR   c                    s"   g | ]}|g krt  |¡nˆ ‘qS r'   rS   rU   )Úempty_Ir'   r(   rQ   Æ   rR   c                 S   s   g | ]}t |ƒ‘qS r'   ©ÚlenrU   r'   r'   r(   rQ   Ç   rR   Úuint64N)r   r   r;   Zascontiguousarrayr   r   r   r
   r   r   r   r   rC   r   rM   r   r<   ÚappendÚzerosrZ   ÚcumsumrT   )r   r   Ú	thresholdr   r   r   r!   r"   r    r#   r   rE   r$   r   r   r%   r&   Úlims_iÚDiÚIiÚjÚl0Úl1ÚsizesÚlimsr'   )rW   rX   r(   Úrange_ground_truth˜   sP    





rh   c           
      C   sp   |r||k}n||k }t  | ¡}d}t| ƒD ]0\}}	t|	ƒ}	||||	 …  ¡ ||< ||	7 }q,||| || fS )z select a set of results r   )r;   Ú
zeros_likeÚ	enumerater5   r:   )
rK   ÚdisÚidsÚthreshr   r=   Znew_nresÚorV   Únrr'   r'   r(   Úthreshold_radius_nresÎ   s    


rp   c                 C   s‚   |r||k}n||k }t  | ¡}t| ƒd }t|ƒD ]:}| | | |d   }	}
|| ||	|
…  ¡  ||d < q4||| || fS )z= restrict range-search results to those below a given radius r-   )r;   ri   rZ   rC   r:   )rg   rk   rl   rm   r   r=   Znew_limsÚnrV   rd   re   r'   r'   r(   Úthreshold_radiusÝ   s    

"rr   c           
      C   sì   t  dd„ | D ƒ¡}t|ƒ|ks$J ‚|rL| t|ƒ| d ¡ |d|  }n| |¡ || }|jdkrrt|ƒ}nt|ƒ}t d| ¡ d}t	| ƒD ]@\}\}}}	t
|||	||d\}}}	|t|ƒ7 }|||	f| |< q”t d	| ¡ ||fS )
z‘find radius that reduces number of results to target_nres, and
    applies it in-place to the result batches used in
    range_search_max_resultsc                 S   s   g | ]\}}}|‘qS r'   r'   )rP   Ú_rk   r'   r'   r(   rQ   ï   rR   z apply_maxres.<locals>.<listcomp>r-   r   rN   z   setting radius to %sr   r   z.   updated previous results, new nb results %d)r;   rT   rZ   Ú	partitionr1   r6   r5   r
   r8   rj   rp   )
Úres_batchesZtarget_nresr   ZalldisÚradiusÚtotresrV   rK   rk   rl   r'   r'   r(   Úapply_maxresë   s(    



ÿrx   c                 C   s˜  t | tjƒ}|du r,|dus J ‚td| ƒ}|du rL|dus@J ‚t|d ƒ}|dkr\t ¡ }|rŽt d| ¡ t ¡ }	||	_tj	| |	|d}
nd}
t
 
¡ }d }}d } }}g }|D ].}t
 
¡ }t dt|ƒ› d	¡ |
rôt|||
| ƒ\}}}n|  ||¡\}}}|d
d… |dd…  }|t|ƒ7 }|t|ƒ7 }t
 
¡ }|rN| d¡}|t|ƒ7 }| |||f¡ |durª||krªt d||f ¡ t||| jtjkd\}}t
 
¡ }||| 7 }||| 7 }t dt
 
¡ | ||f ¡ q¶t d||||f ¡ |r(||kr(t||| jtjkd\}}t dd„ |D ƒ¡}t dd„ |D ƒ¡}t dd„ |D ƒ¡}tjt|ƒd
 dd}t |¡|d
d…< ||||fS )a  Performs a range search with many queries (given by an iterator)
    and adjusts the threshold on-the-fly so that the total results
    table does not grow larger than max_results.

    If ngpu != 0, the function moves the index to this many GPUs to
    speed up search.
    Ngš™™™™™é?g      ø?r   r   r   r   z
searching z vectorsr-   r,   z-too many results %d > %d, scaling back radiusr   z'   [%.3f s] %d queries done, %d resultszBsearch done in %.3f s + %.3f s, total %d results, end threshold %gc                 S   s   g | ]\}}}|‘qS r'   r'   ©rP   Únres_iZdis_iZids_ir'   r'   r(   rQ   Y  rR   z,range_search_max_results.<locals>.<listcomp>c                 S   s   g | ]\}}}|‘qS r'   r'   ry   r'   r'   r(   rQ   Z  rR   c                 S   s   g | ]\}}}|‘qS r'   r'   ry   r'   r'   r(   rQ   [  rR   r[   r0   )r3   r   r4   r5   r   r
   r   r   r   r   r   r8   rZ   rM   r<   r9   r\   rx   r   ZMETRIC_INNER_PRODUCTr;   rT   r]   r^   )r#   Zquery_iteratorrv   Zmax_resultsZmin_resultsr   r   Zclip_to_minrF   r   rE   Zt_startZt_searchZt_post_processZqtotrw   Z
raw_totresru   Úxqir    r`   ra   rb   rz   rG   rH   rK   rk   rl   rg   r'   r'   r(   Úrange_search_max_results  s~    

ÿ
þ
ÿ
ÿÿ
þ
r|   é    é N  c                 c   sP   t | ƒ}|}d}||k rL| ||| … }|V  ||k r>|d9 }|t |ƒ7 }qdS )z¤ produces batches of progressively increasing sizes. This is useful to
    adjust the search radius progressively without overflowing with
    intermediate results r   é   NrY   )r   Zstart_bsZmax_bsr!   ÚbsrV   r{   r'   r'   r(   Úexponential_query_iteratorc  s    r   )r*   )F)F)F)NNFr   F)r}   r~   )r   r   Únumpyr;   ÚloggingÚ	getLoggerÚ__name__r
   Z	METRIC_L2r)   ZknnrM   rh   rp   rr   rx   r|   r   r'   r'   r'   r(   Ú<module>   s"   
'
^ÿ
6


  þ
\