a
    ­Àh\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ÚsearchZ
add_resultÚresetÚfinalizeÚDÚI)ÚxqÚdb_iteratorÚkÚmetric_typer   r   Út0ÚnqÚdr   ZrhÚindexr   Úi0ÚxbiÚnir   r   © r&   ú[/var/www/html/assistant/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_sizesr0   Zwrite_resultÚrange)r   Úr2Ú	index_gpuZ	index_cpuZgpu_kr    r!   Úis_binary_indexr   r   r   r   r   Út1Út2r?   r<   Úxbr=   r@   ZCombinerRangeKNNZcombinerÚspZL_resÚnresZD_resZI_resZt3r&   r&   r'   Úrange_search_gpu:   sp    	
 ÿ




þ





$rK   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.
    Úfloat32r/   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&   rM   r&   r&   r'   rO   ®   rP   r,   r	   r.   c                    s"   g | ]}|g krt  |¡nˆ ‘qS r&   ©r:   Úhstack©rN   Úi)Úempty_Dr&   r'   rO   Å   rP   c                    s"   g | ]}|g krt  |¡nˆ ‘qS r&   rQ   rS   )Úempty_Ir&   r'   rO   Æ   rP   c                 S   s   g | ]}t |ƒ‘qS r&   ©ÚlenrS   r&   r&   r'   rO   Ç   rP   Úuint64N)r   r   r:   Zascontiguousarrayr   r   r   r
   r   r   r   r   rB   r   rK   r   r;   ÚappendÚzerosrX   ÚcumsumrR   )r   r   Ú	thresholdr   r   r   r    r!   r   r"   r   rD   r#   r   r   r$   r%   Úlims_iÚDiÚIiÚjÚl0Úl1ÚsizesÚlimsr&   )rU   rV   r'   Úrange_ground_truth˜   sP    





rf   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Ú	enumerater4   r9   )
rJ   ÚdisÚidsÚthreshr   r<   Znew_nresÚorT   Únrr&   r&   r'   Úthreshold_radius_nresÎ   s    


rn   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:   rg   rX   rB   r9   )re   ri   rj   rk   r   r<   Znew_limsÚnrT   rb   rc   r&   r&   r'   Úthreshold_radiusÝ   s    

"rp   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&   )rN   Ú_ri   r&   r&   r'   rO   ï   rP   z apply_maxres.<locals>.<listcomp>r,   r   rL   z   setting radius to %sr   r   z.   updated previous results, new nb results %d)r:   rR   rX   Ú	partitionr0   r5   r4   r
   r7   rh   rn   )
Úres_batchesZtarget_nresr   ZalldisÚradiusÚtotresrT   rJ   ri   rj   r&   r&   r'   Úapply_maxresë   s(    



ÿrv   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&   ©rN   Únres_iZdis_iZids_ir&   r&   r'   rO   Y  rP   z,range_search_max_results.<locals>.<listcomp>c                 S   s   g | ]\}}}|‘qS r&   r&   rw   r&   r&   r'   rO   Z  rP   c                 S   s   g | ]\}}}|‘qS r&   r&   rw   r&   r&   r'   rO   [  rP   rY   r/   )r2   r   r3   r4   r   r
   r   r   r   r   r   r7   rX   rK   r;   r8   rZ   rv   r   ZMETRIC_INNER_PRODUCTr:   rR   r[   r\   )r"   Zquery_iteratorrt   Zmax_resultsZmin_resultsr   r   Zclip_to_minrE   r   rD   Zt_startZt_searchZt_post_processZqtotru   Z
raw_totresrs   Úxqir   r^   r_   r`   rx   rF   rG   rJ   ri   rj   re   r&   r&   r'   Úrange_search_max_results  s~    

ÿ
þ
ÿ
ÿÿ
þ
rz   é    é 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   é   NrW   )r   Zstart_bsZmax_bsr    ÚbsrT   ry   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knnrK   rf   rn   rp   rv   rz   r   r&   r&   r&   r'   Ú<module>   s"   
'
^ÿ
6


  þ
\