class_docstr: !
  @brief PAM BUILD algorithm is designed to find optimal initial medoids for K-Medoids algorithms family, like PAM.
  
  @details The initialization procedure chooses `k` times the point which yields the smallest distance sum of total
            deviation. Complexity of the algorithm is $O\left ( n^{2}k 
  ight )$, where `n` is the amount
            of points and `k` is the amount of initial medoids to generate.
  
  Implementation based on paper @cite inproceedings::cluster::kmedoids::1.
  
  There is an example where PAM BUILD algorithm is used to generate initial medoids for various samples.
  @code
      from pyclustering.cluster.kmedoids import build
      from pyclustering.cluster import cluster_visualizer
      from pyclustering.utils import read_sample
      from pyclustering.samples.definitions import FCPS_SAMPLES, SIMPLE_SAMPLES
  
      # Short name of each sample.
      name = ['TwoDiamonds', 'Lsun', 'WingNut', 'Tetra', 'Hepta', 'Simple01', 'Simple02', 'Simple03']
  
      # Path to each sample.
      path = [FCPS_SAMPLES.SAMPLE_TWO_DIAMONDS, FCPS_SAMPLES.SAMPLE_LSUN, FCPS_SAMPLES.SAMPLE_WING_NUT, FCPS_SAMPLES.SAMPLE_TETRA, FCPS_SAMPLES.SAMPLE_HEPTA, SIMPLE_SAMPLES.SAMPLE_SIMPLE1, SIMPLE_SAMPLES.SAMPLE_SIMPLE2, SIMPLE_SAMPLES.SAMPLE_SIMPLE3]
  
      # Amount of medoids that should be initialized for each sample.
      amount_medoids = [2, 3, 2, 4, 7, 2, 3, 4]
  
      # Prepare 8 plots where each line contains 4 plots.
      visualizer = cluster_visualizer(8, 4)
  
      for i in range(len(name)):
          # Load list of points to cluster analysis.
          sample = read_sample(path[i])
  
          # Initialize initial medoids using PAM BUILD algorithm.
          initial_medoids = build(sample, amount_medoids[i]).initialize()
  
          # Set bigger medoid marker for 3-dimensional data to make it more visible.
          medoid_marker_size = 8
          if len(sample[0]) == 3:
              medoid_marker_size = 32
  
          # Append points as a one big cluster.
          visualizer.append_cluster(sample, canvas=i, marker='.', markersize=2, color='dimgray')
  
          # Append initial medoids that were obtained by PAM BUILD algorithm.
          visualizer.append_cluster(initial_medoids, sample, canvas=i, markersize=medoid_marker_size, marker='*', color='blue')
  
          # Set name of the sample that was used.
          visualizer.set_canvas_title(name[i], canvas=i)
  
      # Display results.
      visualizer.show()
  @endcode
  
  PAM BUILD algorithm provides much more optimal initial medoids in average than kmeans++ based approach and as a
  result it reduces amount of iterations that is needed for K-Medoids algorithms family to extract clusters. There is
  an illustration that was generated by the code above where initial medoids are marked by blue stars.
  
  @image html pam_build_initial_medoids.png "Fig. 1. Initial medoids for various samples generated by PAM BUILD algorithm."
