

"""simple docstring"""


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")

__A		     =    'K-MEANS-CLUST/ '






def 					a__					(					__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE=None				)			->			List[str]:
  if seed is not None:  # useful for obtaining consistent results
    np.random.seed(lowercase__				)
  __lowerCAmelCase: Optional[int]					   =    data.shape[0]  # number of data points

  # Pick K indices from range [0, N).
  __lowerCAmelCase: List[str]					   =    np.random.randint(0      ,				lowercase__      ,				lowercase__				)

  # 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.
  __lowerCAmelCase: Dict					   =    data[rand_indices, :]

  return centroids






def 					a__					(					__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE				)			->			List[Any]:
  return pairwise_distances(lowercase__      ,				lowercase__      ,				metric="euclidean"				)






def 					a__					(					__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE				)			->			Dict:
  # Compute distances between each data point and the set of centroids:
  # Fill in the blank (RHS only)
  __lowerCAmelCase: Optional[Any]					   =    centroid_pairwise_dist(lowercase__      ,				lowercase__				)

  # Compute cluster assignments for each data point:
  # Fill in the blank (RHS only)
  __lowerCAmelCase: Any					   =    np.argmin(lowercase__      ,				axis=1				)

  return cluster_assignment






def 					a__					(					__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE				)			->			Tuple:
  __lowerCAmelCase: str					   =    []
  for i in range(lowercase__				):
    # Select all data points that belong to cluster i. Fill in the blank (RHS only)
    __lowerCAmelCase: Optional[int]					   =    data[cluster_assignment == i]
    # Compute the mean of the data points. Fill in the blank (RHS only)
    __lowerCAmelCase: Dict					   =    member_data_points.mean(axis=0				)
    new_centroids.append(lowercase__				)
  __lowerCAmelCase: Optional[int]					   =    np.array(lowercase__				)

  return new_centroids






def 					a__					(					__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE				)			->			int:
  __lowerCAmelCase: Tuple					   =    0.0
  for i in range(lowercase__				):
    # Select all data points that belong to cluster i. Fill in the blank (RHS only)
    __lowerCAmelCase: Optional[int]					   =    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)
      __lowerCAmelCase: Union[str, Any]					   =    pairwise_distances(
          lowercase__      ,				[centroids[i]]      ,				metric="euclidean"				)
      __lowerCAmelCase: Tuple					   =    distances**2
      heterogeneity += np.sum(lowercase__				)

  return heterogeneity






def 					a__					(					__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE				)			->			Tuple:
  plt.figure(figsize=(7, 4)				)
  plt.plot(lowercase__      ,				linewidth=4				)
  plt.xlabel("# Iterations"				)
  plt.ylabel("Heterogeneity"				)
  plt.title(F"Heterogeneity of clustering over time, K={k:d}"				)
  plt.rcParams.update({"font.size": 1_6}				)
  plt.show()






