o
    -ѹg                     @   sX  d dl mZ d dlZd dlZd dlZd dlZd dlm	Z	m
Z
mZmZmZ d dlmZmZ d dlZd dlmZ eejd dZeejjd Zeejjd Zed	g d
Zejddd Zej dddddf Z!ej"ddd Z#ej Z$e%ededfZ&ejddd Z'ej(dd e)dD ejdZ*ej+ej,-ejddd ejddd ee$fejdddddf ejddd ej.ddd ej/ej/ejddd ejejej/ej/ej/ej/d	dddddd Z0ej+ej,-ejddd ejddd e#e$fej"dddddf ejddd ej.ddd ej/ej/ej"ddd ejejej/ej/ej/ej/d	dddddd Z1ej+ej,-ejddd ejddd ee$fejdddddf ejddd ej.ddd ej/ej/ejddd ejejej/ej/ej/ej/d	dddddd Z2ej+dddej,jddd ej,jddd ej,jej,j/dddd Z3ej+dddddd Z4ej+dej,jej,jd d!	"	#dmd$d%Z5ej+dej,6e&ej,jej,jd&d!	"	#dmd'd(Z7ej+dej,6e&ej,jej,jd&d!	"	#dmd)d*Z8ej+dej,jej,jd d!	"	#dmd+d,Z9ej+dej,jej,jd d!	"	#dmd-d.Z:ej+dd/dnd1d2Z;ej+dd/	"	0	#dnd3d4Z<ej+dd/dnd5d6Z=ej+d7ej,>ej,j?ej,jdddd8ej,jej,j?ej,jdddd8ej,j?ej,j.ddd0d8gdej,jej,j@ej,jAd9dd:d;d< ZBej+d=ej,>ej,j?ej,j"dddd8ej,jej,j?ej,j"dddd8ej,j?ej,j.ddd0d8gdej,jej,j@ej,jAd9dd:d>d? ZCej+d@ej,j?ej,jdddd8ej,j?ej,jdddd8ej,j?ej,jdAddd8ej,j?ej,jdddd8ej,j?ej,jdAddd8ej,j?ej,jdddd8ej,j?ej,j.ddd0d8gej,j/ej,j>dBddCdDdE ZDej+dFej,j?ej,jdddd8ej,j?ej,j"dddd8ej,j?ej,j"dAddd8ej,j?ej,jdddd8ej,j?ej,jdAddd8ej,j?ej,jdddd8ej,j?ej,j.ddd0d8gej,j/ej,j>dBddCdGdH ZEej+dddIdJdK ZFej+dLej,j/iddCdMdN ZG		0	0	#dodOdPZHej+dd/dQdR ZIdSdT ZJdUdV ZKdWdX ZLe+ dYdZ ZMej+dd[d\d] ZNd^d_ ZOd ZPdZQdAZRd`ZSdaZTdbdc ZUddde ZVej+dej.ddd ejej/dfd0dgdhdi ZWej+ddLejid0djdkdl ZXdS )p    )warnN)
sparse_mulsparse_diff
sparse_sumarr_intersectsparse_dot_product)tau_rand_intnorm)
namedtupleCg:0yE>   FlatTreehyperplanesoffsetschildrenindices	leaf_sizec                 C   s   g | ]	}t |d qS )1)bincount.0i r   X/Users/admin/.pyenv/versions/3.10.0/lib/python3.10/site-packages/pynndescent/rp_trees.py
<listcomp>*   s    r      dtype)	n_leftn_righthyperplane_vectorhyperplane_offsetmargindr   
left_indexright_indexT)localsfastmathnogilcachec                 C   s  | j d }t||j d  }t||j d  }|||k7 }||j d  }|| }|| }t| | }t| | }	t|tk r@d}t|	tk rHd}	tj|tjd}
t|D ]}| ||f | | ||f |	  |
|< qTt|
}t|tk rud}t|D ]
}|
| | |
|< qyd}d}t|j d tj	}t|j d D ]L}d}t|D ]}||
| | || |f  7 }qt|tk rt|d ||< || dkr|d7 }q|d7 }q|dkrd||< |d7 }qd||< |d7 }q|dks|dkrd}d}t|j d D ]}t|d ||< || dkr|d7 }q|d7 }qtj|tj
d}tj|tj
d}d}d}t|j d D ] }|| dkrE|| ||< |d7 }q0|| ||< |d7 }q0|||
dfS )M  Given a set of ``graph_indices`` for graph_data points from ``graph_data``, create
    a random hyperplane to split the graph_data, returning two arrays graph_indices
    that fall on either side of the hyperplane. This is the basis for a
    random projection tree, which simply uses this splitting recursively.
    This particular split uses cosine distance to determine the hyperplane
    and which side each graph_data sample falls on.
    Parameters
    ----------
    data: array of shape (n_samples, n_features)
        The original graph_data to be split
    indices: array of shape (tree_node_size,)
        The graph_indices of the elements in the ``graph_data`` array that are to
        be split in the current operation.
    rng_state: array of int64, shape (3,)
        The internal state of the rng
    Returns
    -------
    indices_left: array
        The elements of ``graph_indices`` that fall on the "left" side of the
        random hyperplane.
    indices_right: array
        The elements of ``graph_indices`` that fall on the "left" side of the
        random hyperplane.
    r   r         ?r              N)shaper   r	   absEPSnpemptyfloat32rangeint8int32)datar   	rng_statedimr'   r(   leftright	left_norm
