


import warnings

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.metrics import pairwise_distances

warnings.filterwarnings("ignore")

__UpperCamelCase							:							Any    							=					"K-MEANS-CLUST/ "

def       _a	(					SCREAMING_SNAKE_CASE						:					Any     ,			SCREAMING_SNAKE_CASE						:					List[Any]     ,			SCREAMING_SNAKE_CASE						:					Dict=None  ):







 """simple docstring"""



 if seed is not None:  # useful for obtaining consistent results
  np.random.seed(SCREAMING_SNAKE_CASE  )
 UpperCamelCase__       :     str 							= data.shape[0]  # number of data points

 # Pick K indices from range [0, N).
 UpperCamelCase__       :     str 							= np.random.randint(0     ,			SCREAMING_SNAKE_CASE     ,			SCREAMING_SNAKE_CASE  )

 # Keep centroids as dense format, as many entries will be nonzero due to averaging.
 # As long as at least one document in a cluster contains a word,
 # it will carry a nonzero weight in the TF-IDF vector of the centroid.
 UpperCamelCase__       :     Optional[Any] 							= data[rand_indices, :]

 return centroids

def       _a	(					SCREAMING_SNAKE_CASE						:					Dict     ,			SCREAMING_SNAKE_CASE						:					Dict  ):







 """simple docstring"""



 return pairwise_distances(SCREAMING_SNAKE_CASE     ,			SCREAMING_SNAKE_CASE     ,			metric='''euclidean'''  )

def       _a	(					SCREAMING_SNAKE_CASE						:					Tuple     ,			SCREAMING_SNAKE_CASE						:					Any  ):







 """simple docstring"""



 UpperCamelCase__       :     Tuple 							= centroid_pairwise_dist(SCREAMING_SNAKE_CASE     ,			SCREAMING_SNAKE_CASE  )

 # Compute cluster assignments for each data point:
 # Fill in the blank (RHS only)
 UpperCamelCase__       :     Optional[Any] 							= np.argmin(SCREAMING_SNAKE_CASE     ,			axis=1  )

 return cluster_assignment

def       _a	(					SCREAMING_SNAKE_CASE						:					Union[str, Any]     ,			SCREAMING_SNAKE_CASE						:					Union[str, Any]     ,			SCREAMING_SNAKE_CASE						:					int  ):







 """simple docstring"""



 UpperCamelCase__       :     List[str] 							= []
 for i in range(SCREAMING_SNAKE_CASE  ):
  # Select all data points that belong to cluster i. Fill in the blank (RHS only)
  UpperCamelCase__       :     Any 							= data[cluster_assignment == i]
  # Compute the mean of the data points. Fill in the blank (RHS only)
  UpperCamelCase__       :     Union[str, Any] 							= member_data_points.mean(axis=0  )
  new_centroids.append(SCREAMING_SNAKE_CASE  )
 UpperCamelCase__       :     Optional[Any] 							= np.array(SCREAMING_SNAKE_CASE  )

 return new_centroids

def       _a	(					SCREAMING_SNAKE_CASE						:					List[Any]     ,			SCREAMING_SNAKE_CASE						:					Optional[Any]     ,			SCREAMING_SNAKE_CASE						:					Any     ,			SCREAMING_SNAKE_CASE						:					str  ):







 """simple docstring"""



 UpperCamelCase__       :     Optional[int] 							= 0.0
 for i in range(SCREAMING_SNAKE_CASE  ):
  # Select all data points that belong to cluster i. Fill in the blank (RHS only)
  UpperCamelCase__       :     Union[str, Any] 							= data[cluster_assignment == i, :]

  if member_data_points.shape[0] > 0:  # check if i-th cluster is non-empty
   # Compute distances from centroid to data points (RHS only)
   UpperCamelCase__       :     Optional[int] 							= pairwise_distances(
       SCREAMING_SNAKE_CASE     ,			[centroids[i]]     ,			metric='''euclidean'''  )
   UpperCamelCase__       :     List[Any] 							= distances**2
   heterogeneity += np.sum(SCREAMING_SNAKE_CASE  )

 return heterogeneity