class_docstr_tok: ["!","@","brief","PAM","BUILD","algorithm","is","designed","to","find","optimal","initial","medoids","for","K-Medoids","algorithms","family",",","like","PAM",".","@","details","The","initialization","procedure","chooses","`","k","`","times","the","point","which","yields","the","smallest","distance","sum","of","total","deviation",".","Complexity","of","the","algorithm","is","$","O\\left","(","n^","{","2","}","k","ight",")","$",",","where","`","n","`","is","the","amount","of","points","and","`","k","`","is","the","amount","of","initial","medoids","to","generate",".","Implementation","based","on","paper","@","cite","inproceedings",":",":cluster",":",":kmedoids",":",":1",".","There","is","an","example","where","PAM","BUILD","algorithm","is","used","to","generate","initial","medoids","for","various","samples",".","@","code","from","pyclustering.cluster.kmedoids","import","build","from","pyclustering.cluster","import","cluster_visualizer","from","pyclustering.utils","import","read_sample","from","pyclustering.samples.definitions","import","FCPS_SAMPLES",",","SIMPLE_SAMPLES","#","Short","name","of","each","sample",".","name","=","[","'TwoDiamonds","'",",","'Lsun","'",",","'WingNut","'",",","'Tetra","'",",","'Hepta","'",",","'Simple01","'",",","'Simple02","'",",","'Simple03","'","]","#","Path","to","each","sample",".","path","=","[","FCPS_SAMPLES.SAMPLE_TWO_DIAMONDS",",","FCPS_SAMPLES.SAMPLE_LSUN",",","FCPS_SAMPLES.SAMPLE_WING_NUT",",","FCPS_SAMPLES.SAMPLE_TETRA",",","FCPS_SAMPLES.SAMPLE_HEPTA",",","SIMPLE_SAMPLES.SAMPLE_SIMPLE1",",","SIMPLE_SAMPLES.SAMPLE_SIMPLE2",",","SIMPLE_SAMPLES.SAMPLE_SIMPLE3","]","#","Amount","of","medoids","that","should","be","initialized","for","each","sample",".","amount_medoids","=","[","2",",","3",",","2",",","4",",","7",",","2",",","3",",","4","]","#","Prepare","8","plots","where","each","line","contains","4","plots",".","visualizer","=","cluster_visualizer","(","8",",","4",")","for","i","in","range","(","len","(","name",")",")",":","#","Load","list","of","points","to","cluster","analysis",".","sample","=","read_sample","(","path","[","i","]",")","#","Initialize","initial","medoids","using","PAM","BUILD","algorithm",".","initial_medoids","=","build","(","sample",",","amount_medoids","[","i","]",")",".initialize","(",")","#","Set","bigger","medoid","marker","for","3-dimensional","data","to","make","it","more","visible",".","medoid_marker_size","=","8","if","len","(","sample","[","0","]",")","==","3",":","medoid_marker_size","=","32","#","Append","points","as","a","one","big","cluster",".","visualizer.append_cluster","(","sample",",","canvas=i",",","marker=","'",".","'",",","markersize=2",",","color='dimgray","'",")","#","Append","initial","medoids","that","were","obtained","by","PAM","BUILD","algorithm",".","visualizer.append_cluster","(","initial_medoids",",","sample",",","canvas=i",",","markersize=medoid_marker_size",",","marker=","'","*","'",",","color='blue","'",")","#","Set","name","of","the","sample","that","was","used",".","visualizer.set_canvas_title","(","name","[","i","]",",","canvas=i",")","#","Display","results",".","visualizer.show","(",")","@","endcode","PAM","BUILD","algorithm","provides","much","more","optimal","initial","medoids","in","average","than","kmeans++","based","approach","and","as","a","result","it","reduces","amount","of","iterations","that","is","needed","for","K-Medoids","algorithms","family","to","extract","clusters",".","There","is","an","illustration","that","was","generated","by","the","code","above","where","initial","medoids","are","marked","by","blue","stars",".","@","image","html","pam_build_initial_medoids.png","``","Fig",".","1",".","Initial","medoids","for","various","samples","generated","by","PAM","BUILD","algorithm",".","''"]
code: def __calculate_next_medoid(self):
      optimal_medoid = -1
      optimal_deviation = float("inf")
      optimal_distances = [0] * len(self.__data)
      current_distances = [0] * len(self.__data)
  
      for i in range(len(self.__data)):
          if i in self.__medoids:
              continue
  
          total_deviation = 0.0
          for j in range(len(self.__data)):
              if (i == j) or (j in self.__medoids):
                  current_distances[j] = 0
                  continue
  
              distance = min(
                  self.__distance_calculator(i, j),
                  self.__distance_closest_medoid[j],
              )
              total_deviation += distance
              current_distances[j] = distance
  
          if total_deviation < optimal_deviation:
              optimal_medoid = i
              optimal_deviation = total_deviation
              optimal_distances, current_distances = (
                  current_distances,
                  optimal_distances,
              )
  
      self.__medoids.append(optimal_medoid)
      self.__distance_closest_medoid = optimal_distances
  
imports: import numpy
  from pyclustering.cluster.encoder import type_encoding
  from pyclustering.utils.metric import distance_metric, type_metric
  import pyclustering.core.pam_build_wrapper
  import pyclustering.core.kmedoids_wrapper
  from pyclustering.core.wrapper import ccore_library
  from pyclustering.core.metric_wrapper import metric_wrapper
label_desc: Use image node_id 7 for calling the build obj's underlying member method code with example usage: obj.__calculate_next_medoid() without return types