ga.py
1 """!
2 
3 @brief Cluster analysis algorithm: Genetic clustering algorithm (GA).
4 @details Implementation based on papers @cite article::ga::1, @cite article::ga::2.
5 
6 @authors Andrei Novikov, Aleksey Kukushkin (pyclustering@yandex.ru)
7 @date 2014-2019
8 @copyright GNU Public License
9 
10 @cond GNU_PUBLIC_LICENSE
11  PyClustering is free software: you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  PyClustering is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program. If not, see <http://www.gnu.org/licenses/>.
23 @endcond
24 
25 """
26 
27 
28 import numpy as np
29 import math
30 import warnings
31 
32 try:
33  import matplotlib.pyplot as plt
34  import matplotlib.animation as animation
35 except Exception as error_instance:
36  warnings.warn("Impossible to import matplotlib (please, install 'matplotlib'), pyclustering's visualization "
37  "functionality is not available (details: '%s')." % str(error_instance))
38 
39 from pyclustering.cluster import cluster_visualizer
40 from pyclustering.cluster.ga_maths import ga_math
41 
42 
43 
45  """!
46  @brief Genetic algorithm observer that is used to collect information about clustering process on each iteration.
47 
48  """
49 
50  def __init__(self, need_global_best=False, need_population_best=False, need_mean_ff=False):
51  """!
52  @brief Constructs genetic algorithm observer to collect specific information.
53 
54  @param[in] need_global_best (bool): If 'True' then the best chromosomes and its fitness function value (global optimum) for each iteration are stored.
55  @param[in] need_population_best (bool): If 'True' then current (on each iteration) best chromosomes and its fitness function value (local optimum) are stored.
56  @param[in] need_mean_ff (bool): If 'True' then average value of fitness function on each iteration is stored.
57 
58  """
59 
60  # Global best chromosome and fitness function for each population
61  self._global_best_result = {'chromosome': [], 'fitness_function': []}
62 
63  # Best chromosome and fitness function on a population
64  self._best_population_result = {'chromosome': [], 'fitness_function': []}
65 
66  # Mean fitness function on each population
67  self._mean_ff_result = []
68 
69  # Flags to collect
70  self._need_global_best = need_global_best
71  self._need_population_best = need_population_best
72  self._need_mean_ff = need_mean_ff
73 
74 
75  def __len__(self):
76  """!
77  @brief Returns amount of iterations that genetic algorithm was observed.
78 
79  """
80  global_length = len(self._global_best_result['chromosome'])
81  local_length = len(self._best_population_result['chromosome'])
82  average_length = len(self._mean_ff_result)
83 
84  return max(global_length, local_length, average_length)
85 
86 
87  def collect_global_best(self, best_chromosome, best_fitness_function):
88  """!
89  @brief Stores the best chromosome and its fitness function's value.
90 
91  @param[in] best_chromosome (list): The best chromosome that were observed.
92  @param[in] best_fitness_function (float): Fitness function value of the best chromosome.
93 
94  """
95 
96  if not self._need_global_best:
97  return
98 
99  self._global_best_result['chromosome'].append(best_chromosome)
100  self._global_best_result['fitness_function'].append(best_fitness_function)
101 
102 
103  def collect_population_best(self, best_chromosome, best_fitness_function):
104  """!
105  @brief Stores the best chromosome for current specific iteration and its fitness function's value.
106 
107  @param[in] best_chromosome (list): The best chromosome on specific iteration.
108  @param[in] best_fitness_function (float): Fitness function value of the chromosome.
109 
110  """
111 
112  if not self._need_population_best:
113  return
114 
115  self._best_population_result['chromosome'].append(best_chromosome)
116  self._best_population_result['fitness_function'].append(best_fitness_function)
117 
118 
119  def collect_mean(self, fitness_functions):
120  """!
121  @brief Stores average value of fitness function among chromosomes on specific iteration.
122 
123  @param[in] fitness_functions (float): Average value of fitness functions among chromosomes.
124 
125  """
126 
127  if not self._need_mean_ff:
128  return
129 
130  self._mean_ff_result.append(np.mean(fitness_functions))
131 
132 
133  def get_global_best(self):
134  """!
135  @return (dict) Returns dictionary with keys 'chromosome' and 'fitness_function' where evolution of the best chromosome
136  and its fitness function's value (evolution of global optimum) are stored in lists.
137 
138  """
139  return self._global_best_result
140 
141 
143  """!
144  @brief (dict) Returns dictionary with keys 'chromosome' and 'fitness_function' where evolution of the current best chromosome
145  and its fitness function's value (evolution of local optimum) are stored in lists.
146 
147  """
148  return self._best_population_result
149 
150 
152  """!
153  @brief (list) Returns fitness function's values on each iteration.
154 
155  """
156  return self._mean_ff_result
157 
158 
159 
161  """!
162  @brief Genetic algorithm visualizer is used to show clustering results that are specific for
163  this particular algorithm: clusters, evolution of global and local optimum.
164  @details The visualizer requires 'ga_observer' that collects evolution of clustering process in
165  genetic algorithm. The observer is created by user and passed to genetic algorithm. There
166  is usage example of the visualizer using the observer:
167  @code
168  from pyclustering.cluster.ga import genetic_algorithm, ga_observer, ga_visualizer
169  from pyclustering.utils import read_sample
170  from pyclustering.samples.definitions import SIMPLE_SAMPLES
171 
172 
173  # Read data for clustering
174  sample = read_sample(SIMPLE_SAMPLES.SAMPLE_SIMPLE1)
175 
176  # Create instance of observer that will collect all information:
177  observer_instance = ga_observer(True, True, True)
178 
179  # Create genetic algorithm where observer will collect information:
180  ga_instance = genetic_algorithm(data=sample,
181  count_clusters=2,
182  chromosome_count=20,
183  population_count=20,
184  count_mutation_gens=1,
185  observer=observer_instance)
186 
187  # Start processing
188  ga_instance.process()
189 
190  # Obtain results
191  clusters = ga_instance.get_clusters()
192 
193  # Print cluster to console
194  print("Amount of clusters: '%d'. Clusters: '%s'" % (len(clusters), clusters))
195 
196  # Show cluster using observer:
197  ga_visualizer.show_clusters(sample, observer_instance)
198  @endcode
199 
200  @see cluster_visualizer
201 
202  """
203 
204  @staticmethod
205  def show_evolution(observer, start_iteration = 0, stop_iteration=None, ax=None, display=True):
206  """!
207  @brief Displays evolution of fitness function for the best chromosome, for the current best chromosome and
208  average value among all chromosomes.
209 
210  @param[in] observer (ga_observer): Genetic algorithm observer that was used for collecting evolution in the algorithm and
211  where whole required information for visualization is stored.
212  @param[in] start_iteration (uint): Iteration from that evolution should be shown.
213  @param[in] stop_iteration (uint): Iteration after that evolution shouldn't be shown.
214  @param[in] ax (Axes): Canvas where evolution should be displayed.
215  @param[in] display (bool): If 'True' then visualization of the evolution will be shown by the function.
216  This argument should be 'False' if you want to add something else to the canvas and display it later.
217 
218  @return (Axis) Canvas where evolution was shown.
219 
220  """
221 
222  if (ax is None):
223  _, ax = plt.subplots(1)
224  ax.set_title("Evolution")
225 
226  if stop_iteration is None:
227  stop_iteration = len(observer)
228 
229  line_best, = ax.plot(observer.get_global_best()['fitness_function'][start_iteration:stop_iteration], 'r')
230  line_current, = ax.plot(observer.get_population_best()['fitness_function'][start_iteration:stop_iteration], 'k')
231  line_mean, = ax.plot(observer.get_mean_fitness_function()[start_iteration:stop_iteration], 'c')
232 
233  if start_iteration < (stop_iteration - 1):
234  ax.set_xlim([start_iteration, (stop_iteration - 1)])
235 
236  ax.set_xlabel("Iteration")
237  ax.set_ylabel("Fitness function")
238  ax.legend([line_best, line_current, line_mean], ["The best pop.", "Cur. best pop.", "Average"], prop={'size': 10})
239  ax.grid()
240 
241  if display is True:
242  plt.show()
243 
244  return ax
245 
246 
247  @staticmethod
248  def show_clusters(data, observer, marker='.', markersize=None):
249  """!
250  @brief Shows allocated clusters by the genetic algorithm.
251 
252  @param[in] data (list): Input data that was used for clustering process by the algorithm.
253  @param[in] observer (ga_observer): Observer that was used for collection information about clustering process.
254  @param[in] marker (char): Type of marker that should be used for object (point) representation.
255  @param[in] markersize (uint): Size of the marker that is used for object (point) representation.
256 
257  @note If you have clusters instead of observer then 'cluster_visualizer' can be used for visualization purposes.
258 
259  @see cluster_visualizer
260 
261  """
262 
263  figure = plt.figure()
264  ax1 = figure.add_subplot(121)
265 
266  clusters = ga_math.get_clusters_representation(observer.get_global_best()['chromosome'][-1])
267 
268  visualizer = cluster_visualizer(1, 2)
269  visualizer.append_clusters(clusters, data, 0, marker, markersize)
270  visualizer.show(figure, display=False)
271 
272  ga_visualizer.show_evolution(observer, 0, None, ax1, True)
273 
274 
275  @staticmethod
276  def animate_cluster_allocation(data, observer, animation_velocity=75, movie_fps=5, save_movie=None):
277  """!
278  @brief Animate clustering process of genetic clustering algorithm.
279  @details This method can be also used for rendering movie of clustering process and 'ffmpeg' is required for that purpuse.
280 
281  @param[in] data (list): Input data that was used for clustering process by the algorithm.
282  @param[in] observer (ga_observer): Observer that was used for collection information about clustering process.
283  Be sure that whole information was collected by the observer.
284  @param[in] animation_velocity (uint): Interval between frames in milliseconds (for run-time animation only).
285  @param[in] movie_fps (uint): Defines frames per second (for rendering movie only).
286  @param[in] save_movie (string): If it is specified then animation will be stored to file that is specified in this parameter.
287 
288  """
289 
290  figure = plt.figure()
291 
292  def init_frame():
293  return frame_generation(0)
294 
295  def frame_generation(index_iteration):
296  figure.clf()
297 
298  figure.suptitle("Clustering genetic algorithm (iteration: " + str(index_iteration) + ")", fontsize=18, fontweight='bold')
299 
300  visualizer = cluster_visualizer(4, 2, ["The best pop. on step #" + str(index_iteration), "The best population"])
301 
302  local_minimum_clusters = ga_math.get_clusters_representation(observer.get_population_best()['chromosome'][index_iteration])
303  visualizer.append_clusters(local_minimum_clusters, data, 0)
304 
305  global_minimum_clusters = ga_math.get_clusters_representation(observer.get_global_best()['chromosome'][index_iteration])
306  visualizer.append_clusters(global_minimum_clusters, data, 1)
307 
308  ax1 = plt.subplot2grid((2, 2), (1, 0), colspan=2)
309  ga_visualizer.show_evolution(observer, 0, index_iteration + 1, ax1, False)
310 
311  visualizer.show(figure, shift=0, display=False)
312  figure.subplots_adjust(top=0.85)
313 
314  return [figure.gca()]
315 
316  iterations = len(observer)
317  cluster_animation = animation.FuncAnimation(figure, frame_generation, iterations, interval=animation_velocity, init_func=init_frame, repeat_delay=5000)
318 
319  if save_movie is not None:
320  cluster_animation.save(save_movie, writer='ffmpeg', fps=movie_fps, bitrate=1500)
321  else:
322  plt.show()
323 
324 
326  """!
327  @brief Class represents Genetic clustering algorithm.
328  @details The searching capability of genetic algorithms is exploited in order to search for appropriate
329  cluster centres.
330 
331  Example of clustering using genetic algorithm:
332  @code
333  from pyclustering.cluster.ga import genetic_algorithm, ga_observer
334  from pyclustering.utils import read_sample
335  from pyclustering.samples.definitions import SIMPLE_SAMPLES
336 
337 
338  # Read input data for clustering
339  sample = read_sample(SIMPLE_SAMPLES.SAMPLE_SIMPLE4)
340 
341  # Create instance of observer that will collect all information:
342  observer_instance = ga_observer(True, True, True)
343 
344  # Create genetic algorithm for clustering
345  ga_instance = genetic_algorithm(data=sample,
346  count_clusters=4,
347  chromosome_count=100,
348  population_count=200,
349  count_mutation_gens=1)
350 
351  # Start processing
352  ga_instance.process()
353 
354  # Obtain results
355  clusters = ga_instance.get_clusters()
356 
357  # Print cluster to console
358  print("Amount of clusters: '%d'. Clusters: '%s'" % (len(clusters), clusters))
359  @endcode
360 
361  There is an example of clustering results (fitness function evolution and allocated clusters) that were
362  visualized by 'ga_visualizer':
363 
364  @image html ga_clustering_sample_simple_04.png
365 
366  @see ga_visualizer
367  @see ga_observer
368 
369  """
370 
371  def __init__(self, data, count_clusters, chromosome_count, population_count, **kwargs):
372  """!
373  @brief Initialize genetic clustering algorithm for cluster analysis.
374 
375  @param[in] data (numpy.array|list): Input data for clustering that is represented by two dimensional array
376  where each row is a point, for example, [[0.0, 2.1], [0.1, 2.0], [-0.2, 2.4]].
377  @param[in] count_clusters (uint): Amount of clusters that should be allocated in the data.
378  @param[in] chromosome_count (uint): Amount of chromosomes in each population.
379  @param[in] population_count (uint): Amount of populations.
380  @param[in] **kwargs: Arbitrary keyword arguments (available arguments: 'count_mutation_gens', 'coeff_mutation_count', 'select_coeff', 'crossover_rate', 'observer').
381 
382  <b>Keyword Args:</b><br>
383  - count_mutation_gens (uint): Amount of genes in chromosome that is mutated on each step.
384  - coeff_mutation_count (float): Percent of chromosomes for mutation, distributed in range (0, 1] and
385  thus amount of chromosomes is defined as follows: 'chromosome_count' * 'coeff_mutation_count'.
386  - select_coeff (float): Exponential coefficient for selection procedure that is used as follows:
387  math.exp(1 + fitness(chromosome) * select_coeff).
388  - crossover_rate (float): Crossover rate.
389  - observer (ga_observer): Observer that is used for collecting information of about clustering process on each step.
390 
391  """
392 
393  # Initialize random
394  np.random.seed()
395 
396  # Clustering data
397  if type(data) is list:
398  self._data = np.array(data)
399  else:
400  self._data = data
401 
402  # Count clusters
403  self._count_clusters = count_clusters
404 
405  # Home many chromosome in population
406  self._chromosome_count = chromosome_count
407 
408  # How many populations
409  self._population_count = population_count
410 
411  # Count mutation genes
412  self._count_mutation_gens = kwargs.get('count_mutation_gens', 2)
413 
414  # Crossover rate
415  self._crossover_rate = kwargs.get('crossover_rate', 1.0)
416 
417  # Count of chromosome for mutation (range [0, 1])
418  self._coeff_mutation_count = kwargs.get('coeff_mutation_count', 0.25)
419 
420  # Exponential coeff for selection
421  self._select_coeff = kwargs.get('select_coeff', 1.0)
422 
423  # Result of clustering : best chromosome
424  self._result_clustering = {'best_chromosome': [],
425  'best_fitness_function': 0.0}
426 
427  # Observer
428  self._observer = kwargs.get('observer', ga_observer())
429 
430  def process(self):
431  """!
432  @brief Perform clustering procedure in line with rule of genetic clustering algorithm.
433 
434  @see get_clusters()
435 
436  """
437 
438  # Initialize population
439  chromosomes = self._init_population(self._count_clusters, len(self._data), self._chromosome_count)
440 
441  # Initialize the Best solution
442  best_chromosome, best_ff, first_fitness_functions \
443  = self._get_best_chromosome(chromosomes, self._data, self._count_clusters)
444 
445  # Save best result into observer
446  if self._observer is not None:
447  self._observer.collect_global_best(best_chromosome, best_ff)
448  self._observer.collect_population_best(best_chromosome, best_ff)
449  self._observer.collect_mean(first_fitness_functions)
450 
451  # Next population
452  for _ in range(self._population_count):
453 
454  # Select
455  chromosomes = self._select(chromosomes, self._data, self._count_clusters, self._select_coeff)
456 
457  # Crossover
458  self._crossover(chromosomes)
459 
460  # Mutation
461  self._mutation(chromosomes, self._count_clusters, self._count_mutation_gens, self._coeff_mutation_count)
462 
463  # Update the Best Solution
464  new_best_chromosome, new_best_ff, fitness_functions \
465  = self._get_best_chromosome(chromosomes, self._data, self._count_clusters)
466 
467  # Get best chromosome
468  if new_best_ff < best_ff:
469  best_ff = new_best_ff
470  best_chromosome = new_best_chromosome
471 
472  # Save best result into observer
473  if self._observer is not None:
474  self._observer.collect_global_best(best_chromosome, best_ff)
475  self._observer.collect_population_best(new_best_chromosome, new_best_ff)
476  self._observer.collect_mean(fitness_functions)
477 
478  # Save result
479  self._result_clustering['best_chromosome'] = best_chromosome
480  self._result_clustering['best_fitness_function'] = best_ff
481 
482  return best_chromosome, best_ff
483 
484 
485  def get_observer(self):
486  """!
487  @brief Returns genetic algorithm observer.
488 
489  """
490  return self._observer
491 
492 
493  def get_clusters(self):
494  """!
495  @brief Returns list of allocated clusters, each cluster contains indexes of objects from the data.
496 
497  @return (list) List of allocated clusters.
498 
499  @see process()
500 
501  """
502 
503  return ga_math.get_clusters_representation(self._result_clustering['best_chromosome'], self._count_clusters)
504 
505 
506  @staticmethod
507  def _select(chromosomes, data, count_clusters, select_coeff):
508  """!
509  @brief Performs selection procedure where new chromosomes are calculated.
510 
511  @param[in] chromosomes (numpy.array): Chromosomes
512 
513  """
514 
515  # Calc centers
516  centres = ga_math.get_centres(chromosomes, data, count_clusters)
517 
518  # Calc fitness functions
519  fitness = genetic_algorithm._calc_fitness_function(centres, data, chromosomes)
520 
521  for _idx in range(len(fitness)):
522  fitness[_idx] = math.exp(1 + fitness[_idx] * select_coeff)
523 
524  # Calc probability vector
525  probabilities = ga_math.calc_probability_vector(fitness)
526 
527  # Select P chromosomes with probabilities
528  new_chromosomes = np.zeros(chromosomes.shape, dtype=np.int)
529 
530  # Selecting
531  for _idx in range(len(chromosomes)):
532  new_chromosomes[_idx] = chromosomes[ga_math.get_uniform(probabilities)]
533 
534  return new_chromosomes
535 
536 
537  @staticmethod
538  def _crossover(chromosomes):
539  """!
540  @brief Crossover procedure.
541 
542  """
543 
544  # Get pairs to Crossover
545  pairs_to_crossover = np.array(range(len(chromosomes)))
546 
547  # Set random pairs
548  np.random.shuffle(pairs_to_crossover)
549 
550  # Index offset ( pairs_to_crossover split into 2 parts : [V1, V2, .. | P1, P2, ...] crossover between V<->P)
551  offset_in_pair = int(len(pairs_to_crossover) / 2)
552 
553  # For each pair
554  for _idx in range(offset_in_pair):
555 
556  # Generate random mask for crossover
557  crossover_mask = genetic_algorithm._get_crossover_mask(len(chromosomes[_idx]))
558 
559  # Crossover a pair
560  genetic_algorithm._crossover_a_pair(chromosomes[pairs_to_crossover[_idx]],
561  chromosomes[pairs_to_crossover[_idx + offset_in_pair]],
562  crossover_mask)
563 
564 
565  @staticmethod
566  def _mutation(chromosomes, count_clusters, count_gen_for_mutation, coeff_mutation_count):
567  """!
568  @brief Mutation procedure.
569 
570  """
571 
572  # Count gens in Chromosome
573  count_gens = len(chromosomes[0])
574 
575  # Get random chromosomes for mutation
576  random_idx_chromosomes = np.array(range(len(chromosomes)))
577  np.random.shuffle(random_idx_chromosomes)
578 
579  #
580  for _idx_chromosome in range(int(len(random_idx_chromosomes) * coeff_mutation_count)):
581 
582  #
583  for _ in range(count_gen_for_mutation):
584 
585  # Get random gen
586  gen_num = np.random.randint(count_gens)
587 
588  # Set random cluster
589  chromosomes[random_idx_chromosomes[_idx_chromosome]][gen_num] = np.random.randint(count_clusters)
590 
591 
592  @staticmethod
593  def _crossover_a_pair(chromosome_1, chromosome_2, mask):
594  """!
595  @brief Crossovers a pair of chromosomes.
596 
597  @param[in] chromosome_1 (numpy.array): The first chromosome for crossover.
598  @param[in] chromosome_2 (numpy.array): The second chromosome for crossover.
599  @param[in] mask (numpy.array): Crossover mask that defines which genes should be swapped.
600 
601  """
602 
603  for _idx in range(len(chromosome_1)):
604 
605  if mask[_idx] == 1:
606  # Swap values
607  chromosome_1[_idx], chromosome_2[_idx] = chromosome_2[_idx], chromosome_1[_idx]
608 
609 
610  @staticmethod
611  def _get_crossover_mask(mask_length):
612  """!
613  @brief Crossover mask to crossover a pair of chromosomes.
614 
615  @param[in] mask_length (uint): Length of the mask.
616 
617  """
618 
619  # Initialize mask
620  mask = np.zeros(mask_length)
621 
622  # Set a half of array to 1
623  mask[:int(int(mask_length) / 2)] = 1
624 
625  # Random shuffle
626  np.random.shuffle(mask)
627 
628  return mask
629 
630 
631  @staticmethod
632  def _init_population(count_clusters, count_data, chromosome_count):
633  """!
634  @brief Returns first population as a uniform random choice.
635 
636  @param[in] count_clusters (uint): Amount of clusters that should be allocated.
637  @param[in] count_data (uint): Data size that is used for clustering process.
638  @param[in] chromosome_count (uint):Amount of chromosome that is used for clustering.
639 
640  """
641 
642  population = np.random.randint(count_clusters, size=(chromosome_count, count_data))
643 
644  return population
645 
646 
647  @staticmethod
648  def _get_best_chromosome(chromosomes, data, count_clusters):
649  """!
650  @brief Returns the current best chromosome.
651 
652  @param[in] chromosomes (list): Chromosomes that are used for searching.
653  @param[in] data (list): Input data that is used for clustering process.
654  @param[in] count_clusters (uint): Amount of clusters that should be allocated.
655 
656  @return (list, float, list) The best chromosome, its fitness function value and fitness function values for
657  all chromosomes.
658 
659  """
660 
661  # Calc centers
662  centres = ga_math.get_centres(chromosomes, data, count_clusters)
663 
664  # Calc Fitness functions
665  fitness_functions = genetic_algorithm._calc_fitness_function(centres, data, chromosomes)
666 
667  # Index of the best chromosome
668  best_chromosome_idx = fitness_functions.argmin()
669 
670  # Get chromosome with the best fitness function
671  return chromosomes[best_chromosome_idx], fitness_functions[best_chromosome_idx], fitness_functions
672 
673 
674  @staticmethod
675  def _calc_fitness_function(centres, data, chromosomes):
676  """!
677  @brief Calculate fitness function values for chromosomes.
678 
679  @param[in] centres (list): Cluster centers.
680  @param[in] data (list): Input data that is used for clustering process.
681  @param[in] chromosomes (list): Chromosomes whose fitness function's values are calculated.
682 
683  @return (list) Fitness function value for each chromosome correspondingly.
684 
685  """
686 
687  # Get count of chromosomes and clusters
688  count_chromosome = len(chromosomes)
689 
690  # Initialize fitness function values
691  fitness_function = np.zeros(count_chromosome)
692 
693  # Calc fitness function for each chromosome
694  for _idx_chromosome in range(count_chromosome):
695 
696  # Get centers for a selected chromosome
697  centres_data = np.zeros(data.shape)
698 
699  # Fill data centres
700  for _idx in range(len(data)):
701  centres_data[_idx] = centres[_idx_chromosome][chromosomes[_idx_chromosome][_idx]]
702 
703  # Get City Block distance for a chromosome
704  fitness_function[_idx_chromosome] += np.sum(abs(data - centres_data))
705 
706  return fitness_function
Common visualizer of clusters on 1D, 2D or 3D surface.
Definition: __init__.py:359
def animate_cluster_allocation(data, observer, animation_velocity=75, movie_fps=5, save_movie=None)
Animate clustering process of genetic clustering algorithm.
Definition: ga.py:276
pyclustering module for cluster analysis.
Definition: __init__.py:1
Genetic algorithm visualizer is used to show clustering results that are specific for this particular...
Definition: ga.py:160
def __init__(self, need_global_best=False, need_population_best=False, need_mean_ff=False)
Constructs genetic algorithm observer to collect specific information.
Definition: ga.py:50
def collect_global_best(self, best_chromosome, best_fitness_function)
Stores the best chromosome and its fitness function&#39;s value.
Definition: ga.py:87
def collect_population_best(self, best_chromosome, best_fitness_function)
Stores the best chromosome for current specific iteration and its fitness function&#39;s value...
Definition: ga.py:103
def process(self)
Perform clustering procedure in line with rule of genetic clustering algorithm.
Definition: ga.py:430
def show_evolution(observer, start_iteration=0, stop_iteration=None, ax=None, display=True)
Displays evolution of fitness function for the best chromosome, for the current best chromosome and a...
Definition: ga.py:205
def __len__(self)
Returns amount of iterations that genetic algorithm was observed.
Definition: ga.py:75
def _crossover(chromosomes)
Crossover procedure.
Definition: ga.py:538
Class represents Genetic clustering algorithm.
Definition: ga.py:325
def _get_best_chromosome(chromosomes, data, count_clusters)
Returns the current best chromosome.
Definition: ga.py:648
def _init_population(count_clusters, count_data, chromosome_count)
Returns first population as a uniform random choice.
Definition: ga.py:632
def _select(chromosomes, data, count_clusters, select_coeff)
Performs selection procedure where new chromosomes are calculated.
Definition: ga.py:507
def __init__(self, data, count_clusters, chromosome_count, population_count, kwargs)
Initialize genetic clustering algorithm for cluster analysis.
Definition: ga.py:371
Genetic algorithm observer that is used to collect information about clustering process on each itera...
Definition: ga.py:44
def collect_mean(self, fitness_functions)
Stores average value of fitness function among chromosomes on specific iteration. ...
Definition: ga.py:119
def get_population_best(self)
(dict) Returns dictionary with keys &#39;chromosome&#39; and &#39;fitness_function&#39; where evolution of the curren...
Definition: ga.py:142
def get_observer(self)
Returns genetic algorithm observer.
Definition: ga.py:485
def get_mean_fitness_function(self)
(list) Returns fitness function&#39;s values on each iteration.
Definition: ga.py:151
def show_clusters(data, observer, marker='.', markersize=None)
Shows allocated clusters by the genetic algorithm.
Definition: ga.py:248
def get_clusters(self)
Returns list of allocated clusters, each cluster contains indexes of objects from the data...
Definition: ga.py:493
def _mutation(chromosomes, count_clusters, count_gen_for_mutation, coeff_mutation_count)
Mutation procedure.
Definition: ga.py:566