right_normr#   r&   hyperplane_normr!   r"   sider   r%   indices_leftindices_rightr   r   r   angular_random_projection_split.   sv   
,






rE   c                 C   s  | j d }t||j d  }t||j d  }|||k7 }||j d  }|| }|| }d}d}	tj|d tjd}
|
d| }|
|d }t|D ]"}| ||f | ||f A }|| ||f @ ||< || ||f @ ||< qJd}t|D ]}|t|
|  7 }|t| ||f  7 }|	t| ||f  7 }	qsd}d}t|j d tj}t|j d D ]^}d}t|D ]"}|t|| | || |f @  7 }|t|| | || |f @  8 }qt|t	k rt|d ||< || dkr|d7 }q|d7 }q|dkrd||< |d7 }qd||< |d7 }q|dks|dkr8d}d}t|j d D ]}t|d ||< || dkr2|d7 }q|d7 }qtj|tj
d}tj|tj
d}d}d}t|j d D ] }|| dkrh|| ||< |d7 }qS|| ||< |d7 }qS|||
dfS )r-   r   r   r/   r0   r   N)r1   r   r4   r5   uint8r7   popcntr8   r2   r3   r9   )r:   r   r;   r<   r'   r(   r=   r>   r?   r@   r#   Zpositive_hyperplane_componentZnegative_hyperplane_componentr&   Z
xor_vectorrA   r!   r"   rB   r   r%   rC   rD   r   r   r   )angular_bitpacked_random_projection_split   st   
, "



rH   c                 C   sd  | j d }t||j d  }t||j d  }|||k7 }||j d  }|| }|| }d}tj|tjd}	t|D ]$}
| ||
f | ||
f  |	|
< ||	|
 | ||
f | ||
f   d 8 }q:d}d}t|j d tj}t|j d D ]N}|}t|D ]}
||	|
 | || |
f  7 }q|t|tk rtt|d ||< || dkr|d7 }qt|d7 }qt|dkrd||< |d7 }qtd||< |d7 }qt|dks|dkrd}d}t|j d D ]}t|d ||< || dkr|d7 }q|d7 }qtj|tj	d}tj|tj	d}d}d}t|j d D ] }|| dkr || ||< |d7 }q|| ||< |d7 }q|||	|fS )aP  Given a set of ``graph_indices`` for graph_data points from ``graph_data``, create
    a random hyperplane to split the graph_data, returning two arrays graph_indices
    that fall on either side of the hyperplane. This is the basis for a
    random projection tree, which simply uses this splitting recursively.
    This particular split uses euclidean distance to determine the hyperplane
    and which side each graph_data sample falls on.
    Parameters
    ----------
    data: array of shape (n_samples, n_features)
        The original graph_data to be split
    indices: array of shape (tree_node_size,)
        The graph_indices of the elements in the ``graph_data`` array that are to
        be split in the current operation.
    rng_state: array of int64, shape (3,)
        The internal state of the rng
    Returns
    -------
    indices_left: array
        The elements of ``graph_indices`` that fall on the "left" side of the
        random hyperplane.
    indices_right: array
        The elements of ``graph_indices`` that fall on the "left" side of the
        random hyperplane.
    r   r   r/   r          @r0   N)