def 					a__					(					__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE=5_0_0      ,				__SCREAMING_SNAKE_CASE=None      ,				__SCREAMING_SNAKE_CASE=False				)			->			Tuple:
  __lowerCAmelCase: Optional[Any]					   =    initial_centroids[:]
  __lowerCAmelCase: Dict					   =    None

  for itr in range(lowercase__				):
    if verbose:
      print(lowercase__      ,				end=""				)

    # 1. Make cluster assignments using nearest centroids
    __lowerCAmelCase: Union[str, Any]					   =    assign_clusters(lowercase__      ,				lowercase__				)

    # 2. Compute a new centroid for each of the k clusters, averaging all data
    #    points assigned to that cluster.
    __lowerCAmelCase: List[str]					   =    revise_centroids(lowercase__      ,				lowercase__      ,				lowercase__				)

    # 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:
      __lowerCAmelCase: List[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
      __lowerCAmelCase: str					   =    compute_heterogeneity(lowercase__      ,				lowercase__      ,				lowercase__      ,				lowercase__				)
      record_heterogeneity.append(lowercase__				)

    __lowerCAmelCase: Tuple					   =    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

   __A		     =    ds.load_iris()
   __A		     =    3
   __A		     =    []
   __A		     =    get_initial_centroids(dataset["data"], k, seed=0)
   __A		     =    kmeans(
       dataset["data"],
       k,
       initial_centroids,
       maxiter=400,
       record_heterogeneity=heterogeneity,
       verbose=True,
   )
   plot_heterogeneity(heterogeneity, k)






def 					a__					(					__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE=None				)			->			Dict:
  # Fill missing values with given rules
  if fill_missing_report:
    __lowerCAmelCase: List[str]					   =    df.fillna(value=lowercase__				)
  __lowerCAmelCase: Union[str, Any]					   =    1
  __lowerCAmelCase: Optional[int]					   =    df.select_dtypes(np.number				).columns
  __lowerCAmelCase: Optional[Any]					   =    (
      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(lowercase__				)				)),
              ("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(lowercase__				)[
                              round(len(lowercase__				) * 2_5 / 1_0_0				) : round(len(lowercase__				) * 7_5 / 1_0_0				)
                          ]				)				),
              ),
              ("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=lowercase__      ,				columns={"level_0": "Features", "level_1": "Type"}				)
  )  # rename columns
  # calculate the size of cluster(count of clientID's)
  __lowerCAmelCase: Optional[int]					   =    report[
      (report["Features"] == "dummy") & (report["Type"] == "count")
  ].copy()  # avoid SettingWithCopyWarning
  __lowerCAmelCase: str					   =    (
      "ClusterSize"  # rename created cluster df to match report column names
  )
  __lowerCAmelCase: Tuple					   =    "# of Customers"
  __lowerCAmelCase: str					   =    pd.DataFrame(
      clustersize.iloc[:, 2:].values
      / clustersize.iloc[:, 2:].values.sum()				)
  __lowerCAmelCase: Any					   =    "% of Customers"  # rename created cluster df to match report column names
  __lowerCAmelCase: str					   =    "ClusterProportion"
  __lowerCAmelCase: Optional[int]					   =    clusterproportion.columns.tolist()
  __lowerCAmelCase: str					   =    cols[-2:] + cols[:-2]
  __lowerCAmelCase: Optional[int]					   =    clusterproportion[cols]  # rearrange columns to match report
  __lowerCAmelCase: List[Any]					   =    report.columns
  __lowerCAmelCase: Any					   =    pd.DataFrame(
      abs(
          report[report["Type"] == "count"].iloc[:, 2:].values
          - clustersize.iloc[:, 2:].values				)				)  # generating df with count of nan values
  __lowerCAmelCase: Dict					   =    0
  __lowerCAmelCase: Optional[Any]					   =    "# of nan"
  __lowerCAmelCase: Any					   =    report[
      report["Type"] == "count"
  ].Features.tolist()  # filling values in order to match report
  __lowerCAmelCase: List[str]					   =    a.columns.tolist()
  __lowerCAmelCase: str					   =    cols[-2:] + cols[:-2]
  __lowerCAmelCase: Tuple					   =    a[cols]  # rearrange columns to match report
  __lowerCAmelCase: List[str]					   =    report.columns  # rename columns to match report
  __lowerCAmelCase: List[str]					   =    report.drop(
      report[report.Type == "count"].index				)  # drop count values except cluster size
  __lowerCAmelCase: Optional[Any]					   =    pd.concat(
      [report, a, clustersize, clusterproportion]      ,				axis=0				)  # concat report with clustert size and nan values
  __lowerCAmelCase: Optional[Any]					   =    report["Features"].isin(lowercase__				)
  __lowerCAmelCase: Dict					   =    report.columns.tolist()
  __lowerCAmelCase: Dict					   =    cols[0:2] + cols[-1:] + cols[2:-1]
  __lowerCAmelCase: str					   =    report[cols]
  __lowerCAmelCase: int					   =    {
      "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,
  }
  __lowerCAmelCase: Optional[Any]					   =    (
      report.assign(
          Sortera=lambda __SCREAMING_SNAKE_CASE				: x.Type.map(lowercase__				)      ,				Sortera=lambda __SCREAMING_SNAKE_CASE				: list(reversed(range(len(lowercase__				)				)				)				)      ,				)
      .sort_values(["Sorter1", "Mark", "Sorter2"]      ,				ascending=lowercase__				)
      .drop(["Sorter1", "Sorter2"]      ,				axis=1				)
  )
  __lowerCAmelCase: List[str]					   =    ""
  __lowerCAmelCase: Any					   =    report.reset_index()
  __lowerCAmelCase: int					   =    report.drop(columns=["index"]				)
  return report


if __name__ == "__main__":
   import doctest

   doctest.testmod()





"""simple docstring"""


import math

import qiskit
from qiskit import Aer, ClassicalRegister, QuantumCircuit, QuantumRegister, execute






def 					a__					(					__SCREAMING_SNAKE_CASE = 1      ,				__SCREAMING_SNAKE_CASE = 1				)			->			qiskit.result.counts.Counts:
		if isinstance(__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE				) or isinstance(__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE				):
				raise TypeError("inputs must be integers."				)
		if (bit_a < 0) or (bit_a < 0):
				raise ValueError("inputs must be positive."				)
		if (math.floor(__SCREAMING_SNAKE_CASE				) != bit_a) or (math.floor(__SCREAMING_SNAKE_CASE				) != bit_a):
				raise ValueError("inputs must be exact integers."				)
		if (bit_a > 1) or (bit_a > 1):
				raise ValueError("inputs must be less or equal to 1."				)

		# build registers
		__lowerCAmelCase: str					   =    QuantumRegister(2      ,				"qr"				)
		__lowerCAmelCase: Optional[Any]					   =    ClassicalRegister(2      ,				"cr"				)

		__lowerCAmelCase: Dict					   =    QuantumCircuit(__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE				)

		# entanglement the qubits
		quantum_circuit.h(1				)
		quantum_circuit.cx(1      ,				0				)

		# send the information
		__lowerCAmelCase: Dict					   =    str(__SCREAMING_SNAKE_CASE				) + str(__SCREAMING_SNAKE_CASE				)

		if c_information == "11":
				quantum_circuit.x(1				)
				quantum_circuit.z(1				)
		elif c_information == "10":
				quantum_circuit.z(1				)
		elif c_information == "01":
				quantum_circuit.x(1				)
		else:
				quantum_circuit.i(1				)

		# unentangled the circuit
		quantum_circuit.cx(1      ,				0				)
		quantum_circuit.h(1				)

		# measure the circuit
		quantum_circuit.measure(__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE				)

		__lowerCAmelCase: List[str]					   =    Aer.get_backend("aer_simulator"				)
		__lowerCAmelCase: Dict					   =    execute(__SCREAMING_SNAKE_CASE      ,				__SCREAMING_SNAKE_CASE      ,				shots=1_0_0_0				)

		return job.result().get_counts(__SCREAMING_SNAKE_CASE				)


if __name__ == "__main__":
			print(F'''Counts for classical state send: {superdense_coding(1,1)}''')


