
    -ih                        S SK r S SKJr  S SKJrJr  S SKrS SKJ	r	  SSK
Jr  SSKJrJrJrJr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  SSKJr  SSKJrJ r   SSK!J"r"  S r#S r$ " S S5      r% " S S5      r& " S S\\\\5      r'g)    N)sqrt)IntegralReal)sparse   )config_context)BaseEstimatorClassNamePrefixFeaturesOutMixinClusterMixinTransformerMixin_fit_context)ConvergenceWarning)pairwise_distances_argmin)euclidean_distances)HiddenInterval
StrOptions)	row_norms)check_is_fittedvalidate_data   )AgglomerativeClusteringc              #     #    U R                   S   nU R                  nU R                  nU R                  n[	        U5       H>  n[
        R                  " U R                   S   5      nXE   XES-      pX'U n	X7U Xi'   Uv   M@     g7f)zThis little hack returns a densified row when iterating over a sparse
matrix, instead of constructing a sparse matrix for every row that is
expensive.
r   r   N)shapeindicesdataindptrrangenpzeros)
X	n_samples	X_indicesX_dataX_indptrirowstartptrendptrnonzero_indicess
             I/var/www/html/venv/lib/python3.13/site-packages/sklearn/cluster/_birch.py_iterate_sparse_Xr,      s     
 