r1   r   r4   r5   r6   r7   r8   r2   r3   r9   )r:   r   r;   r<   r'   r(   r=   r>   r$   r#   r&   r!   r"   rB   r   r%   rC   rD   r   r   r   !euclidean_random_projection_split5  sd   
,"





rJ   )normalized_left_datanormalized_right_datarA   r   )r*   r+   r,   r)   c           "      C   sF  t ||jd  }t ||jd  }|||k7 }||jd  }|| }|| }| || ||d   }	||| ||d   }
| || ||d   }||| ||d   }t|
}t|}t|tk rgd}t|tk rod}|
| tj}|| tj}t|	|||\}}t|}t|tk rd}t	|jd D ]
}|| | ||< qd}d}t
|jd tj}t	|jd D ]l}d}| |||  ||| d   }||||  ||| d   }t||||\}}|D ]}||7 }qt|tk rt |d ||< || dkr|d7 }q|d7 }q|dkrd||< |d7 }qd||< |d7 }q|dks2|dkrZd}d}t	|jd D ]}t |d ||< || dkrT|d7 }q=|d7 }q=tj
|tjd}tj
|tjd} d}d}t	|jd D ] }|| dkr|| ||< |d7 }qu|| | |< |d7 }qut||f}!|| |!dfS )  Given a set of ``graph_indices`` for graph_data points from a sparse graph_data set
    presented in csr sparse format as inds, graph_indptr and graph_data, create
    a random hyperplane to split the graph_data, returning two arrays graph_indices
    that fall on either side of the hyperplane. This is the basis for a
    random projection tree, which simply uses this splitting recursively.
    This particular split uses cosine distance to determine the hyperplane
    and which side each graph_data sample falls on.
    Parameters
    ----------
    inds: array
        CSR format index array of the matrix
    indptr: array
        CSR format index pointer array of the matrix
    data: array
        CSR format graph_data array of the matrix
    indices: array of shape (tree_node_size,)
        The graph_indices of the elements in the ``graph_data`` array that are to
        be split in the current operation.
    rng_state: array of int64, shape (3,)
        The internal state of the rng
    Returns
    -------
    indices_left: array
        The elements of ``graph_indices`` that fall on the "left" side of the
        random hyperplane.
    indices_right: array
        The elements of ``graph_indices`` that fall on the "left" side of the
        random hyperplane.
    r   r   r.   r/   r0   r   N)r   r1   r	   r2   r3   astyper4   r6   r   r7   r5   r8   r   r9   vstack)"indsindptrr:   r   r;   r'   r(   r=   r>   	left_inds	left_data
right_inds
right_datar?   r@   rK   rL   hyperplane_indshyperplane_datarA   r&   r!   r"   rB   r   r%   i_indsi_data_mul_datavalrC   rD   
hyperplaner   r   r   &sparse_angular_random_projection_split  s   *  





r^   )r*   r+   r,   c                 C   s  t t||jd  }t t||jd  }|||k7 }||jd  }|| }|| }| || ||d   }	||| ||d   }
| || ||d   }||| ||d   }d}t|	|
||\}}t|	|
||\}}|d }t||||t j\}}|D ]}||8 }qd}d}t 	|jd t j
}t|jd D ]l}|}| |||  ||| d   }||||  ||| d   }t||||\}}|D ]}||7 }qt|tk rtt|d ||< || dkr|d7 }q|d7 }q|dkrd||< |d7 }qd||< |d7 }q|dks|dkrAd}d}t|jd D ]}tt|d ||< || dkr;|d7 }q"|d7 }q"t j	|t jd}t j	|t jd}d}d}t|jd D ] }|| dkrq|| ||< |d7 }q\|| ||< |d7 }q\t ||f}||||fS )rM   r   r   r/   rI   r0   r   N)r4   r2   r   r1   r   r   r   rN   r6   r5   r8   r7   r3   r9   rO   )rP   rQ   r:   r   r;   r'   r(   r=   r>   rR   rS   rT   rU   r$   rV   rW   Zoffset_indsoffset_datar\   r!   r"   rB   r   r%   rX   rY   rZ   r[   rC   rD   r]   r   r   r   (sparse_euclidean_random_projection_split6  sz    
  