def       _a	(					SCREAMING_SNAKE_CASE						:					Any     ,			SCREAMING_SNAKE_CASE						:					Optional[int]  ):







 """simple docstring"""



 plt.figure(figsize=(7, 4)  )
 plt.plot(SCREAMING_SNAKE_CASE     ,			linewidth=4  )
 plt.xlabel('''# Iterations'''  )
 plt.ylabel('''Heterogeneity'''  )
 plt.title(F"Heterogeneity of clustering over time, K={k:d}"  )
 plt.rcParams.update({'''font.size''': 16}  )
 plt.show()

def       _a	(					SCREAMING_SNAKE_CASE						:					Optional[Any]     ,			SCREAMING_SNAKE_CASE						:					Any     ,			SCREAMING_SNAKE_CASE						:					List[Any]     ,			SCREAMING_SNAKE_CASE						:					Tuple=500     ,			SCREAMING_SNAKE_CASE						:					Any=None     ,			SCREAMING_SNAKE_CASE						:					Any=False  ):







 """simple docstring"""



 UpperCamelCase__       :     Dict 							= initial_centroids[:]
 UpperCamelCase__       :     Tuple 							= None

 for itr in range(SCREAMING_SNAKE_CASE  ):
  if verbose:
   print(SCREAMING_SNAKE_CASE     ,			end=''''''  )

  # 1. Make cluster assignments using nearest centroids
  UpperCamelCase__       :     List[str] 							= assign_clusters(SCREAMING_SNAKE_CASE     ,			SCREAMING_SNAKE_CASE  )

  # 2. Compute a new centroid for each of the k clusters, averaging all data
  #    points assigned to that cluster.
  UpperCamelCase__       :     int 							= revise_centroids(SCREAMING_SNAKE_CASE     ,			SCREAMING_SNAKE_CASE     ,			SCREAMING_SNAKE_CASE  )

  # Check for convergence: if none of the assignments changed, stop
  if (
      prev_cluster_assignment is not None
      and (prev_cluster_assignment == cluster_assignment).all()
  ):
   break

  # Print number of new assignments
  if prev_cluster_assignment is not None:
   UpperCamelCase__       :     Optional[Any] 							= np.sum(prev_cluster_assignment != cluster_assignment  )
   if verbose:
    print(
        F"    {num_changed:5d} elements changed their cluster assignment."  )

        # Record heterogeneity convergence metric
  if record_heterogeneity is not None:
   # YOUR CODE HERE
   UpperCamelCase__       :     Any 							= compute_heterogeneity(SCREAMING_SNAKE_CASE     ,			SCREAMING_SNAKE_CASE     ,			SCREAMING_SNAKE_CASE     ,			SCREAMING_SNAKE_CASE  )
   record_heterogeneity.append(SCREAMING_SNAKE_CASE  )

  UpperCamelCase__       :     Optional[int] 							= cluster_assignment[:]

 return centroids, cluster_assignment


# Mock test below
if False:  # change to true to run this test case.
       from sklearn import datasets as ds

       __UpperCamelCase							:							int    							=					ds.load_iris()
       __UpperCamelCase							:							List[str]    							=					3
       __UpperCamelCase							:							Dict    							=					[]
       __UpperCamelCase							:							Union[str, Any]    							=					get_initial_centroids(dataset["data"], k, seed=0)
       __UpperCamelCase							,    __UpperCamelCase							:							Any    							=					kmeans(
           dataset["data"],
           k,
           initial_centroids,
           maxiter=400,
           record_heterogeneity=heterogeneity,
           verbose=True,
       )
       plot_heterogeneity(heterogeneity, k)

