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-2020
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',
381  'coeff_mutation_count', 'select_coeff', 'crossover_rate', 'observer', 'random_state').
382 
383  <b>Keyword Args:</b><br>
384  - count_mutation_gens (uint): Amount of genes in chromosome that is mutated on each step.
385  - coeff_mutation_count (float): Percent of chromosomes for mutation, distributed in range (0, 1] and
386  thus amount of chromosomes is defined as follows: 'chromosome_count' * 'coeff_mutation_count'.
387  - select_coeff (float): Exponential coefficient for selection procedure that is used as follows:
388  math.exp(1 + fitness(chromosome) * select_coeff).
389  - crossover_rate (float): Crossover rate.
390  - observer (ga_observer): Observer that is used for collecting information of about clustering process on each step.
391  - random_state (int): Seed for random state (by default is `None`, current system time is used).
392 
393  """
394 
395  # Initialize random
396  np.random.seed(kwargs.get('random_state', None))
397 
398  # Clustering data
399  self._data = np.array(data)
400 
401  # Count clusters
402  self._count_clusters = count_clusters
403 
404  # Home many chromosome in population
405  self._chromosome_count = chromosome_count
406 
407  # How many populations
408  self._population_count = population_count
409 
410  # Count mutation genes
411  self._count_mutation_gens = kwargs.get('count_mutation_gens', 2)
412 
413  # Crossover rate
414  self._crossover_rate = kwargs.get('crossover_rate', 1.0)
415 
416  # Count of chromosome for mutation (range [0, 1])
417  self._coeff_mutation_count = kwargs.get('coeff_mutation_count', 0.25)
418 
419  # Exponential coeff for selection
420  self._select_coeff = kwargs.get('select_coeff', 1.0)
421 
422  # Result of clustering : best chromosome
423  self._result_clustering = {'best_chromosome': [],
424  'best_fitness_function': 0.0}
425 
426  # Observer
427  self._observer = kwargs.get('observer', ga_observer())
428 
429  self._verify_arguments()
430 
431 
432  def process(self):
433  """!
434  @brief Perform clustering procedure in line with rule of genetic clustering algorithm.
435 
436  @see get_clusters()
437 
438  """
439 
440  # Initialize population
441  chromosomes = self._init_population(self._count_clusters, len(self._data), self._chromosome_count)
442 
443  # Initialize the Best solution
444  best_chromosome, best_ff, first_fitness_functions \
445  = self._get_best_chromosome(chromosomes, self._data, self._count_clusters)
446 
447  # Save best result into observer
448  if self._observer is not None:
449  self._observer.collect_global_best(best_chromosome, best_ff)
450  self._observer.collect_population_best(best_chromosome, best_ff)
451  self._observer.collect_mean(first_fitness_functions)
452 
453  # Next population
454  for _ in range(self._population_count):
455 
456  # Select
457  chromosomes = self._select(chromosomes, self._data, self._count_clusters, self._select_coeff)
458 
459  # Crossover
460  self._crossover(chromosomes)
461 
462  # Mutation
463  self._mutation(chromosomes, self._count_clusters, self._count_mutation_gens, self._coeff_mutation_count)
464 
465  # Update the Best Solution
466  new_best_chromosome, new_best_ff, fitness_functions \
467  = self._get_best_chromosome(chromosomes, self._data, self._count_clusters)
468 
469  # Get best chromosome
470  if new_best_ff < best_ff:
471  best_ff = new_best_ff
472  best_chromosome = new_best_chromosome
473 
474  # Save best result into observer
475  if self._observer is not None:
476  self._observer.collect_global_best(best_chromosome, best_ff)
477  self._observer.collect_population_best(new_best_chromosome, new_best_ff)
478  self._observer.collect_mean(fitness_functions)
479 
480  # Save result
481  self._result_clustering['best_chromosome'] = best_chromosome
482  self._result_clustering['best_fitness_function'] = best_ff
483 
484  return best_chromosome, best_ff
485 
486 
487  def get_observer(self):
488  """!
489  @brief Returns genetic algorithm observer.
490 
491  """
492  return self._observer
493 
494 
495  def get_clusters(self):
496  """!
497  @brief Returns list of allocated clusters, each cluster contains indexes of objects from the data.
498 
499  @return (list) List of allocated clusters.
500 
501  @see process()
502 
503  """
504 
505  return ga_math.get_clusters_representation(self._result_clustering['best_chromosome'], self._count_clusters)
506 
507 
508  @staticmethod
509  def _select(chromosomes, data, count_clusters, select_coeff):
510  """!
511  @brief Performs selection procedure where new chromosomes are calculated.
512 
513  @param[in] chromosomes (numpy.array): Chromosomes
514 
515  """
516 
517  # Calc centers
518  centres = ga_math.get_centres(chromosomes, data, count_clusters)
519 
520  # Calc fitness functions
521  fitness = genetic_algorithm._calc_fitness_function(centres, data, chromosomes)
522 
523  for _idx in range(len(fitness)):
524  fitness[_idx] = math.exp(1 + fitness[_idx] * select_coeff)
525 
526  # Calc probability vector
527  probabilities = ga_math.calc_probability_vector(fitness)
528 
529  # Select P chromosomes with probabilities
530  new_chromosomes = np.zeros(chromosomes.shape, dtype=np.int)
531 
532  # Selecting
533  for _idx in range(len(chromosomes)):
534  new_chromosomes[_idx] = chromosomes[ga_math.get_uniform(probabilities)]
535 
536  return new_chromosomes
537 
538 
539  @staticmethod
540  def _crossover(chromosomes):
541  """!
542  @brief Crossover procedure.
543 
544  """
545 
546  # Get pairs to Crossover
547  pairs_to_crossover = np.array(range(len(chromosomes)))
548 
549  # Set random pairs
550  np.random.shuffle(pairs_to_crossover)
551 
552  # Index offset ( pairs_to_crossover split into 2 parts : [V1, V2, .. | P1, P2, ...] crossover between V<->P)
553  offset_in_pair = int(len(pairs_to_crossover) / 2)
554 
555  # For each pair
556  for _idx in range(offset_in_pair):
557 
558  # Generate random mask for crossover
559  crossover_mask = genetic_algorithm._get_crossover_mask(len(chromosomes[_idx]))
560 
561  # Crossover a pair
562  genetic_algorithm._crossover_a_pair(chromosomes[pairs_to_crossover[_idx]],
563  chromosomes[pairs_to_crossover[_idx + offset_in_pair]],
564  crossover_mask)
565 
566 
567  @staticmethod
568  def _mutation(chromosomes, count_clusters, count_gen_for_mutation, coeff_mutation_count):
569  """!
570  @brief Mutation procedure.
571 
572  """
573 
574  # Count gens in Chromosome
575  count_gens = len(chromosomes[0])
576 
577  # Get random chromosomes for mutation
578  random_idx_chromosomes = np.array(range(len(chromosomes)))
579  np.random.shuffle(random_idx_chromosomes)
580 
581  #
582  for _idx_chromosome in range(int(len(random_idx_chromosomes) * coeff_mutation_count)):
583 
584  #
585  for _ in range(count_gen_for_mutation):
586 
587  # Get random gen
588  gen_num = np.random.randint(count_gens)
589 
590  # Set random cluster
591  chromosomes[random_idx_chromosomes[_idx_chromosome]][gen_num] = np.random.randint(count_clusters)
592 
593 
594  @staticmethod
595  def _crossover_a_pair(chromosome_1, chromosome_2, mask):
596  """!
597  @brief Crossovers a pair of chromosomes.
598 
599  @param[in] chromosome_1 (numpy.array): The first chromosome for crossover.
600  @param[in] chromosome_2 (numpy.array): The second chromosome for crossover.
601  @param[in] mask (numpy.array): Crossover mask that defines which genes should be swapped.
602 
603  """
604 
605  for _idx in range(len(chromosome_1)):
606 
607  if mask[_idx] == 1:
608  # Swap values
609  chromosome_1[_idx], chromosome_2[_idx] = chromosome_2[_idx], chromosome_1[_idx]
610 
611 
612  @staticmethod
613  def _get_crossover_mask(mask_length):
614  """!
615  @brief Crossover mask to crossover a pair of chromosomes.
616 
617  @param[in] mask_length (uint): Length of the mask.
618 
619  """
620 
621  # Initialize mask
622  mask = np.zeros(mask_length)
623 
624  # Set a half of array to 1
625  mask[:int(int(mask_length) / 2)] = 1
626 
627  # Random shuffle
628  np.random.shuffle(mask)
629 
630  return mask
631 
632 
633  @staticmethod
634  def _init_population(count_clusters, count_data, chromosome_count):
635  """!
636  @brief Returns first population as a uniform random choice.
637 
638  @param[in] count_clusters (uint): Amount of clusters that should be allocated.
639  @param[in] count_data (uint): Data size that is used for clustering process.
640  @param[in] chromosome_count (uint):Amount of chromosome that is used for clustering.
641 
642  """
643 
644  population = np.random.randint(count_clusters, size=(chromosome_count, count_data))
645 
646  return population
647 
648 
649  @staticmethod
650  def _get_best_chromosome(chromosomes, data, count_clusters):
651  """!
652  @brief Returns the current best chromosome.
653 
654  @param[in] chromosomes (list): Chromosomes that are used for searching.
655  @param[in] data (list): Input data that is used for clustering process.
656  @param[in] count_clusters (uint): Amount of clusters that should be allocated.
657 
658  @return (list, float, list) The best chromosome, its fitness function value and fitness function values for
659  all chromosomes.
660 
661  """
662 
663  # Calc centers
664  centres = ga_math.get_centres(chromosomes, data, count_clusters)
665 
666  # Calc Fitness functions
667  fitness_functions = genetic_algorithm._calc_fitness_function(centres, data, chromosomes)
668 
669  # Index of the best chromosome
670  best_chromosome_idx = fitness_functions.argmin()
671 
672  # Get chromosome with the best fitness function
673  return chromosomes[best_chromosome_idx], fitness_functions[best_chromosome_idx], fitness_functions
674 
675 
676  @staticmethod
677  def _calc_fitness_function(centres, data, chromosomes):
678  """!
679  @brief Calculate fitness function values for chromosomes.
680 
681  @param[in] centres (list): Cluster centers.
682  @param[in] data (list): Input data that is used for clustering process.
683  @param[in] chromosomes (list): Chromosomes whose fitness function's values are calculated.
684 
685  @return (list) Fitness function value for each chromosome correspondingly.
686 
687  """
688 
689  # Get count of chromosomes and clusters
690  count_chromosome = len(chromosomes)
691 
692  # Initialize fitness function values
693  fitness_function = np.zeros(count_chromosome)
694 
695  # Calc fitness function for each chromosome
696  for _idx_chromosome in range(count_chromosome):
697 
698  # Get centers for a selected chromosome
699  centres_data = np.zeros(data.shape)
700 
701  # Fill data centres
702  for _idx in range(len(data)):
703  centres_data[_idx] = centres[_idx_chromosome][chromosomes[_idx_chromosome][_idx]]
704 
705  # Get City Block distance for a chromosome
706  fitness_function[_idx_chromosome] += np.sum(abs(data - centres_data))
707 
708  return fitness_function
709 
710 
711  def _verify_arguments(self):
712  """!
713  @brief Verify input parameters for the algorithm and throw exception in case of incorrectness.
714 
715  """
716  if len(self._data) == 0:
717  raise ValueError("Input data is empty (size: '%d')." % len(self._data))
718 
719  if self._count_clusters <= 0:
720  raise ValueError("Amount of cluster (current value: '%d') for allocation should be greater than 0." %
721  self._count_clusters)
Common visualizer of clusters on 1D, 2D or 3D surface.
Definition: __init__.py:390
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:432
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:540
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:650
def _init_population(count_clusters, count_data, chromosome_count)
Returns first population as a uniform random choice.
Definition: ga.py:634
def _select(chromosomes, data, count_clusters, select_coeff)
Performs selection procedure where new chromosomes are calculated.
Definition: ga.py:509
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 _verify_arguments(self)
Verify input parameters for the algorithm and throw exception in case of incorrectness.
Definition: ga.py:711
def get_observer(self)
Returns genetic algorithm observer.
Definition: ga.py:487
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:495
def _mutation(chromosomes, count_clusters, count_gen_for_mutation, coeff_mutation_count)
Mutation procedure.
Definition: ga.py:568