r`   )left_node_numright_node_num)r+   r)         c	                 C     |j d |krb|dkrbt| ||\}	}
}}t| |	|||||||d 	 t|d }t| |
|||||||d 	 t|d }|| || |t|t|f |tjdgtjd d S |tjdgtjd |tj	  |tdtdf || d S Nr   r   r   r   g      )
r1   rJ   make_euclidean_treelenappendr4   r9   arrayr6   infr:   r   r   r   r   point_indicesr;   r   	max_depthleft_indicesright_indicesr]   offsetra   rb   r   r   r   rg     sR   



rg   )r   ra   rb   c	                 C   re   rf   )
r1   rE   make_angular_treerh   ri   r4   r9   rj   r6   rk   rl   r   r   r   rr     R   



rr   c	                 C   re   )Nr   r   r   r      )
r1   rH   make_bit_treerh   ri   r4   r9   rj   rF   rk   rl   r   r   r   ru   0  rs   ru   c                 C   $  |j d |	krh|
dkrht| ||||\}}}}t| |||||||||	|
d  t|d }t| |||||||||	|
d  t|d }|| || |t|t|f |tjdgtjd d S |tjdgdggtjd |tj	  |tdtdf || d S rf   )
r1   r`   make_sparse_euclidean_treerh   ri   r4   r9   rj   float64rk   rP   rQ   r:   r   r   r   r   rm   r;   r   rn   ro   rp   r]   rq   ra   rb   r   r   r   rw   t  s^   



rw   c                 C   rv   rf   )
r1   r^   make_sparse_angular_treerh   ri   r4   r9   rj   rx   rk   ry   r   r   r   rz     sZ   


rz   )r+   Fc                 C   s   t | jd t j}tjjt	}tjjt
}tjjt}tjjt}	|r8t| |||||	|||d	 nt| |||||	|||d	 |}
|	D ]}t||
krXtt|}
qIt||||	|
}|S )Nr   rn   )r4   aranger1   rN   r9   numbatypedList
empty_listdense_hyperplane_typeoffset_typechildren_typepoint_indices_typerr   rg   rh   r   r:   r;   r   angularrn   r   r   r   r   rm   max_leaf_sizepointsresultr   r   r   make_dense_tree  sF   r   c                 C   s   t |jd d t j}tjjt	}tjjt
}	tjjt}
tjjt}|r<t| |||||	|
||||d nt| |||||	|
||||d |}|D ]}t||kr^tt|}qOt||	|
||S )Nr   r   r{   )r4   r|   r1   rN   r9   r}   r~   r   r   sparse_hyperplane_typer   r   r   rz   rw   rh   r   )rP   rQ   Zspdatar;   r   r   rn   r   r   r   r   rm   r   r   r   r   r   make_sparse_tree,  sL   
r   c                 C   s   t | jd t j}tjjt	}tjjt
}tjjt}tjjt}	|r8t| |||||	|||d	 ntd|}
|	D ]}t||
krOtt|}
q@t||||	|
}|S )Nr   r{   z,Euclidean bit trees are not implemented yet.)r4   r|   r1   rN   r9   r}   r~   r   r   bit_hyperplane_typer   r   r   ru   NotImplementedErrorrh   r   r   r   r   r   make_dense_bit_treeb  s2   r   zb1(f4[::1],f4,f4[::1],i8[::1]))readonly)r%   r<   r&   )r*   r)   r,   c                 C   sn   |}|j d }t|D ]}|| | ||  7 }qt|tk r/tt|d }|dkr-dS dS |dkr5dS dS Nr   r0   r   )r1   r7   r2   r3   r4   r   r]   rq   pointr;   r%   r<   r&   rB   r   r   r   select_side  s   
r   zb1(u1[::1],f4,u1[::1],i8[::1])c                 C   s   |}|j d }t|D ]}|t| | || @  7 }|t| ||  || @  8 }qt|tk r?tt|d }|dkr=dS dS |dkrEdS dS r   )r1   r7   rG   r2   r3   r4   r   r   r   r   r   select_side_bit  s   
r   z<i4[::1](f4[::1],f4[:,::1],f4[::1],i4[:,::1],i4[::1],i8[::1])r0   )noderB   )r)   r,   c                 C   |   d}||df dkr.t || || | |}|dkr ||df }n||df }||df dks
|||df  ||df   S Nr   r   )r   r   r   r   r   r   r;   r   rB   r   r   r   search_flat_tree      r   z<i4[::1](u1[::1],u1[:,::1],f4[::1],i4[:,::1],i4[::1],i8[::1])c                 C   r   r   )r   r   r   r   r   search_flat_bit_tree  r   r   )r*   r,   c           
      C   s   |}| j d }| d|d f dk r|d8 }| d|d f dk s| dd |f tj}| dd |f }|t||||7 }t|tk rPt|d }	|	dkrNdS dS |dkrVdS dS )Nr   r   r/   r0   )r1   rN   r4   r9   r   r2   r3   r   )