def       _a	(					SCREAMING_SNAKE_CASE						:					pd.DataFrame     ,			SCREAMING_SNAKE_CASE						:					np.ndarray     ,			SCREAMING_SNAKE_CASE						:					List[Any]=None  ):







 """simple docstring"""



 if fill_missing_report:
  UpperCamelCase__       :     Optional[Any] 							= df.fillna(value=SCREAMING_SNAKE_CASE  )
 UpperCamelCase__       :     List[str] 							= 1
 UpperCamelCase__       :     str 							= df.select_dtypes(np.number  ).columns
 UpperCamelCase__       :     Dict 							= (
     df.groupby(['''Cluster''']  )[  # construct report dataframe
         numeric_cols
     ]  # group by cluster number
     .agg(
         [
             ('''sum''', np.sum),
             ('''mean_with_zeros''', lambda SCREAMING_SNAKE_CASE  : np.mean(np.nan_to_num(SCREAMING_SNAKE_CASE  )  )),
             ('''mean_without_zeros''', lambda SCREAMING_SNAKE_CASE  : x.replace(0     ,			np.NaN  ).mean()),
             (
                 '''mean_25-75''',
                 lambda SCREAMING_SNAKE_CASE  : np.mean(
                     np.nan_to_num(
                         sorted(SCREAMING_SNAKE_CASE  )[
                             round(len(SCREAMING_SNAKE_CASE  ) * 25 / 100  ) : round(len(SCREAMING_SNAKE_CASE  ) * 75 / 100  )
                         ]  )  ),
             ),
             ('''mean_with_na''', np.mean),
             ('''min''', lambda SCREAMING_SNAKE_CASE  : x.min()),
             ('''5%''', lambda SCREAMING_SNAKE_CASE  : x.quantile(0.05  )),
             ('''25%''', lambda SCREAMING_SNAKE_CASE  : x.quantile(0.25  )),
             ('''50%''', lambda SCREAMING_SNAKE_CASE  : x.quantile(0.50  )),
             ('''75%''', lambda SCREAMING_SNAKE_CASE  : x.quantile(0.75  )),
             ('''95%''', lambda SCREAMING_SNAKE_CASE  : x.quantile(0.95  )),
             ('''max''', lambda SCREAMING_SNAKE_CASE  : x.max()),
             ('''count''', lambda SCREAMING_SNAKE_CASE  : x.count()),
             ('''stdev''', lambda SCREAMING_SNAKE_CASE  : x.std()),
             ('''mode''', lambda SCREAMING_SNAKE_CASE  : x.mode()[0]),
             ('''median''', lambda SCREAMING_SNAKE_CASE  : x.median()),
             ('''# > 0''', lambda SCREAMING_SNAKE_CASE  : (x > 0).sum()),
         ]  )
     .T.reset_index()
     .rename(index=SCREAMING_SNAKE_CASE     ,			columns={'''level_0''': '''Features''', '''level_1''': '''Type'''}  )
 )  # rename columns
 # calculate the size of cluster(count of clientID's)
 UpperCamelCase__       :     List[str] 							= report[
     (report['''Features'''] == '''dummy''') & (report['''Type'''] == '''count''')
 ].copy()  # avoid SettingWithCopyWarning
 UpperCamelCase__       :     str 							= (
     '''ClusterSize'''  # rename created cluster df to match report column names
 )
 UpperCamelCase__       :     str 							= '''# of Customers'''
 UpperCamelCase__       :     List[str] 							= pd.DataFrame(
     clustersize.iloc[:, 2:].values
     / clustersize.iloc[:, 2:].values.sum()  )
 UpperCamelCase__       :     Tuple 							= '''% of Customers'''  # rename created cluster df to match report column names
 UpperCamelCase__       :     Optional[int] 							= '''ClusterProportion'''
 UpperCamelCase__       :     Optional[int] 							= clusterproportion.columns.tolist()
 UpperCamelCase__       :     List[str] 							= cols[-2:] + cols[:-2]
 UpperCamelCase__       :     Optional[int] 							= clusterproportion[cols]  # rearrange columns to match report
 UpperCamelCase__       :     List[str] 							= report.columns
 UpperCamelCase__       :     Tuple 							= pd.DataFrame(
     abs(
         report[report['''Type'''] == '''count'''].iloc[:, 2:].values
         - clustersize.iloc[:, 2:].values  )  )  # generating df with count of nan values
 UpperCamelCase__       :     Union[str, Any] 							= 0
 UpperCamelCase__       :     Any 							= '''# of nan'''
 UpperCamelCase__       :     List[Any] 							= report[
     report['''Type'''] == '''count'''
 ].Features.tolist()  # filling values in order to match report
 UpperCamelCase__       :     Optional[int] 							= a.columns.tolist()
 UpperCamelCase__       :     Dict 							= cols[-2:] + cols[:-2]
 UpperCamelCase__       :     str 							= a[cols]  # rearrange columns to match report
 UpperCamelCase__       :     Any 							= report.columns  # rename columns to match report
 UpperCamelCase__       :     Dict 							= report.drop(
     report[report.Type == '''count'''].index  )  # drop count values except cluster size
 UpperCamelCase__       :     List[Any] 							= pd.concat(
     [report, a, clustersize, clusterproportion]     ,			axis=0  )  # concat report with clustert size and nan values
 UpperCamelCase__       :     Any 							= report['''Features'''].isin(SCREAMING_SNAKE_CASE  )
 UpperCamelCase__       :     List[Any] 							= report.columns.tolist()
 UpperCamelCase__       :     Optional[int] 							= cols[0:2] + cols[-1:] + cols[2:-1]
 UpperCamelCase__       :     List[str] 							= report[cols]
 UpperCamelCase__       :     Tuple 							= {
     '''ClusterSize''': 9,
     '''ClusterProportion''': 8,
     '''mean_with_zeros''': 7,
     '''mean_with_na''': 6,
     '''max''': 5,
     '''50%''': 4,
     '''min''': 3,
     '''25%''': 2,
     '''75%''': 1,
     '''# of nan''': 0,
     '''# > 0''': -1,
     '''sum_with_na''': -2,
 }
 UpperCamelCase__       :     int 							= (
     report.assign(
         Sortera=lambda SCREAMING_SNAKE_CASE  : x.Type.map(SCREAMING_SNAKE_CASE  )     ,			Sortera=lambda SCREAMING_SNAKE_CASE  : list(reversed(range(len(SCREAMING_SNAKE_CASE  )  )  )  )     ,			)
     .sort_values(['''Sorter1''', '''Mark''', '''Sorter2''']     ,			ascending=SCREAMING_SNAKE_CASE  )
     .drop(['''Sorter1''', '''Sorter2''']     ,			axis=1  )
 )
 UpperCamelCase__       :     Tuple 							= ''''''
 UpperCamelCase__       :     Union[str, Any] 							= report.reset_index()
 UpperCamelCase__       :     Optional[int] 							= report.drop(columns=['''index''']  )
 return report


