
    yj)                        d Z ddlmZ ddlmZmZ ddlZddlm	Z	 ddl
mZ erddlmZ ddZddZ G d de          ZdS )z=
Graph-theoretic surprisal using k-NN graph and random walk.
    )annotations)TYPE_CHECKINGAnyN)NDArray   )SurprisalTreeNearestNeighborspointsNDArray[np.floating[Any]]n_neighborsintreturnNDArray[np.intp]c                    ddl m}  ||d          }|                    |            |                    |           \  }}|S )z.Get k-nearest neighbor indices for each point.r   r	   auto)r   	algorithm)sklearn.neighborsr
   fit
kneighbors)r   r   r
   knn
_distancesindicess         ?/DATA/AppData/hermes/projects/honcho/src/dreamer/trees/graph.py_knn_indicesr      sV     322222,,PVWWWCGGFOOO..00JN    query
np.ndarrayc                    ddl m}  |d          }|                    |            |                    |g          \  }}t	          |d                   S )z%Find index of nearest point to query.r   r	   r   )r   )r   r   )r   r
   r   r   r   )r   r   r
   r   r   r   s         r   _nearest_indexr       s`    222222,,;;;CGGFOOO..%11Jwt}r   c                       e Zd ZU dZded<   ded<   ded<   ded<   d	ed
<   ded<   	 dd fdZddZddZddZddZ	 xZ
S ) GraphSurprisalz
    Graph-theoretic surprisal using k-NN graph and random walk.
    Surprisal based on stationary distribution of random walk.
    r   kmax_iterzlist[NDArray[np.floating[Any]]]r   z NDArray[np.floating[Any]] | Nonestationary_distboolgraph_builttotal_points   d   
   max_leaf_sizer   Nonec                    t                                          |           || _        || _        g | _        d | _        d| _        d S )NF)super__init__r#   r$   r   r%   r'   )selfr#   r$   r,   	__class__s       r   r0   zGraphSurprisal.__init__5   sH     	''' # r   pointr   c                h    | j                             |           | xj        dz  c_        d| _        d S )Nr   F)r   appendr(   r'   )r1   r3   s     r   insertzGraphSurprisal.insert?   s:    5!!!Q r   c                    | j                             |           | xj        t          |          z  c_        d| _        dS )zMore efficient batch insertion.FN)r   extendr(   lenr'   )r1   r   s     r   batch_insertzGraphSurprisal.batch_insertD   s@    6"""S[[( r   c                ,   t          | j                  dk     rdS t          j        | j                  }t	          | j        t          | j                  dz
            }t          ||dz             }t          | j                  }t          j        ||f          }t          |          D ])}||ddf         }|D ]}t          |          }	d|||	f<   *|
                    dd          }
t          |          D ]}|
|df         dk    rd|||f<   d|
|df<   ||
z  }t          j        |          |z  }t          | j                  D ]'}|j        |z  }t          j        ||d	          r n|}(||
                                z  | _        d| _        dS )
z5Build k-NN graph and compute stationary distribution.   Nr   g      ?T)axiskeepdimsr   gư>)atol)r9   r   nparrayminr#   r   zerosranger   sumonesr$   Tallcloser%   r'   )r1   points_arrayk_actualr   n
transitioni	neighborsj_idxjrow_sums
stationary_new_stationarys                 r   #_build_graph_and_compute_stationaryz2GraphSurprisal._build_graph_and_compute_stationaryJ   s   t{aF24(4;2G2Gtvs4;//!344|X\::Xq!f%%
q 	' 	'A*1!QRR%.I" ' 'U#&
1a4  ' >>q4>88q 	% 	%A1~""#&
1a4 !$A(*
02

Q
t}%% 	( 	(A8Bz8QN{>:DAAA 'JJ)JNN,<,<<r   floatc                J   | j         s|                                  | j        t          | j                  dk    rt          d          S t          j        | j                  }t          ||          }| j        |         }t          t          j	        |dz                        S )z
        Compute surprisal based on stationary distribution.
        Well-connected central facts = high probability = low surprisal
        Peripheral isolated facts = low probability = high surprisal
        Nr   infg|=)
r'   rU   r%   r9   r   rV   r@   rA   r    log)r1   r3   rI   nearest_idxprobs        r   	surprisalzGraphSurprisal.surprisalo   s      	744666'3t{+;+;q+@+@<<24(4;2G2G$\599#K0bfTE\***+++r   )r)   r*   r+   )r#   r   r$   r   r,   r   r   r-   )r3   r   r   r-   )r   r   r   r-   )r   r-   )r3   r   r   rV   )__name__
__module____qualname____doc____annotations__r0   r6   r:   rU   r\   __classcell__)r2   s   @r   r"   r"   (   s          
 FFFMMM++++5555 EG! ! ! ! ! ! !! ! ! !
! ! ! !#  #  #  # J, , , , , , , ,r   r"   )r   r   r   r   r   r   )r   r   r   r   r   r   )r`   
__future__r   typingr   r   numpyr@   numpy.typingr   baser   r   r
   r   r    r"    r   r   <module>ri      s     # " " " " " % % % % % % % %                       3222222	 	 	 	   X, X, X, X, X,] X, X, X, X, X,r   