I		IVVFxxH9hhqwwqz"#;Q&#V4%v6	 s   BBc                    [        5       n[        5       n[        UUU R                  U R                  U R                  R
                  S9n[        UUU R                  U R                  U R                  R
                  S9nXSl        Xdl        U R                  (       ah  U R                  b  XPR                  l        U R                  Ul        Xel        XVl        U R                  Ul        U R                  b  X`R                  l        [        U R                  U R                  SS9nUR                  S   n[        R                  " UR                  5       X45      n	Xy4   u  pX:  nSXS   '   [!        U R"                  5       HT  u  pX   (       a$  UR%                  U5        UR'                  U5        M2  UR%                  U5        UR'                  U5        MV     X44$ )a  The node has to be split if there is no place for a new subcluster
in the node.
1. Two empty nodes and two empty subclusters are initialized.
2. The pair of distant subclusters are found.
3. The properties of the empty subclusters and nodes are updated
   according to the nearest distance between the subclusters to the
   pair of distant subclusters.
4. The two nodes are set as children to the two subclusters.
	thresholdbranching_factoris_leaf
n_featuresdtypeT)Y_norm_squaredsquaredr   )_CFSubcluster_CFNoder1   r2   init_centroids_r3   child_
prev_leaf_
next_leaf_r   
centroids_squared_norm_r   r   unravel_indexargmax	enumeratesubclusters_append_subclusterupdate)noder/   r0   new_subcluster1new_subcluster2	new_node1	new_node2dist
n_clustersfarthest_idx
node1_dist
node2_distnode1_closeridx
subclusters                  r+   _split_noderQ   .   s    $oO#oO)??""((I )??""((I '&||??&)2OO&#	((#	??&)2OO&(:(:DD AJ##DKKMJ3KLL!/2J*L %)La!$T%6%67''
3"":.''
3"":. 8 ++    c                   0    \ rS rSrSrS rS rS rS rSr	g)	r7   m   a  Each node in a CFTree is called a CFNode.

The CFNode can have a maximum of branching_factor
number of CFSubclusters.

Parameters
----------
threshold : float
    Threshold needed for a new subcluster to enter a CFSubcluster.

branching_factor : int
    Maximum number of CF subclusters in each node.

is_leaf : bool
    We need to know if the CFNode is a leaf or not, in order to
    retrieve the final subclusters.

n_features : int
    The number of features.

Attributes
----------
subclusters_ : list
    List of subclusters for a particular CFNode.

prev_leaf_ : _CFNode
    Useful only if is_leaf is True.

next_leaf_ : _CFNode
    next_leaf. Useful only if is_leaf is True.
    the final subclusters.

init_centroids_ : ndarray of shape (branching_factor + 1, n_features)
    Manipulate ``init_centroids_`` throughout rather than centroids_ since
    the centroids are just a view of the ``init_centroids_`` .

init_sq_norm_ : ndarray of shape (branching_factor + 1,)
    manipulate init_sq_norm_ throughout. similar to ``init_centroids_``.

centroids_ : ndarray of shape (branching_factor + 1, n_features)
    View of ``init_centroids_``.

squared_norm_ : ndarray of shape (branching_factor + 1,)
    View of ``init_sq_norm_``.

c                    Xl         X l        X0l        X@l        / U l        [
        R                  " US-   U4US9U l        [
        R                  " US-   U5      U l        / U l	        S U l
        S U l        g )Nr   )r3   )r/   r0   r1   r2   rA   r   r    r8   init_sq_norm_r=   r:   r;   )selfr/   r0   r1   r2   r3   s         r+   __init___CFNode.__init__   so    " 0$ !xx)9A)=z(JRWXXX'7!';eDrR   c                 0   [        U R                  5      nU R                  R                  U5        UR                  U R                  U'   UR
                  U R                  U'   U R                  S US-   2S S 24   U l        U R                  S US-    U l        g )Nr   )	lenrA   append	centroid_r8   sq_norm_rV   r<   r=   )rW   rP   r"   s      r+   rB   _CFNode.append_subcluster   s    ))*	  ,*4*>*>Y'(2(;(;9%
 ..Q/AB!//)a-@rR   c                     U R                   R                  U5      nX R                   U'   UR                  U R                  U'   UR                  U R
                  U'   U R                  U5        g)zJRemove a subcluster from a node and update it with the
split subclusters.
N)rA   indexr]   r8   r^   rV   rB   )rW   rP   rE   rF   inds        r+   update_split_subclusters _CFNode.update_split_subclusters   sb     %%j1!0#$3$=$=S!"1":":3/rR   c                 0   U R                   (       d  U R                  U5        gU R                  nU R                  n[        R
                  " U R                  UR                  5      nUS-  nX@R                  -  n[        R                  " U5      nU R                   U   nUR                  b  UR                  R                  U5      nU(       d^  UR                  U5        U R                   U   R                  U R                  U'   U R                   U   R                  U R                  U'   g[!        UR                  UU5      u  pU R#                  XhU	5        [%        U R                   5      U R                  :  a  ggUR'                  XR                  5      n
U
(       a3  UR                  U R                  U'   UR                  U R                  U'   g[%        U R                   5      U R                  :  a  U R                  U5        gU R                  U5        g)z&Insert a new subcluster into the node.Fg       T)rA   rB   r/   r0   r   dotr<   r]   r=   argminr9   insert_cf_subclusterrC   r8   r^   rV   rQ   rc   r[   merge_subcluster)rW   rP   r/   r0   dist_matrixclosest_indexclosest_subclustersplit_childrE   rF   mergeds              r+   rh   _CFNode.insert_cf_subcluster   s     "":.NN	00 ffT__j.B.BCt)))		+.!..}= $$0,33HHTK #))*56:6G6G!7) $$]3 594E4E!5( ""=1  4?&--$40
 --& t(()D,A,AA (88^^TF6H6R6R$$]34F4O4O""=1 T&&'$*?*??&&z2
 &&z2rR   )r0   r<   r8   rV   r1   r2   r;   r:   r=   rA   r/   N)
__name__
__module____qualname____firstlineno____doc__rX   rB   rc   rh   __static_attributes__ rR   r+   r7   r7   m   s    -^
A0CrR   r7   c                   B    \ rS rSrSrSS.S jrS rS r\S 5       r	S	r
g)
r6   i  a&  Each subcluster in a CFNode is called a CFSubcluster.

A CFSubcluster can have a CFNode has its child.

Parameters
----------
linear_sum : ndarray of shape (n_features,), default=None
    Sample. This is kept optional to allow initialization of empty
    subclusters.

Attributes
----------
n_samples_ : int
    Number of samples that belong to each subcluster.

linear_sum_ : ndarray
    Linear sum of all the samples in a subcluster. Prevents holding
    all sample data in memory.

squared_sum_ : float
    Sum of the squared l2 norms of all samples belonging to a subcluster.

centroid_ : ndarray of shape (branching_factor + 1, n_features)
    Centroid of the subcluster. Prevent recomputing of centroids when
    ``CFNode.centroids_`` is called.

child_ : _CFNode
    Child Node of the subcluster. Once a given _CFNode is set as the child
    of the _CFNode, it is set to ``self.child_``.

sq_norm_ : ndarray of shape (branching_factor + 1,)
    Squared norm of the subcluster. Used to prevent recomputing when
    pairwise minimum distances are computed.
N
linear_sumc                    Uc  SU l         SU l        S=U l        U l        OLSU l         U=U l        U l        [        R
                  " U R                  U R                  5      =U l        U l        S U l        g )Nr           r   )
n_samples_squared_sum_r]   linear_sum_r   rf   r^   r9   )rW   ry   s     r+   rX   _CFSubcluster.__init__,  sp    DO #D011DNT-DO0::DNT-02  $"2"21 D rR   c                 Z   U =R                   UR                   -  sl         U =R                  UR                  -  sl        U =R                  UR                  -  sl        U R                  U R                   -  U l        [        R
                  " U R                  U R                  5      U l        g N)r|   r~   r}   r]   r   rf   r^   )rW   rP   s     r+   rC   _CFSubcluster.update9  st    :000J222Z444))DOO;t~~t~~>rR   c                 >   U R                   UR                   -   nU R                  UR                  -   nU R                  UR                  -   nSU-  U-  n[        R                  " Xf5      nX5-  U-
  nXS-  ::  a%  XTX6U4u  U l        U l        U l         U l        U l        gg)zECheck if a cluster is worthy enough to be merged. If
yes then merge.
r   r   TF)r}   r~   r|   r   rf   r]   r^   )	rW   nominee_clusterr/   new_ssnew_lsnew_nnew_centroidnew_sq_norm	sq_radiuss	            r+   ri   _CFSubcluster.merge_subcluster@  s     ""_%A%AA!!O$?$??/"<"<<E	V+ff\8 N[0	1$ kB !rR   c                 x    U R                   U R                  -  U R                  -
  n[        [	        SU5      5      $ )zReturn radius of the subclusterr   )r}   r|   r^   r   max)rW   r   s     r+   radius_CFSubcluster.radius_  s3     %%7$--G	C9%&&rR   )r]   r9   r~   r|   r^   r}   )rp   rq   rr   rs   rt   rX   rC   ri   propertyr   ru   rv   rR   r+   r6   r6     s0    !F &* ?> ' 'rR   r6   c                     ^  \ rS rSr% Sr\" \SSSS9/\" \SSSS9/S\\" \SSSS9/S	/S	\	" \
" S
15      5      /S.r\\S'   SSSSS
S.S jr\" SS9SS j5       rS rS r\" SS9SS j5       rS rS rS rSS jrU 4S jrSrU =r$ )Birchig  a?  Implements the BIRCH clustering algorithm.

It is a memory-efficient, online-learning algorithm provided as an
alternative to :class:`MiniBatchKMeans`. It constructs a tree
data structure with the cluster centroids being read off the leaf.
These can be either the final cluster centroids or can be provided as input
to another clustering algorithm such as :class:`AgglomerativeClustering`.

Read more in the :ref:`User Guide <birch>`.

.. versionadded:: 0.16

Parameters
----------
threshold : float, default=0.5
    The radius of the subcluster obtained by merging a new sample and the
    closest subcluster should be lesser than the threshold. Otherwise a new
    subcluster is started. Setting this value to be very low promotes
    splitting and vice-versa.

branching_factor : int, default=50
    Maximum number of CF subclusters in each node. If a new samples enters
    such that the number of subclusters exceed the branching_factor then
    that node is split into two nodes with the subclusters redistributed
    in each. The parent subcluster of that node is removed and two new
    subclusters are added as parents of the 2 split nodes.

n_clusters : int, instance of sklearn.cluster model or None, default=3
    Number of clusters after the final clustering step, which treats the
    subclusters from the leaves as new samples.

    - `None` : the final clustering step is not performed and the
      subclusters are returned as they are.

    - :mod:`sklearn.cluster` Estimator : If a model is provided, the model
      is fit treating the subclusters as new samples and the initial data
      is mapped to the label of the closest subcluster.

    - `int` : the model fit is :class:`AgglomerativeClustering` with
      `n_clusters` set to be equal to the int.

compute_labels : bool, default=True
    Whether or not to compute labels for each fit.

copy : bool, default=True
    Whether or not to make a copy of the given data. If set to False,
    the initial data will be overwritten.

    .. deprecated:: 1.6
        `copy` was deprecated in 1.6 and will be removed in 1.8. It has no effect
        as the estimator does not perform in-place operations on the input data.

Attributes
----------
root_ : _CFNode
    Root of the CFTree.

dummy_leaf_ : _CFNode
    Start pointer to all the leaves.

subcluster_centers_ : ndarray
    Centroids of all subclusters read directly from the leaves.

subcluster_labels_ : ndarray
    Labels assigned to the centroids of the subclusters after
    they are clustered globally.

labels_ : ndarray of shape (n_samples,)
    Array of labels assigned to the input data.
    if partial_fit is used instead of fit, they are assigned to the
    last batch of data.

n_features_in_ : int
    Number of features seen during :term:`fit`.

    .. versionadded:: 0.24

feature_names_in_ : ndarray of shape (`n_features_in_`,)
    Names of features seen during :term:`fit`. Defined only when `X`
    has feature names that are all strings.

    .. versionadded:: 1.0

See Also
--------
MiniBatchKMeans : Alternative implementation that does incremental updates
    of the centers' positions using mini-batches.

Notes
-----
The tree data structure consists of nodes with each node consisting of
a number of subclusters. The maximum number of subclusters in a node
is determined by the branching factor. Each subcluster maintains a
linear sum, squared sum and the number of samples in that subcluster.
In addition, each subcluster can also have a node as its child, if the
subcluster is not a member of a leaf node.

For a new point entering the root, it is merged with the subcluster closest
to it and the linear sum, squared sum and the number of samples of that
subcluster are updated. This is done recursively till the properties of
the leaf node are updated.

See :ref:`sphx_glr_auto_examples_cluster_plot_birch_vs_minibatchkmeans.py` for a
comparison with :class:`~sklearn.cluster.MiniBatchKMeans`.

References
----------
* Tian Zhang, Raghu Ramakrishnan, Maron Livny
  BIRCH: An efficient data clustering method for large databases.
  https://www.cs.sfu.ca/CourseCentral/459/han/papers/zhang96.pdf

* Roberto Perdisci
  JBirch - Java implementation of BIRCH clustering algorithm
  https://code.google.com/archive/p/jbirch

Examples
--------
>>> from sklearn.cluster import Birch
>>> X = [[0, 1], [0.3, 1], [-0.3, 1], [0, -1], [0.3, -1], [-0.3, -1]]
>>> brc = Birch(n_clusters=None)
>>> brc.fit(X)
Birch(n_clusters=None)
>>> brc.predict(X)
array([0, 0, 0, 1, 1, 1])

For a comparison of the BIRCH clustering algorithm with other clustering algorithms,
see :ref:`sphx_glr_auto_examples_cluster_plot_cluster_comparison.py`
r{   Nneither)closedr   leftboolean
deprecatedr/   r0   rJ   compute_labelscopy_parameter_constraintsg      ?2      Tc                @    Xl         X l        X0l        X@l        XPl        g r   r   )rW   r/   r0   rJ   r   r   s         r+   rX   Birch.__init__  s     # 0$,	rR   )prefer_skip_nested_validationc                 "    U R                  USS9$ )a  
Build a CF Tree for the input data.

Parameters
----------
X : {array-like, sparse matrix} of shape (n_samples, n_features)
    Input data.

y : Ignored
    Not used, present here for API consistency by convention.

Returns
-------
self
    Fitted estimator.
Fpartial)_fitrW   r!   ys      r+   fit	Birch.fit  s    $ yyEy**rR   c           	         [        U SS 5      nU=(       a    U(       + nU R                  S:w  a"  U(       a  [        R                  " S[        5        [        U USU[        R                  [        R                  /S9nU R                  nU R                  nUR                  u  pxU(       an  [        UUSUUR                  S9U l        [        UUSUUR                  S9U l        U R                  U R                  l        U R                  U R                  l        [$        R&                  " U5      (       d  [(        n	O[*        n	U	" U5       H  n
[-        U
S9nU R                  R/                  U5      nU(       d  M0  [1        U R                  XV5      u  pU ?[        UUS	UUR                  S9U l        U R                  R3                  U5        U R                  R3                  U5        M     [        R4                  " U R7                  5        Vs/ s H  oR8                  PM     sn5      nUU l        U R:                  R                  S
   U l        U R?                  U5        U $ s  snf )Nroot_r   z`copy` was deprecated in 1.6 and will be removed in 1.8 since it has no effect internally. Simply leave this parameter to its default value to avoid this warning.csr)accept_sparseresetr3   Tr.   rx   Fr   ) getattrr   warningswarnFutureWarningr   r   float64float32r/   r0   r   r7   r3   r   dummy_leaf_r;   r:   r   issparseiterr,   r6   rh   rQ   rB   concatenate_get_leavesr<   subcluster_centers__n_features_out_global_clustering)rW   r!   r   has_root
first_callr/   r0   r"   r2   	iter_funcsamplerP   splitrE   rF   leaf	centroidss                    r+   r   
Birch._fit  s   4$/!.h/
99$MM/ 	 ::rzz*
 NN	00 !	  #!1%ggDJ  '#!1%gg D +/**D'$($4$4DJJ! q!!I)IlF&&9JJJ33J?Eu3>JJ	40 J$'%5!)''
 

,,_=

,,_=# #& NN@P@P@R#S@ROO@R#ST	#, #77==a@" $Ts   Ic                     U R                   R                  n/ nUb"  UR                  U5        UR                  nUb  M"  U$ )zu
Retrieve the leaves of the CF Node.

Returns
-------
leaves : list of shape (n_leaves,)
    List of the leaf nodes.
)r   r;   r\   )rW   leaf_ptrleavess      r+   r   Birch._get_leavese  sF     ##.."MM(#**H " rR   c                 L    Uc  U R                  5         U $ U R                  USS9$ )az  
Online learning. Prevents rebuilding of CFTree from scratch.

Parameters
----------
X : {array-like, sparse matrix} of shape (n_samples, n_features),             default=None
    Input data. If X is not provided, only the global clustering
    step is done.

y : Ignored
    Not used, present here for API consistency by convention.

Returns
-------
self
    Fitted estimator.
Tr   )r   r   r   s      r+   partial_fitBirch.partial_fitu  s-    ( 9##%K99Q9--rR   c                 P    [        U 5        [        XSSS9nU R                  U5      $ )a  
Predict data using the ``centroids_`` of subclusters.

Avoid computation of the row norms of X.

Parameters
----------
X : {array-like, sparse matrix} of shape (n_samples, n_features)
    Input data.

Returns
-------
labels : ndarray of shape(n_samples,)
    Labelled data.
r   Fr   r   )r   r   _predictrW   r!   s     r+   predictBirch.predict  s)      	$eD}}QrR   c                     SU R                   0n[        SS9   [        XR                  US9nSSS5        U R                  W   $ ! , (       d  f       N= f)z5Predict data using the ``centroids_`` of subclusters.r4   Tassume_finite)metric_kwargsN)_subcluster_normsr   r   r   subcluster_labels_)rW   r!   kwargsrg   s       r+   r   Birch._predict  sP    "D$:$:;$/.++6F 0 &&v..	 0/s   A
Ac                     [        U 5        [        XSSS9n[        SS9   [        XR                  5      sSSS5        $ ! , (       d  f       g= f)a`  
Transform X into subcluster centroids dimension.

Each dimension represents the distance from the sample point to each
cluster centroid.

Parameters
----------
X : {array-like, sparse matrix} of shape (n_samples, n_features)
    Input data.

Returns
-------
X_trans : {array-like, sparse matrix} of shape (n_samples, n_clusters)
    Transformed data.
r   Fr   Tr   N)r   r   r   r   r   r   s     r+   	transformBirch.transform  s<    " 	$eD$/&q*B*BC 0//s	   ?
Ac                 l   U R                   nU R                  nUSL=(       a    U R                  nSn[        U[        5      (       a.  [        U R                   S9n[        U5      U R                   :  a  Sn[        U R                  SS9U l        Ub  U(       a_  [        R                  " [        U5      5      U l        U(       a3  [        R                  " S[        U5      U R                   4-  [        5        O UR                  U R                  5      U l        U(       a  U R!                  U5      U l        gg)z>
Global clustering for the subclusters obtained after fitting
NF)rJ   T)r5   zTNumber of subclusters found (%d) by BIRCH is less than (%d). Decrease the threshold.)rJ   r   r   
isinstancer   r   r[   r   r   r   aranger   r   r   r   fit_predictr   labels_)rW   r!   	clustererr   r   not_enough_centroidss         r+   r   Birch._global_clustering  s     OO	,,	4-@T-@-@  %i**/4??KI9~/'+$ "+4+C+CT!R 4&(iiI&?D##99~t78 '	 '0&;&;D<T<T&UD#==+DL rR   c                 l   > [         TU ]  5       nSS/UR                  l        SUR                  l        U$ )Nr   r   T)super__sklearn_tags__transformer_tagspreserves_dtype
input_tagsr   )rW   tags	__class__s     r+   r   Birch.__sklearn_tags__  s4    w')1:I0F-!%rR   )r   r   r0   r   r   r   r   rJ   r   r   r   r/   r   )NN)rp   rq   rr   rs   rt   r   r   r   r   r   r   r   dict__annotations__rX   r   r   r   r   r   r   r   r   r   r   ru   __classcell__)r   s   @r+   r   r   g  s    D tS$yAB%h4	JK\8Haf+UV$+F:|n#=>?$D   5+ 6+&M^  5. 6.4 (/D,#,J rR   r   )(r   mathr   numbersr   r   numpyr   scipyr   _configr   baser	   r
   r   r   r   
exceptionsr   metricsr   metrics.pairwiser   utils._param_validationr   r   r   utils.extmathr   utils.validationr   r    r   r,   rQ   r7   r6   r   rv   rR   r+   <module>r      sx      "   $  , / 2 B B % = %$<,~X Xv\' \'~F#\3C]FrR   