r]   rq   
point_inds
point_datar;   r%   Zhyperplane_sizerV   rW   rB   r   r   r   sparse_select_side   s$   
r   r   c           	      C   s~   d}||df dkr/t || || | ||}|dkr!||df }n||df }||df dks
|||df  ||df   S r   )r   )	r   r   r   r   r   r   r;   r   rB   r   r   r   search_sparse_flat_tree  s    	r   c
              
      s"  g }
du rt dt||du rd}|jtt|dfdtjz[tj	
r@tj|dd fdd	t|D }
n4|rYtj|dd fd
d	t|D }
n tj|dd fdd	t|D }
W t|
S W t|
S W t|
S  tttfy   td Y t|
S w )zBuild a random projection forest with ``n_trees``.

    Parameters
    ----------
    data
    n_neighbors
    n_trees
    leaf_size
    rng_state
    angular

    Returns
    -------
    forest: list
        A list of random projection trees.
    N
   r      )size	sharedmemn_jobsrequirec              
   3   s6    | ]}t tjjj|  d V  qdS r{   N)joblibdelayedr   r   rQ   r:   r   r   r:   r   rn   Z
rng_statesr   r   	<genexpr>T  s    

zmake_forest.<locals>.<genexpr>c                 3   ,    | ]}t t|  d V  qdS r   )r   r   r   r   r   r   r   r   a      
c                 3   r   r   )r   r   r   r   r   r   r   r   l  r   zRandom Projection forest initialisation failed due to recursionlimit being reached. Something is a little strange with your graph_data, and this may take longer than normal to compute.)maxr4   r9   randint	INT32_MIN	INT32_MAXrN   int64scipysparseZisspmatrix_csrr   Parallelr7   RuntimeErrorRecursionErrorSystemErrorr   tuple)r:   Zn_neighborsZn_treesr   r;   Zrandom_stater   r   Zbit_treern   r   r   r   r   make_forest,  s>   



)r   c                 C   s   d}t t| jD ]}| j| d dkr!| j| d dkr!|d7 }q	tj||fdtjd}d}t t| jD ]+}| j| d dksJ| j| d dkra| j| jd }| j| ||d |f< |d7 }q6|S )Nr   r   r   r   )r7   rh   r   r4   fullr9   r   r1   )treer   n_leavesr   r   Z
leaf_indexr   r   r   r   get_leaves_from_tree  s   $$r   c                    s8   t dd | D  tjddd fdd| D }|S )Nc                 S   s   g | ]}|j qS r   )r   r   Zrp_treer   r   r   r     s    z.rptree_leaf_array_parallel.<locals>.<listcomp>r   r   r   c                 3   s     | ]}t t| V  qd S N)r   r   r   r   r   r   r   r     s    
z-rptree_leaf_array_parallel.<locals>.<genexpr>)r4   r   r   r   )	rp_forestr   r   r   r   rptree_leaf_array_parallel  s
   r   c                 C   s(   t | dkrtt| S tdggS )Nr   r   )rh   r4   rO   r   rj   )r   r   r   r   rptree_leaf_array  s   r   c           
   
   C   s   | j | d dk r-|t| j|  }| ||df< | ||df< | j| |||< ||fS | j| ||< | j| ||< |d ||df< |}	t| |||||d || j | d \}}|d ||	df< t| |||||d || j | d \}}||fS r   )r   rh   r   r   r   recursive_convert