if __name__ == "__main__":
       import doctest

       doctest.testmod()






from typing import TYPE_CHECKING

from ...utils import (
    OptionalDependencyNotAvailable,
    _LazyModule,
    is_tf_available,
    is_tokenizers_available,
    is_torch_available,
)


__UpperCamelCase							:							Dict    							=					{
    "configuration_dpr": ["DPR_PRETRAINED_CONFIG_ARCHIVE_MAP", "DPRConfig"],
    "tokenization_dpr": [
        "DPRContextEncoderTokenizer",
        "DPRQuestionEncoderTokenizer",
        "DPRReaderOutput",
        "DPRReaderTokenizer",
    ],
}


try:
       if not is_tokenizers_available():
              raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
       pass
else:
       __UpperCamelCase							:							Any    							=					[
           "DPRContextEncoderTokenizerFast",
           "DPRQuestionEncoderTokenizerFast",
           "DPRReaderTokenizerFast",
       ]

try:
       if not is_torch_available():
              raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
       pass
else:
       __UpperCamelCase							:							str    							=					[
           "DPR_CONTEXT_ENCODER_PRETRAINED_MODEL_ARCHIVE_LIST",
           "DPR_QUESTION_ENCODER_PRETRAINED_MODEL_ARCHIVE_LIST",
           "DPR_READER_PRETRAINED_MODEL_ARCHIVE_LIST",
           "DPRContextEncoder",
           "DPRPretrainedContextEncoder",
           "DPRPreTrainedModel",
           "DPRPretrainedQuestionEncoder",
           "DPRPretrainedReader",
           "DPRQuestionEncoder",
           "DPRReader",
       ]

try:
       if not is_tf_available():
              raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
       pass
else:
       __UpperCamelCase							:							int    							=					[
           "TF_DPR_CONTEXT_ENCODER_PRETRAINED_MODEL_ARCHIVE_LIST",
           "TF_DPR_QUESTION_ENCODER_PRETRAINED_MODEL_ARCHIVE_LIST",
           "TF_DPR_READER_PRETRAINED_MODEL_ARCHIVE_LIST",
           "TFDPRContextEncoder",
           "TFDPRPretrainedContextEncoder",
           "TFDPRPretrainedQuestionEncoder",
           "TFDPRPretrainedReader",
           "TFDPRQuestionEncoder",
           "TFDPRReader",
       ]


if TYPE_CHECKING:
       from .configuration_dpr import DPR_PRETRAINED_CONFIG_ARCHIVE_MAP, DPRConfig
       from .tokenization_dpr import (
           DPRContextEncoderTokenizer,
           DPRQuestionEncoderTokenizer,
           DPRReaderOutput,
           DPRReaderTokenizer,
       )

       try:
              if not is_tokenizers_available():
                     raise OptionalDependencyNotAvailable()
       except OptionalDependencyNotAvailable:
              pass
       else:
              from .tokenization_dpr_fast import (
                  DPRContextEncoderTokenizerFast,
                  DPRQuestionEncoderTokenizerFast,
                  DPRReaderTokenizerFast,
              )

       try:
              if not is_torch_available():
                     raise OptionalDependencyNotAvailable()
       except OptionalDependencyNotAvailable:
              pass
       else:
              from .modeling_dpr import (
                  DPR_CONTEXT_ENCODER_PRETRAINED_MODEL_ARCHIVE_LIST,
                  DPR_QUESTION_ENCODER_PRETRAINED_MODEL_ARCHIVE_LIST,
                  DPR_READER_PRETRAINED_MODEL_ARCHIVE_LIST,
                  DPRContextEncoder,
                  DPRPretrainedContextEncoder,
                  DPRPreTrainedModel,
                  DPRPretrainedQuestionEncoder,
                  DPRPretrainedReader,
                  DPRQuestionEncoder,
                  DPRReader,
              )

       try:
              if not is_tf_available():
                     raise OptionalDependencyNotAvailable()
       except OptionalDependencyNotAvailable:
              pass
       else:
              from .modeling_tf_dpr import (
                  TF_DPR_CONTEXT_ENCODER_PRETRAINED_MODEL_ARCHIVE_LIST,
                  TF_DPR_QUESTION_ENCODER_PRETRAINED_MODEL_ARCHIVE_LIST,
                  TF_DPR_READER_PRETRAINED_MODEL_ARCHIVE_LIST,
                  TFDPRContextEncoder,
                  TFDPRPretrainedContextEncoder,
                  TFDPRPretrainedQuestionEncoder,
                  TFDPRPretrainedReader,
                  TFDPRQuestionEncoder,
                  TFDPRReader,
              )

else:
       import sys

       __UpperCamelCase							:							Dict    							=					_LazyModule(__name__, globals()["__file__"], _import_structure, module_spec=__spec__)