r   r   r   r   r   Znode_numZ
leaf_startZ	tree_nodeZleaf_endZold_node_numr   r   r   r     s@   

r   c           
   
   C   s  | j | d dk r-|t| j|  }| ||df< | ||df< | j| |||< ||fS | j| ||d d d | j| jd f< | j| ||< |d ||df< |}	t| |||||d || j | d \}}|d ||	df< t| |||||d || j | d \}}||fS r   )r   rh   r   r   r1   r   recursive_convert_sparser   r   r   r   r     sF   

r   )r,   c                 C   sP   d}d}t t| jD ]}| j| d dk r|d7 }|d7 }q|d7 }q||fS r   )r7   rh   r   )r   n_nodesr   r   r   r   r   num_nodes_and_leaves  s   

r   c              
   C   s0  t | \}}d}| jd jdkr.| jd jtjkr|d }n|}tj||f| jd jd}nd}|}tj|d|ftjd}d|d d dd d f< tj|tjd}tdtj	|dftjd }	tdtj	|tjd }
|rt
| |||	|
ddt| jd  nt| |||	|
ddt| jd  t|||	|
| jS )NFr   r   r0   r   Tr   )r   r   ndimr    r4   rF   zerosr6   r9   Zonesr   rh   r   r   r   r   )r   	data_sizeZdata_dimr   r   Z	is_sparseZhyperplane_dimr   r   r   r   r   r   r   convert_tree_format  s,   
r   r      c                 C   s   | j | j| j| j| jf}|S r   r   r   r   r   r   r   denumbaify_tree&  s   r   c                 C   s(   t | t | t | t | t | t }|S r   )r   FLAT_TREE_HYPERPLANESFLAT_TREE_OFFSETSFLAT_TREE_CHILDRENFLAT_TREE_INDICESFLAT_TREE_LEAF_SIZEr   r   r   r   renumbaify_tree2  s   r   )intersectionr   r   )parallelr)   r,   c                 C   sr   d}t |jd D ]$}t|| | j| j| j| j|}t|| |}|t 	|jd dk7 }q
|t 	|jd  S )Nr/   r   r   )
r}   Zpranger1   r   r   r   r   r   r   r6   )r   neighbor_indicesr:   r;   r   r   Zleaf_indicesr   r   r   r   
score_tree>  s   
r   )r+   r)   r,   c                 C   s   d}t | j}t|D ]G}t|}| j| d }| j| d }|dkrR|dkrRt| j| jd D ]}| j| | }	t||	 | j| }
|t|
jd dk7 }q2q|t|jd  S )Nr/   r   r   r   )	rh   r   r7   r}   r9   r   r1   r   r6   )r   r   r   r   r   r   Z
left_childZright_childjidxr   r   r   r   score_linked_treeW  s   

r   )rc   rd   )rc   Frd   )NFFrd   )Ywarningsr   localeZnumpyr4   r}   Zscipy.sparser   Zpynndescent.sparser   r   r   r   r   Zpynndescent.utilsr   r	   r   collectionsr
   	setlocale
LC_NUMERICr3   Ziinfor9   minr   r   r   r   r6   r   rx   r   rF   r   r   Ztypeofr   r   rj   r7   rG   ZnjittypesTupler   Zuint32rE   rH   rJ   r^   r`   rg   ZListTyperr   ru   rw   rz   r   r   r   booleanArrayZintpZuint16r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s  "2
r"2
o"2
d

v<
;
<D
B
)
5	
	






T
&

(
 
	