clusters = [[] for i in range(len(self.__medians))]<EOL>for index_point in range(len(self.__pointer_data)):<EOL><INDENT>index_optim = -<NUM_LIT:1><EOL>dist_optim = <NUM_LIT:0.0><EOL>for index in range(len(self.__medians)):<EOL><INDENT>dist = self.__metric(self.__pointer_data[index_point], self.__medians[index])<EOL>if (dist < dist_optim) or (index == <NUM_LIT:0>):<EOL><INDENT>index_optim = index<EOL>dist_optim = dist<EOL><DEDENT><DEDENT>clusters[index_optim].append(index_point)<EOL><DEDENT>clusters = [cluster for cluster in clusters if len(cluster) > <NUM_LIT:0>]<EOL>return clusters<EOL>

!
        @brief Calculate Manhattan distance to each point from the each cluster.
        @details Nearest points are captured by according clusters and as a result clusters are updated.

        @return (list) updated clusters as list of clusters where each cluster contains indexes of objects from data.


volume = <NUM_LIT:0.0><EOL>for i in range(<NUM_LIT:0>, len(self.__max_corner)):<EOL><INDENT>side_length = self.__max_corner[i] - self.__min_corner[i]<EOL>if side_length != <NUM_LIT:0.0>:<EOL><INDENT>if volume == <NUM_LIT:0.0>: volume = side_length<EOL>else: volume *= side_length<EOL><DEDENT><DEDENT>return volume<EOL>

!
        @brief Calculates volume of current spatial block.
        @details If empty dimension is detected (where all points has the same value) then such dimension is ignored
                  during calculation of volume.

        @return (double) Volume of current spatial block.


if len(self.__directory.get_data()[<NUM_LIT:0>]) != <NUM_LIT:2>:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>

!
        @brief Check correctness of input arguments and throw exception if incorrect is found.


def split(self, split_dimension, cache_points):

left_region_number = self.__region_number<EOL>right_region_number = self.__region_number + <NUM_LIT:2> ** self.__level<EOL>first_spatial_block, second_spatial_block = self.__spatial_block.split(split_dimension)<EOL>left = bang_block(self.__data, left_region_number, self.__level + <NUM_LIT:1>, first_spatial_block, cache_points)<EOL>right = bang_block(self.__data, right_region_number, self.__level + <NUM_LIT:1>, second_spatial_block, cache_points)<EOL>return left, right<EOL>

!
        @brief Split BANG-block into two new blocks in specified dimension.

        @param[in] split_dimension (uint): Dimension where block should be split.
        @param[in] cache_points (bool): If True then covered points are cached. Used for leaf blocks.

        @return (tuple) Pair of BANG-block that were formed from the current.


return self.__directory<EOL>

!
        @brief Returns grid directory that describes grid of the processed data.

        @remark Grid directory is returned only after data processing (method process()). Otherwise None value is returned.

        @return (bang_directory) BANG directory that describes grid of process data.

        @see process()


return self.__dendrogram<EOL>

!
        @brief Returns dendrogram of clusters.
        @details Dendrogram is created in following way: the density indices of all regions are calculated and sorted
                  in decreasing order for each cluster during clustering process.

        @remark Dendrogram is returned only after data processing (method process()). Otherwise empty list is returned.


def __init__(self, max_corner, min_corner):

self.__max_corner = max_corner<EOL>self.__min_corner = min_corner<EOL>self.__volume = self.__calculate_volume()<EOL>

!
        @brief Creates spatial block in data space.

        @param[in] max_corner (array_like): Maximum corner coordinates of the block.
        @param[in] min_corner (array_like): Minimal corner coordinates of the block.


def __expand_cluster_block(self, block, cluster_index, leaf_blocks, unhandled_block_indexes):

block.set_cluster(cluster_index)<EOL>self.__update_cluster_dendrogram(cluster_index, [block])<EOL>neighbors = self.__find_block_neighbors(block, leaf_blocks, unhandled_block_indexes)<EOL>self.__update_cluster_dendrogram(cluster_index, neighbors)<EOL>for neighbor in neighbors:<EOL><INDENT>neighbor.set_cluster(cluster_index)<EOL>neighbor_neighbors = self.__find_block_neighbors(neighbor, leaf_blocks, unhandled_block_indexes)<EOL>self.__update_cluster_dendrogram(cluster_index, neighbor_neighbors)<EOL>neighbors += neighbor_neighbors<EOL><DEDENT>

!
        @brief Expand cluster from specific block that is considered as a central block.

        @param[in] block (bang_block): Block that is considered as a central block for cluster.
        @param[in] cluster_index (uint): Index of cluster that is assigned to blocks that forms new cluster.
        @param[in] leaf_blocks (list): Leaf BANG-blocks that are considered during cluster formation.
        @param[in] unhandled_block_indexes (set): Set of candidates (BANG block indexes) to become a cluster member. The
                    parameter helps to reduce traversing among BANG-block providing only restricted set of block that
                    should be considered.


self.__cache_points = True<EOL>self.__points = []<EOL>for index_point in range(len(self.__data)):<EOL><INDENT>if self.__data[index_point] in self.__spatial_block:<EOL><INDENT>self.__cache_point(index_point)<EOL><DEDENT><DEDENT>


@staticmethod<EOL><INDENT>def __draw_blocks(ax, blocks, pair):<DEDENT>

ax.grid(False)<EOL>density_scale = blocks[-<NUM_LIT:1>].get_density()<EOL>for block in blocks:<EOL><INDENT>bang_visualizer.__draw_block(ax, pair, block, density_scale)<EOL><DEDENT>

!
        @brief Display BANG-blocks on specified figure.

        @param[in] ax (Axis): Axis where bang-blocks should be displayed.
        @param[in] blocks (list): List of blocks that should be displyed.
        @param[in] pair (tuple): Pair of coordinate index that should be displayed.


for i in range(len(point)):<EOL><INDENT>if point[i] < self.__min_corner[i] or point[i] > self.__max_corner[i]:<EOL><INDENT>return False<EOL><DEDENT><DEDENT>return True<EOL>

!
        @brief Point is considered as contained if it lies in block (belong to it).

        @return (bool) True if point is in block, otherwise False.


@staticmethod<EOL><INDENT>def __draw_block(ax, pair, block, density_scale):<DEDENT>

max_corner, min_corner = bang_visualizer.__get_rectangle_description(block, pair)<EOL>belong_cluster = block.get_cluster() is not None<EOL>if density_scale != <NUM_LIT:0.0>:<EOL><INDENT>density_scale = bang_visualizer.__maximum_density_alpha * block.get_density() / density_scale<EOL><DEDENT>face_color = matplotlib.colors.to_rgba('<STR_LIT>', alpha=density_scale)<EOL>edge_color = matplotlib.colors.to_rgba('<STR_LIT>', alpha=<NUM_LIT:1.0>)<EOL>rect = patches.Rectangle(min_corner, max_corner[<NUM_LIT:0>] - min_corner[<NUM_LIT:0>], max_corner[<NUM_LIT:1>] - min_corner[<NUM_LIT:1>],<EOL>fill=belong_cluster,<EOL>facecolor=face_color,<EOL>edgecolor=edge_color,<EOL>linewidth=<NUM_LIT:0.5>)<EOL>ax.add_patch(rect)<EOL>

!
        @brief Display BANG-block on the specified ax.

        @param[in] ax (Axis): Axis where block should be displayed.
        @param[in] pair (tuple): Pair of coordinate index that should be displayed.
        @param[in] block (bang_block): BANG-block that should be displayed.
        @param[in] density_scale (double): Max density to display density of the block by appropriate tone.


@staticmethod<EOL><INDENT>def __draw_two_dimension_data(ax, data, pair):<DEDENT>

ax.set_xlabel("<STR_LIT>" % pair[<NUM_LIT:0>])<EOL>ax.set_ylabel("<STR_LIT>" % pair[<NUM_LIT:1>])<EOL>for point in data:<EOL><INDENT>if len(data[<NUM_LIT:0>]) > <NUM_LIT:1>:<EOL><INDENT>ax.plot(point[pair[<NUM_LIT:0>]], point[pair[<NUM_LIT:1>]], color='<STR_LIT>', marker='<STR_LIT:.>')<EOL><DEDENT>else:<EOL><INDENT>ax.plot(point[pair[<NUM_LIT:0>]], <NUM_LIT:0>, color='<STR_LIT>', marker='<STR_LIT:.>')<EOL>ax.yaxis.set_ticklabels([])<EOL><DEDENT><DEDENT>

!
        @brief Display data in two-dimensional canvas.

        @param[in] ax (Axis): Canvas where data should be displayed.
        @param[in] data (list): Data points that should be displayed.
        @param[in] pair (tuple): Pair of dimension indexes.


if self.__points is None:<EOL><INDENT>self.__cache_covered_data()<EOL><DEDENT>return self.__points<EOL>

!
        @brief Return points that covers by the BANG-block.

        @return (list) List of point indexes that are covered by the block.


previous_level_blocks = [ self.__root ]<EOL>for level in range(<NUM_LIT:1>, self.__levels):<EOL><INDENT>previous_level_blocks = self.__build_level(previous_level_blocks, level)<EOL>self.__store_level_blocks(previous_level_blocks)<EOL><DEDENT>self.__leafs = sorted(self.__leafs, key=lambda block: block.get_density())<EOL>

!
        @brief Build levels of direction if amount of level is greater than one.


return type_encoding.CLUSTER_INDEX_LIST_SEPARATION<EOL>

!
        @brief Returns clustering result representation type that indicate how clusters are encoded.

        @return (type_encoding) Clustering result representation.

        @see get_clusters()


def __find_block_neighbors(self, block, level_blocks, unhandled_block_indexes):

neighbors = []<EOL>handled_block_indexes = []<EOL>for unhandled_index in unhandled_block_indexes:<EOL><INDENT>if block.is_neighbor(level_blocks[unhandled_index]):<EOL><INDENT>handled_block_indexes.append(unhandled_index)<EOL>neighbors.append(level_blocks[unhandled_index])<EOL>if len(neighbors) == <NUM_LIT:8>:<EOL><INDENT>break<EOL><DEDENT><DEDENT><DEDENT>for handled_index in handled_block_indexes:<EOL><INDENT>unhandled_block_indexes.remove(handled_index)<EOL><DEDENT>return neighbors<EOL>

!
        @brief Search block neighbors that are parts of new clusters (density is greater than threshold and that are
                not cluster members yet), other neighbors are ignored.

        @param[in] block (bang_block): BANG-block for which neighbors should be found (which can be part of cluster).
        @param[in] level_blocks (list): BANG-blocks on specific level.
        @param[in] unhandled_block_indexes (set): Blocks that have not been processed yet.

        @return (list) Block neighbors that can become part of cluster.


if self.__levels <= <NUM_LIT:0>:<EOL><INDENT>raise ValueError("<STR_LIT>" % self.__levels)<EOL><DEDENT>if len(self.__data) == <NUM_LIT:0>:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>if self.__density_threshold < <NUM_LIT:0>:<EOL><INDENT>raise ValueError("<STR_LIT>" % self.__density_threshold)<EOL><DEDENT>

!
        @brief Check input arguments of BANG algorithm and if one of them is not correct then appropriate exception
                is thrown.


if block is not self:<EOL><INDENT>block_max_corner, _ = block.get_corners()<EOL>dimension = len(block_max_corner)<EOL>neighborhood_score = self.__calculate_neighborhood(block_max_corner)<EOL>if neighborhood_score == dimension:<EOL><INDENT>return True<EOL><DEDENT><DEDENT>return False<EOL>

!
        @brief Performs calculation to identify whether specified block is neighbor of current block.
        @details It also considers diagonal blocks as neighbors.

        @param[in] block (spatial_block): Another block that is check whether it is neighbor.

        @return (bool) True is blocks are neighbors, False otherwise.


dimension = len(directory.get_data()[<NUM_LIT:0>])<EOL>amount_canvases = <NUM_LIT:1><EOL>if dimension > <NUM_LIT:1>:<EOL><INDENT>amount_canvases = int(dimension * (dimension - <NUM_LIT:1>) / <NUM_LIT:2>)<EOL><DEDENT>figure = plt.figure()<EOL>grid_spec = gridspec.GridSpec(<NUM_LIT:1>, amount_canvases)<EOL>pairs = list(itertools.combinations(range(dimension), <NUM_LIT:2>))<EOL>if len(pairs) == <NUM_LIT:0>: pairs = [(<NUM_LIT:0>, <NUM_LIT:0>)]<EOL>for index in range(amount_canvases):<EOL><INDENT>ax = figure.add_subplot(grid_spec[index])<EOL>bang_visualizer.__draw_blocks(ax, directory.get_leafs(), pairs[index])<EOL>bang_visualizer.__draw_two_dimension_data(ax, directory.get_data(), pairs[index])<EOL><DEDENT>plt.show()<EOL>

!
        @brief Show BANG-blocks (leafs only) in data space.
        @details BANG-blocks represents grid that was used for clustering process.

        @param[in] directory (bang_directory): Directory that was created by BANG algorithm during clustering process.


leaf_blocks = self.__directory.get_leafs()<EOL>unhandled_block_indexes = set([i for i in range(len(leaf_blocks)) if leaf_blocks[i].get_density() > self.__density_threshold])<EOL>current_block = self.__find_block_center(leaf_blocks, unhandled_block_indexes)<EOL>cluster_index = <NUM_LIT:0><EOL>while current_block is not None:<EOL><INDENT>if current_block.get_density() <= self.__density_threshold or len(current_block) <= self.__amount_threshold:<EOL><INDENT>break<EOL><DEDENT>self.__expand_cluster_block(current_block, cluster_index, leaf_blocks, unhandled_block_indexes)<EOL>current_block = self.__find_block_center(leaf_blocks, unhandled_block_indexes)<EOL>cluster_index += <NUM_LIT:1><EOL><DEDENT>self.__store_clustering_results(cluster_index, leaf_blocks)<EOL>

!
        @brief Performs cluster allocation using leafs of tree in BANG directory (the smallest cells).


def __init__(self, directory, clusters):

self.__directory = directory<EOL>self.__clusters = clusters<EOL>self.__noise = []<EOL>self.__current_block = <NUM_LIT:0><EOL>self.__current_level = <NUM_LIT:0><EOL>self.__level_blocks = directory.get_level(<NUM_LIT:0>)<EOL>self.__figure = plt.figure()<EOL>self.__ax = self.__figure.add_subplot(<NUM_LIT:1>, <NUM_LIT:1>, <NUM_LIT:1>)<EOL>self.__special_frame = <NUM_LIT:0><EOL>self.__validate_arguments()<EOL>

!
        @brief Creates BANG animator instance.

        @param[in] directory (bang_directory): BANG directory that was formed during BANG clustering process.
        @param[in] clusters (list): Allocated clusters during BANG clustering process.


@staticmethod<EOL><INDENT>def show_clusters(data, clusters, noise=None):<DEDENT>

visualizer = cluster_visualizer()<EOL>visualizer.append_clusters(clusters, data)<EOL>visualizer.append_cluster(noise or [], data, marker='<STR_LIT:x>')<EOL>visualizer.show()<EOL>

!
        @brief Display BANG clustering results.

        @param[in] data (list): Dataset that was used for clustering.
        @param[in] clusters (array_like): Clusters that were allocated by the algorithm.
        @param[in] noise (array_like): Noise that were allocated by the algorithm.


return len(self.__level_blocks)<EOL>

!
        @brief Returns height of BANG tree where blocks are stored.

        @return (uint) Height of BANG tree.


self.__current_block += <NUM_LIT:1><EOL>if self.__current_block >= len(self.__level_blocks):<EOL><INDENT>self.__current_block = <NUM_LIT:0><EOL>self.__current_level += <NUM_LIT:1><EOL>if self.__current_level < self.__directory.get_height():<EOL><INDENT>self.__level_blocks = self.__directory.get_level(self.__current_level)<EOL><DEDENT><DEDENT>

!
        @brief Increment BANG block safely by updating block index, level and level block.


return self.__region_number<EOL>

!
        @brief Returns region number of BANG-block.
        @details Region number is unique on among region numbers on a directory level. Pair of region number and level
                  is unique for all directory.

        @return (uint) Region number.


dimension = len(block_max_corner)<EOL>length_edges = [self.__max_corner[i] - self.__min_corner[i] for i in range(dimension)]<EOL>neighborhood_score = <NUM_LIT:0><EOL>for i in range(dimension):<EOL><INDENT>diff = abs(block_max_corner[i] - self.__max_corner[i])<EOL>if diff <= length_edges[i] + length_edges[i] * <NUM_LIT>:<EOL><INDENT>neighborhood_score += <NUM_LIT:1><EOL><DEDENT><DEDENT>return neighborhood_score<EOL>

!
        @brief Calculates neighborhood score that defined whether blocks are neighbors.

        @param[in] block_max_corner (list): Maximum coordinates of other block.

        @return (uint) Neighborhood score.


plt.figure()<EOL>axis = plt.subplot(<NUM_LIT:1>, <NUM_LIT:1>, <NUM_LIT:1>)<EOL>current_position = <NUM_LIT:0><EOL>for index_cluster in range(len(dendrogram)):<EOL><INDENT>densities = [ block.get_density() for block in dendrogram[index_cluster] ]<EOL>xrange = range(current_position, current_position + len(densities))<EOL>axis.bar(xrange, densities, <NUM_LIT:1.0>, linewidth=<NUM_LIT:0.0>, color=color_list.get_color(index_cluster))<EOL>current_position += len(densities)<EOL><DEDENT>axis.set_ylabel("<STR_LIT>")<EOL>axis.set_xlabel("<STR_LIT>")<EOL>axis.xaxis.set_ticklabels([])<EOL>plt.xlim([-<NUM_LIT:0.5>, current_position - <NUM_LIT:0.5>])<EOL>plt.show()<EOL>

!
        @brief Display dendrogram of BANG-blocks.

        @param[in] dendrogram (list): List representation of dendrogram of BANG-blocks.

        @see bang.get_dendrogram()


def __update_cluster_dendrogram(self, index_cluster, blocks):

if len(self.__dendrogram) <= index_cluster:<EOL><INDENT>self.__dendrogram.append([])<EOL><DEDENT>blocks = sorted(blocks, key=lambda block: block.get_density(), reverse=True)<EOL>self.__dendrogram[index_cluster] += blocks<EOL>

!
        @brief Append clustered blocks to dendrogram.

        @param[in] index_cluster (uint): Cluster index that was assigned to blocks.
        @param[in] blocks (list): Blocks that were clustered.


return self.get_spatial_block().is_neighbor(block.get_spatial_block())<EOL>

!
        @brief Performs calculation to check whether specified block is neighbor to the current.

        @param[in] block (bang_block): Other BANG-block that should be checked for neighborhood.

        @return (bool) True if blocks are neighbors, False if blocks are not neighbors.


def __draw_block(self, block, block_alpha=<NUM_LIT:0.0>):

max_corner, min_corner = block.get_spatial_block().get_corners()<EOL>face_color = matplotlib.colors.to_rgba('<STR_LIT>', alpha=block_alpha)<EOL>edge_color = matplotlib.colors.to_rgba('<STR_LIT>', alpha=<NUM_LIT:1.0>)<EOL>rect = patches.Rectangle(min_corner, max_corner[<NUM_LIT:0>] - min_corner[<NUM_LIT:0>], max_corner[<NUM_LIT:1>] - min_corner[<NUM_LIT:1>],<EOL>fill=True,<EOL>facecolor=face_color,<EOL>edgecolor=edge_color,<EOL>linewidth=<NUM_LIT:0.5>)<EOL>self.__ax.add_patch(rect)<EOL>

!
        @brief Display single BANG block on axis.

        @param[in] block (bang_block): BANG block that should be displayed.
        @param[in] block_alpha (double): Transparency level - value of alpha.


def __store_clustering_results(self, amount_clusters, leaf_blocks):

self.__clusters = [[] for _ in range(amount_clusters)]<EOL>for block in leaf_blocks:<EOL><INDENT>index = block.get_cluster()<EOL>if index is not None:<EOL><INDENT>self.__clusters[index] += block.get_points()<EOL><DEDENT>else:<EOL><INDENT>self.__noise += block.get_points()<EOL><DEDENT><DEDENT>self.__clusters = [ list(set(cluster)) for cluster in self.__clusters ]<EOL>self.__noise = list(set(self.__noise))<EOL>

!
        @brief Stores clustering results in a convenient way.

        @param[in] amount_clusters (uint): Amount of cluster that was allocated during processing.
        @param[in] leaf_blocks (list): Leaf BANG-blocks (the smallest cells).


def __draw_cluster(self, data, cluster, color, marker):

for item in cluster:<EOL><INDENT>self.__ax.plot(data[item][<NUM_LIT:0>], data[item][<NUM_LIT:1>], color=color, marker=marker)<EOL><DEDENT>

!
        @brief Draw 2-D single cluster on axis using specified color and marker.


return self.__data<EOL>

!
        @brief Return data that is stored in the directory.

        @return (list) List of points that represents stored data.


return self.__max_corner, self.__min_corner<EOL>

!
        @brief Return spatial description of current block.

        @return (tuple) Pair of maximum and minimum corners (max_corner, min_corner).


return self.__density<EOL>

!
        @brief Returns density of the BANG-block.

        @return (double) BANG-block density.


def __init__(self, data, levels, ccore=False, **kwargs):

self.__data = data<EOL>self.__levels = levels<EOL>self.__directory = None<EOL>self.__clusters = []<EOL>self.__noise = []<EOL>self.__cluster_blocks = []<EOL>self.__dendrogram = []<EOL>self.__density_threshold = kwargs.get('<STR_LIT>', <NUM_LIT:0.0>)<EOL>self.__amount_threshold = kwargs.get('<STR_LIT>', <NUM_LIT:0>)<EOL>self.__ccore = ccore<EOL>self.__validate_arguments()<EOL>

!
        @brief Create BANG clustering algorithm.

        @param[in] data (list): Input data (list of points) that should be clustered.
        @param[in] levels (uint): Amount of levels in tree that is used for splitting (how many times block should be
                    split). For example, if amount of levels is two then surface will be divided into two blocks and
                    each obtained block will be divided into blocks also.
        @param[in] ccore (bool): Reserved positional argument - not used yet.
        @param[in] **kwargs: Arbitrary keyword arguments (available arguments: 'observe').

        Keyword Args:

            - density_threshold (double): If block density is smaller than this value then contained data by this
               block is considered as a noise and its points as outliers. Block density is defined by amount of
               points in block divided by block volume: amount_block_points/block_volume. By default
               it is 0.0 - means than only empty blocks are considered as noise. Be aware that this parameter is used
               with parameter 'amount_threshold' - the maximum threshold is considered during processing.
            - amount_threshold (uint): Amount of points in the block when it contained data in bang-block is
               considered as a noise and there is no need to split it till the last level. Be aware that this parameter
               is used with parameter 'density_threshold' - the maximum threshold is considered during processing.


if self.__kmax > len(self.__data):<EOL><INDENT>raise ValueError("<STR_LIT>" + str(self.__kmax) + "<STR_LIT>" +<EOL>str(len(self.__data)) + "<STR_LIT>")<EOL><DEDENT>if self.__kmin <= <NUM_LIT:1>:<EOL><INDENT>raise ValueError("<STR_LIT>" + str(self.__kmin) + "<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>

!
        @brief Checks algorithm's arguments and if some of them is incorrect then exception is thrown.


initial_values = kmeans_plusplus_initializer(self.__data, k).initialize(return_index=self.__return_index)<EOL>algorithm_type = self.__algorithm.get_type()<EOL>return algorithm_type(self.__data, initial_values).process().get_clusters()<EOL>

!
        @brief Performs cluster analysis using specified K value.

        @param[in] k (uint): Amount of clusters that should be allocated.

        @return (array_like) Allocated clusters.


if self == silhouette_ksearch_type.KMEANS:<EOL><INDENT>return kmeans<EOL><DEDENT>elif self == silhouette_ksearch_type.KMEDIANS:<EOL><INDENT>return kmedians<EOL><DEDENT>elif self == silhouette_ksearch_type.KMEDOIDS:<EOL><INDENT>return kmedoids<EOL><DEDENT>else:<EOL><INDENT>return None<EOL><DEDENT>

!
        @brief Returns algorithm type that corresponds to specified enumeration value.

        @return (type) Algorithm type for cluster analysis.


return self.__scores<EOL>

!
        @brief Returns silhouette score for each K value (amount of clusters).

        @return (dict) Silhouette score for each K value, where key is a K value and value is a silhouette score.

        @see process, get_score


if self.__ccore is True:<EOL><INDENT>self.__process_by_ccore()<EOL><DEDENT>else:<EOL><INDENT>self.__process_by_python()<EOL><DEDENT>return self<EOL>

!
        @brief Performs analysis to find optimal amount of clusters.

        @see get_amount, get_score, get_scores

        @return (silhouette_search) Itself instance (silhouette_search)


results = wrapper.silhoeutte_ksearch(self.__data, self.__kmin, self.__kmax, self.__algorithm)<EOL>self.__amount = results[<NUM_LIT:0>]<EOL>self.__score = results[<NUM_LIT:1>]<EOL>self.__scores = results[<NUM_LIT:2>]<EOL>

!
        @brief Performs processing using CCORE (C/C++ part of pyclustering library).


def __caclulate_optimal_neighbor_cluster_score(self, index_cluster, difference):

optimal_score = float('<STR_LIT>')<EOL>for index_neighbor_cluster in range(len(self.__clusters)):<EOL><INDENT>if index_cluster != index_neighbor_cluster:<EOL><INDENT>candidate_score = self.__calculate_cluster_score(index_neighbor_cluster, difference)<EOL>if candidate_score < optimal_score:<EOL><INDENT>optimal_score = candidate_score<EOL><DEDENT><DEDENT><DEDENT>if optimal_score == float('<STR_LIT>'):<EOL><INDENT>optimal_score = -<NUM_LIT:1.0><EOL><DEDENT>return optimal_score<EOL>

!
        @brief Calculates 'B' score for the specific object for the nearest cluster.

        @param[in] index_point (uint): Index point from input data for which 'B' score should be calculated.
        @param[in] index_cluster (uint): Index cluster to which the point is belong to.

        @return (float) 'B' score for the object.


def __calculate_cluster_difference(self, index_cluster, difference):

cluster_difference = <NUM_LIT:0.0><EOL>for index_point in self.__clusters[index_cluster]:<EOL><INDENT>cluster_difference += difference[index_point]<EOL><DEDENT>return cluster_difference<EOL>

!
        @brief Calculates distance from each object in specified cluster to specified object.

        @param[in] index_point (uint): Index point for which difference is calculated.

        @return (list) Distance from specified object to each object from input data in specified cluster.


!
        @brief Calculates Silhouette score for each object from input data.

        @return (silhouette) Instance of the method (self).


return [ random.gauss(self.__cluster_centers[index_cluster][index_dimension],<EOL>self.__cluster_width[index_cluster] / <NUM_LIT>)<EOL>for index_dimension in range(self.__dimension) ]<EOL>

!
        @brief Generates point in line with parameters of specified cluster.

        @param[in] index_cluster (uint): Index of cluster whose parameters are used for point generation.

        @return (list) New generated point in line with normal distribution and cluster parameters.


def __init__(self, amount_clusters, dimension, cluster_sizes, cluster_centers=None, cluster_width=<NUM_LIT:1.0>):

self.__amount_clusters = amount_clusters<EOL>self.__dimension = dimension<EOL>self.__cluster_sizes = cluster_sizes<EOL>if not isinstance(self.__cluster_sizes, collections.Iterable):<EOL><INDENT>self.__cluster_sizes = [self.__cluster_sizes] * amount_clusters<EOL><DEDENT>self.__cluster_width = cluster_width<EOL>if not isinstance(self.__cluster_width, collections.Iterable):<EOL><INDENT>self.__cluster_width = [self.__cluster_width] * amount_clusters<EOL><DEDENT>self.__cluster_centers = cluster_centers<EOL>if self.__cluster_centers is None:<EOL><INDENT>self.__cluster_centers = self.__generate_cluster_centers(self.__cluster_width)<EOL><DEDENT>

!
        @brief Constructs data generator for generating data-sets.

        @param[in] amount_clusters (uint): Amount of clusters that should be generated.
        @param[in] dimension (uint): Dimension of each generated point.
        @param[in] cluster_sizes (uint|array_like): Size of each cluster. In case of 'array_like' input clusters with
                    corresponding sizes are generated.
        @param[in] cluster_centers (array_like): Optional parameter that defines cluster centers (means).
        @param[in] cluster_width (uint|array_like): Optional parameter that defines cluster width (standard deviation).
                    In case of 'array_like' input each cluster has own standard deviation.


medoid_indexes = [-<NUM_LIT:1>] * len(self.__clusters)<EOL>for index in range(len(self.__clusters)):<EOL><INDENT>medoid_index = medoid(self.__pointer_data, self.__clusters[index], metric=self.__metric, data_type=self.__data_type)<EOL>medoid_indexes[index] = medoid_index<EOL><DEDENT>return medoid_indexes<EOL>

!
        @brief Find medoids of clusters in line with contained objects.

        @return (list) list of medoids for current number of clusters.


return self.__medoid_indexes<EOL>

!
        @brief Returns list of medoids of allocated clusters represented by indexes from the input data.

        @see process()
        @see get_clusters()


def __init__(self, data, maximum_clusters, threshold, ccore=True, **kwargs):

super().__init__(data, maximum_clusters, threshold, ccore, **kwargs)<EOL>

!
        @brief Creates MBSAS algorithm.

        @param[in] data (list): Input data that is presented as list of points (objects), each point should be represented by list or tuple.
        @param[in] maximum_clusters: Maximum allowable number of clusters that can be allocated during processing.
        @param[in] threshold: Threshold of dissimilarity (maximum distance) between points.
        @param[in] ccore (bool): If True than DLL CCORE (C++ solution) will be used for solving.
        @param[in] **kwargs: Arbitrary keyword arguments (available arguments: 'metric').

        Keyword Args:

            - metric (distance_metric): Metric that is used for distance calculation between two points.


def __splitting_criterion(self, clusters, centers):

if self.__criterion == splitting_type.BAYESIAN_INFORMATION_CRITERION:<EOL><INDENT>return self.__bayesian_information_criterion(clusters, centers)<EOL><DEDENT>elif self.__criterion == splitting_type.MINIMUM_NOISELESS_DESCRIPTION_LENGTH:<EOL><INDENT>return self.__minimum_noiseless_description_length(clusters, centers)<EOL><DEDENT>else:<EOL><INDENT>assert <NUM_LIT:0>;<EOL><DEDENT>

!
        @brief Calculates splitting criterion for input clusters.

        @param[in] clusters (list): Clusters for which splitting criterion should be calculated.
        @param[in] centers (list): Centers of the clusters.

        @return (double) Returns splitting criterion. High value of splitting cretion means that current structure is much better.

        @see __bayesian_information_criterion(clusters, centers)
        @see __minimum_noiseless_description_length(clusters, centers)


return type_encoding.CLUSTER_INDEX_LIST_SEPARATION<EOL>

!
        @brief Returns clustering result representation type that indicate how clusters are encoded.

        @return (type_encoding) Clustering result representation.

        @see get_clusters()


def __improve_parameters(self, centers, available_indexes = None):

if available_indexes and len(available_indexes) == <NUM_LIT:1>:<EOL><INDENT>index_center = available_indexes[<NUM_LIT:0>]<EOL>return [ available_indexes ], self.__pointer_data[index_center]<EOL><DEDENT>local_data = self.__pointer_data<EOL>if available_indexes:<EOL><INDENT>local_data = [ self.__pointer_data[i] for i in available_indexes ]<EOL><DEDENT>local_centers = centers<EOL>if centers is None:<EOL><INDENT>local_centers = kmeans_plusplus_initializer(local_data, <NUM_LIT:2>, kmeans_plusplus_initializer.FARTHEST_CENTER_CANDIDATE).initialize()<EOL><DEDENT>kmeans_instance = kmeans(local_data, local_centers, tolerance=self.__tolerance, ccore=False)<EOL>kmeans_instance.process()<EOL>local_centers = kmeans_instance.get_centers()<EOL>clusters = kmeans_instance.get_clusters()<EOL>if available_indexes:<EOL><INDENT>clusters = self.__local_to_global_clusters(clusters, available_indexes)<EOL><DEDENT>return clusters, local_centers<EOL>

!
        @brief Performs k-means clustering in the specified region.

        @param[in] centers (list): Centers of clusters.
        @param[in] available_indexes (list): Indexes that defines which points can be used for k-means clustering, if None - then all points are used.

        @return (list) List of allocated clusters, each cluster contains indexes of objects in list of data.


def __improve_structure(self, clusters, centers):

allocated_centers = []<EOL>amount_free_centers = self.__kmax - len(centers)<EOL>for index_cluster in range(len(clusters)):<EOL><INDENT>(parent_child_clusters, parent_child_centers) = self.__improve_parameters(None, clusters[index_cluster])<EOL>if len(parent_child_clusters) > <NUM_LIT:1>:<EOL><INDENT>parent_scores = self.__splitting_criterion([ clusters[index_cluster] ], [ centers[index_cluster] ])<EOL>child_scores = self.__splitting_criterion([ parent_child_clusters[<NUM_LIT:0>], parent_child_clusters[<NUM_LIT:1>] ], parent_child_centers)<EOL>split_require = False<EOL>if self.__criterion == splitting_type.BAYESIAN_INFORMATION_CRITERION:<EOL><INDENT>if parent_scores < child_scores: split_require = True<EOL><DEDENT>elif self.__criterion == splitting_type.MINIMUM_NOISELESS_DESCRIPTION_LENGTH:<EOL><INDENT>if parent_scores > child_scores: split_require = True;<EOL><DEDENT>if (split_require is True) and (amount_free_centers > <NUM_LIT:0>):<EOL><INDENT>allocated_centers.append(parent_child_centers[<NUM_LIT:0>])<EOL>allocated_centers.append(parent_child_centers[<NUM_LIT:1>])<EOL>amount_free_centers -= <NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>allocated_centers.append(centers[index_cluster])<EOL><DEDENT><DEDENT>else:<EOL><INDENT>allocated_centers.append(centers[index_cluster])<EOL><DEDENT><DEDENT>return allocated_centers<EOL>

!
        @brief Check for best structure: divides each cluster into two and checks for best results using splitting criterion.

        @param[in] clusters (list): Clusters that have been allocated (each cluster contains indexes of points from data).
        @param[in] centers (list): Centers of clusters.

        @return (list) Allocated centers for clustering.


return self.__clusters<EOL>

!
        @brief Returns list of allocated clusters, each cluster contains indexes of objects in list of data.

        @return (list) List of allocated clusters.

        @see process()
        @see get_centers()


def __local_to_global_clusters(self, local_clusters, available_indexes):

clusters = []<EOL>for local_cluster in local_clusters:<EOL><INDENT>current_cluster = []<EOL>for index_point in local_cluster:<EOL><INDENT>current_cluster.append(available_indexes[index_point])<EOL><DEDENT>clusters.append(current_cluster)<EOL><DEDENT>return clusters<EOL>

!
        @brief Converts clusters in local region define by 'available_indexes' to global clusters.

        @param[in] local_clusters (list): Local clusters in specific region.
        @param[in] available_indexes (list): Map between local and global point's indexes.

        @return Global clusters.


dataset_differences = numpy.zeros((amount_clusters, len(self.__pointer_data)))<EOL>for index_center in range(amount_clusters):<EOL><INDENT>if self.__metric.get_type() != type_metric.USER_DEFINED:<EOL><INDENT>dataset_differences[index_center] = self.__metric(self.__pointer_data, self.__centers[index_center])<EOL><DEDENT>else:<EOL><INDENT>dataset_differences[index_center] = [ self.__metric(point, self.__centers[index_center])<EOL>for point in self.__pointer_data ]<EOL><DEDENT><DEDENT>return dataset_differences<EOL>

!
        @brief Calculate distance from each point to each cluster center.


return self.__total_wce<EOL>

!
        @brief Returns sum of metric errors that depends on metric that was used for clustering (by default SSE - Sum of Squared Errors).
        @details Sum of metric errors is calculated using distance between point and its center:
                 \f[error=\sum_{i=0}^{N}distance(x_{i}-center(x_{i}))\f]

        @see process()
        @see get_clusters()


def __init__(self, data, initial_centers, tolerance=<NUM_LIT>, ccore=True, **kwargs):

self.__pointer_data = numpy.array(data)<EOL>self.__clusters = []<EOL>self.__centers = numpy.array(initial_centers)<EOL>self.__tolerance = tolerance<EOL>self.__total_wce = <NUM_LIT:0><EOL>self.__observer = kwargs.get('<STR_LIT>', None)<EOL>self.__metric = kwargs.get('<STR_LIT>', distance_metric(type_metric.EUCLIDEAN_SQUARE))<EOL>self.__itermax = kwargs.get('<STR_LIT>', <NUM_LIT:100>)<EOL>if self.__metric.get_type() != type_metric.USER_DEFINED:<EOL><INDENT>self.__metric.enable_numpy_usage()<EOL><DEDENT>else:<EOL><INDENT>self.__metric.disable_numpy_usage()<EOL><DEDENT>self.__ccore = ccore and self.__metric.get_type() != type_metric.USER_DEFINED<EOL>if self.__ccore is True:<EOL><INDENT>self.__ccore = ccore_library.workable()<EOL><DEDENT>

!
        @brief Constructor of clustering algorithm K-Means.
        @details Center initializer can be used for creating initial centers, for example, K-Means++ method.

        @param[in] data (array_like): Input data that is presented as array of points (objects), each point should be represented by array_like data structure.
        @param[in] initial_centers (array_like): Initial coordinates of centers of clusters that are represented by array_like data structure: [center1, center2, ...].
        @param[in] tolerance (double): Stop condition: if maximum value of change of centers of clusters is less than tolerance then algorithm stops processing.
        @param[in] ccore (bool): Defines should be CCORE library (C++ pyclustering library) used instead of Python code or not.
        @param[in] **kwargs: Arbitrary keyword arguments (available arguments: 'observer', 'metric', 'itermax').

        Keyword Args:

            - observer (kmeans_observer): Observer of the algorithm to collect information about clustering process on each iteration.
            - metric (distance_metric): Metric that is used for distance calculation between two points (by default euclidean square distance).
            - itermax (uint): Maximum number of iterations that is used for clustering process (by default: 200).

        @see center_initializer


maximum_change = float('<STR_LIT>')<EOL>iteration = <NUM_LIT:0><EOL>if self.__observer is not None:<EOL><INDENT>initial_clusters = self.__update_clusters()<EOL>self.__observer.notify(initial_clusters, self.__centers.tolist())<EOL><DEDENT>while maximum_change > self.__tolerance and iteration < self.__itermax:<EOL><INDENT>self.__clusters = self.__update_clusters()<EOL>updated_centers = self.__update_centers()  <EOL>if self.__observer is not None:<EOL><INDENT>self.__observer.notify(self.__clusters, updated_centers.tolist())<EOL><DEDENT>maximum_change = self.__calculate_changes(updated_centers)<EOL>self.__centers = updated_centers    <EOL>iteration += <NUM_LIT:1><EOL><DEDENT>self.__calculate_total_wce()<EOL>

!
        @brief Performs cluster analysis using python code.


ccore_metric = metric_wrapper.create_instance(self.__metric)<EOL>results = wrapper.kmeans(self.__pointer_data, self.__centers, self.__tolerance, self.__itermax, (self.__observer is not None), ccore_metric.get_pointer())<EOL>self.__clusters = results[<NUM_LIT:0>]<EOL>self.__centers = results[<NUM_LIT:1>]<EOL>if self.__observer is not None:<EOL><INDENT>self.__observer.set_evolution_clusters(results[<NUM_LIT:2>])<EOL>self.__observer.set_evolution_centers(results[<NUM_LIT:3>])<EOL><DEDENT>self.__total_wce = results[<NUM_LIT:4>][<NUM_LIT:0>]<EOL>

!
        @brief Performs cluster analysis using CCORE (C/C++ part of pyclustering library).


self.__evolution_clusters = evolution_clusters<EOL>

!
        @brief Set evolution of changes of centers during clustering process.

        @param[in] evolution_clusters (array_like): Evolution of changes of clusters during clustering process.


if isinstance(self.__centers, list):<EOL><INDENT>return self.__centers<EOL><DEDENT>return self.__centers.tolist()<EOL>

!
        @brief Returns list of centers of allocated clusters.

        @see process()
        @see get_clusters()


self.__evolution_clusters.append(clusters)<EOL>self.__evolution_centers.append(centers)<EOL>

!
        @brief This method is called by K-Means algorithm to notify about changes.

        @param[in] clusters (array_like): Allocated clusters by K-Means algorithm.
        @param[in] centers (array_like): Allocated centers by K-Means algorithm.


return self.__evolution_clusters[iteration]<EOL>

!
        @brief Get method to return allocated clusters at specific iteration of clustering process.

        @param[in] iteration (uint): Clustering process iteration at which clusters are required.

        @return (array_like) Clusters at specific iteration.


if len(self.__pointer_data[<NUM_LIT:0>]) != len(self.__centers[<NUM_LIT:0>]):<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>if self.__ccore is True:<EOL><INDENT>self.__process_by_ccore()<EOL><DEDENT>else:<EOL><INDENT>self.__process_by_python()<EOL><DEDENT>return self<EOL>

!
        @brief Performs cluster analysis in line with rules of K-Means algorithm.

        @return (kmeans) Returns itself (K-Means instance).

        @remark Results of clustering can be obtained using corresponding get methods.

        @see get_clusters()
        @see get_centers()


return len(self.__means_evolution)<EOL>

!
        @return (uint) Amount of iterations that were done by the EM algorithm.


def initialize(self, init_type = ema_init_type.KMEANS_INITIALIZATION):

if init_type == ema_init_type.KMEANS_INITIALIZATION:<EOL><INDENT>return self.__initialize_kmeans()<EOL><DEDENT>elif init_type == ema_init_type.RANDOM_INITIALIZATION:<EOL><INDENT>return self.__initialize_random()<EOL><DEDENT>raise NameError("<STR_LIT>")<EOL>

!
        @brief Calculates initial parameters for EM algorithm: means and covariances using
                specified strategy.

        @param[in] init_type (ema_init_type): Strategy for initialization.

        @return (float|list, float|numpy.array) Initial means and variance (covariance matrix in case multi-dimensional data).


return self.__clusters<EOL>

!
        @return (list) Allocated clusters where each cluster is represented by list of indexes of points from dataset,
                        for example, two cluster may have following representation [[0, 1, 4], [2, 3, 5, 6]].


return self.__covariances_evolution<EOL>

!
        @return (list) Covariance matrix (or variance in case of one-dimensional data) of each cluster on each step of clustering.


return len(self.__means_evolution)<EOL>


previous_likelihood = -<NUM_LIT><EOL>current_likelihood = -<NUM_LIT><EOL>current_iteration = <NUM_LIT:0><EOL>while(self.__stop is False) and (abs(previous_likelihood - current_likelihood) > self.__tolerance) and (current_iteration < self.__iterations):<EOL><INDENT>self.__expectation_step()<EOL>self.__maximization_step()<EOL>current_iteration += <NUM_LIT:1><EOL>self.__extract_clusters()<EOL>self.__notify()<EOL>previous_likelihood = current_likelihood<EOL>current_likelihood = self.__log_likelihood()<EOL>self.__stop = self.__get_stop_condition()<EOL><DEDENT>self.__normalize_probabilities()<EOL>

!
        @brief Run clustering process of the algorithm.
        @details This method should be called before call 'get_clusters()'.


return self.__variances<EOL>

!
        @return (list) Corresponding variances (or covariances in case of multi-dimensional data) of clusters.


return self.__clusters_evolution<EOL>

!
        @return (list) Allocated clusters on each step of clustering.


@staticmethod<EOL><INDENT>def _select(chromosomes, data, count_clusters, select_coeff):<DEDENT>

<EOL>centres = ga_math.get_centres(chromosomes, data, count_clusters)<EOL>fitness = genetic_algorithm._calc_fitness_function(centres, data, chromosomes)<EOL>for _idx in range(len(fitness)):<EOL><INDENT>fitness[_idx] = math.exp(<NUM_LIT:1> + fitness[_idx] * select_coeff)<EOL><DEDENT>probabilities = ga_math.calc_probability_vector(fitness)<EOL>new_chromosomes = np.zeros(chromosomes.shape, dtype=np.int)<EOL>for _idx in range(len(chromosomes)):<EOL><INDENT>new_chromosomes[_idx] = chromosomes[ga_math.get_uniform(probabilities)]<EOL><DEDENT>return new_chromosomes<EOL>

!
        @brief Performs selection procedure where new chromosomes are calculated.

        @param[in] chromosomes (numpy.array): Chromosomes


@staticmethod<EOL><INDENT>def _init_population(count_clusters, count_data, chromosome_count):<DEDENT>

population = np.random.randint(count_clusters, size=(chromosome_count, count_data))<EOL>return population<EOL>

!
        @brief Returns first population as a uniform random choice.

        @param[in] count_clusters (uint): Amount of clusters that should be allocated.
        @param[in] count_data (uint): Data size that is used for clustering process.
        @param[in] chromosome_count (uint):Amount of chromosome that is used for clustering.


@staticmethod<EOL><INDENT>def _calc_fitness_function(centres, data, chromosomes):<DEDENT>

<EOL>count_chromosome = len(chromosomes)<EOL>fitness_function = np.zeros(count_chromosome)<EOL>for _idx_chromosome in range(count_chromosome):<EOL><INDENT>centres_data = np.zeros(data.shape)<EOL>for _idx in range(len(data)):<EOL><INDENT>centres_data[_idx] = centres[_idx_chromosome][chromosomes[_idx_chromosome][_idx]]<EOL><DEDENT>fitness_function[_idx_chromosome] += np.sum(abs(data - centres_data))<EOL><DEDENT>return fitness_function<EOL>

!
        @brief Calculate fitness function values for chromosomes.

        @param[in] centres (list): Cluster centers.
        @param[in] data (list): Input data that is used for clustering process.
        @param[in] chromosomes (list): Chromosomes whose fitness function's values are calculated.

        @return (list) Fitness function value for each chromosome correspondingly.


return self._observer<EOL>

!
        @brief Returns genetic algorithm observer.


@staticmethod<EOL><INDENT>def _crossover_a_pair(chromosome_1, chromosome_2, mask):<DEDENT>

for _idx in range(len(chromosome_1)):<EOL><INDENT>if mask[_idx] == <NUM_LIT:1>:<EOL><INDENT>chromosome_1[_idx], chromosome_2[_idx] = chromosome_2[_idx], chromosome_1[_idx]<EOL><DEDENT><DEDENT>

!
        @brief Crossovers a pair of chromosomes.

        @param[in] chromosome_1 (numpy.array): The first chromosome for crossover.
        @param[in] chromosome_2 (numpy.array): The second chromosome for crossover.
        @param[in] mask (numpy.array): Crossover mask that defines which genes should be swapped.


return self._mean_ff_result<EOL>

!
        @brief (list) Returns fitness function's values on each iteration.


def __init__(self, need_global_best=False, need_population_best=False, need_mean_ff=False):

<EOL>self._global_best_result = {'<STR_LIT>': [], '<STR_LIT>': []}<EOL>self._best_population_result = {'<STR_LIT>': [], '<STR_LIT>': []}<EOL>self._mean_ff_result = []<EOL>self._need_global_best = need_global_best<EOL>self._need_population_best = need_population_best<EOL>self._need_mean_ff = need_mean_ff<EOL>

!
        @brief Constructs genetic algorithm observer to collect specific information.

        @param[in] need_global_best (bool): If 'True' then the best chromosomes and its fitness function value (global optimum) for each iteration are stored.
        @param[in] need_population_best (bool): If 'True' then current (on each iteration) best chromosomes and its fitness function value (local optimum) are stored.
        @param[in] need_mean_ff (bool): If 'True' then average value of fitness function on each iteration is stored.


ccore = ccore_library.get()<EOL>ccore.som_get_winner_number.restype = c_size_t<EOL>return ccore.som_get_winner_number(som_pointer)<EOL>

!
    @brief Returns of number of winner at the last step of learning process.

    @param[in] som_pointer (c_pointer): pointer to object of self-organized map.


def som_load(som_pointer, weights, award, capture_objects):

if len(weights) == <NUM_LIT:0>:<EOL><INDENT>return<EOL><DEDENT>ccore = ccore_library.get()<EOL>package_weights = package_builder(weights, c_double).create()<EOL>package_award = package_builder(award, c_size_t).create()<EOL>package_capture_objects = package_builder(capture_objects, c_size_t).create()<EOL>ccore.som_load(som_pointer, package_weights, package_award, package_capture_objects)<EOL>

!
    @brief Load dump of the network to SOM.
    @details Initialize SOM using existed weights, amount of captured objects by each neuron, captured
              objects by each neuron. Initialization is not performed if weights are empty.

    @param[in] som_pointer (POINTER): pointer to object of self-organized map.
    @param[in] weights (list): weights that should assigned to neurons.
    @param[in] awards (list): amount of captured objects by each neuron.
    @param[in] capture_objects (list): captured objects by each neuron.


def som_train(som_pointer, data, epochs, autostop):

pointer_data = package_builder(data, c_double).create()<EOL>ccore = ccore_library.get()<EOL>ccore.som_train.restype = c_size_t<EOL>return ccore.som_train(som_pointer, pointer_data, c_uint(epochs), autostop)<EOL>

!
    @brief Trains self-organized feature map (SOM) using CCORE pyclustering library.

    @param[in] data (list): Input data - list of points where each point is represented by list of features, for example coordinates.
    @param[in] epochs (uint): Number of epochs for training.
    @param[in] autostop (bool): Automatic termination of learining process when adaptation is not occurred.

    @return (uint) Number of learining iterations.


return self.__extract_data(self.__package_pointer)<EOL>

!
        @brief Performs unpacking procedure of the pyclustering package to the data.

        @return (list) Extracted data from the pyclustering package.


return pyclustering_type_data.__PYCLUSTERING_CTYPE_MAP[pyclustering_package_type]<EOL>

!
        @return (ctype) Return ctype that corresponds to pyclustering type data.


return self.__create_package(self.__dataset)<EOL>

!
        @brief Performs packing procedure of the data to the package.

        @return (pointer) ctype-pointer to pyclustering package.


def rock(sample, eps, number_clusters, threshold):

pointer_data = package_builder(sample, c_double).create();<EOL>ccore = ccore_library.get();<EOL>ccore.rock_algorithm.restype = POINTER(pyclustering_package);<EOL>package = ccore.rock_algorithm(pointer_data, c_double(eps), c_size_t(number_clusters), c_double(threshold));<EOL>list_of_clusters = package_extractor(package).extract();<EOL>ccore.free_pyclustering_package(package);<EOL>return list_of_clusters<EOL>

@brief Clustering algorithm ROCK returns allocated clusters and noise that are consisted from input data.
@details Calculation is performed via CCORE (C/C++ part of the pyclustering)."

@param[in] sample: input data - list of points where each point is represented by list of coordinates.
@param[in] eps: connectivity radius (similarity threshold), points are neighbors if distance between them is less than connectivity radius.
@param[in] number_clusters: defines number of clusters that should be allocated from the input data set.
@param[in] threshold: value that defines degree of normalization that influences on choice of clusters for merging during processing.

@return List of allocated clusters, each cluster contains indexes of objects in list of data.


def __init__(self, canvas, x_title=None, y_title=None, x_lim=None, y_lim=None, x_labels=True, y_labels=True):

self.__size = canvas;<EOL>self.__canvases = [ canvas_descr(x_title, y_title, x_lim, y_lim, x_labels, y_labels) for _ in range(canvas) ];<EOL>self.__dynamic_storage = []<EOL>

!
        @brief Construct dynamic visualizer.
        @details Default properties that are generalized in the constructor, for example, X axis title, can be
                  changed by corresponding method: 'set_canvas_properties'.

        @param[in] canvas (uint): Amount of canvases that is used for visualization.
        @param[in] x_title (string): Title for X axis of canvases, if 'None', then nothing is displayed.
        @param[in] y_title (string): Title for Y axis of canvases, if 'None', then nothing is displayed.
        @param[in] x_lim (list): Defines borders of X axis like [from, to], for example [0, 3.14], if 'None' then
                    borders are calculated automatically.
        @param[in] y_lim (list): Defines borders of Y axis like [from, to], if 'None' then borders are calculated
                    automatically.
        @param[in] x_labels (bool): If True then labels of X axis are displayed.
        @param[in] y_labels (bool): If True then labels of Y axis are displayed.


def __init__(self, x_title=None, y_title=None, x_lim=None, y_lim=None, x_labels=True, y_labels=True):

<EOL>self.x_title  = x_title;<EOL>self.y_title  = y_title;<EOL>self.x_lim    = x_lim;<EOL>self.y_lim    = y_lim;<EOL>self.x_labels = x_labels;<EOL>self.y_labels = y_labels<EOL>

!
        @brief Constructor of canvas.

        @param[in] x_title (string): Title for X axis, if 'None', then nothing is displayed.
        @param[in] y_title (string): Title for Y axis, if 'None', then nothing is displayed.
        @param[in] x_lim (list): Defines borders of X axis like [from, to], for example [0, 3.14], if 'None' then
                    borders are calculated automatically.
        @param[in] y_lim (list): Defines borders of Y axis like [from, to], if 'None' then borders are calculated
                    automatically.
        @param[in] x_labels (bool): If True then labels of X axis are displayed.
        @param[in] y_labels (bool): If True then labels of Y axis are displayed.


def show(self, axis=None, display=True):

if (not axis):<EOL><INDENT>(_, axis) = plt.subplots(self.__size, <NUM_LIT:1>);<EOL><DEDENT>self.__format_canvases(axis);<EOL>for dynamic in self.__dynamic_storage:<EOL><INDENT>self.__display_dynamic(axis, dynamic);<EOL><DEDENT>if (display):<EOL><INDENT>plt.show();<EOL><DEDENT>

!
        @brief Draw and show output dynamics.

        @param[in] axis (axis): If is not 'None' then user specified axis is used to display output dynamic.
        @param[in] display (bool): Whether output dynamic should be displayed or not, if not, then user
                    should call 'plt.show()' by himself.


def append_dynamics(self, t, dynamics, canvas=<NUM_LIT:0>, separate=False, color='<STR_LIT>'):

description = dynamic_descr(canvas, t, dynamics, separate, color);<EOL>self.__dynamic_storage.append(description);<EOL>self.__update_canvas_xlim(description.time, description.separate)<EOL>

!
        @brief Append several dynamics to canvas or canvases (defined by 'canvas' and 'separate' arguments).

        @param[in] t (list): Time points that corresponds to dynamic values and considered on a X axis.
        @param[in] dynamics (list): Dynamics where each of them is considered on Y axis.
        @param[in] canvas (uint): Index of canvas where dynamic should be displayed, in case of 'separate'
                    representation this argument is considered as a first canvas from that displaying should be done.
        @param[in] separate (bool|list): If 'True' then each dynamic is displayed on separate canvas, if it is defined
                    by list, for example, [ [1, 2], [3, 4] ], then the first and the second dynamics are displayed on
                    the canvas with index 'canvas' and the third and forth are displayed on the next 'canvas + 1'
                    canvas.
        @param[in] color (string): Color that is used to display output dynamic(s).


def append_dynamic(self, t, dynamic, canvas=<NUM_LIT:0>, color='<STR_LIT>'):

description = dynamic_descr(canvas, t, dynamic, False, color);<EOL>self.__dynamic_storage.append(description);<EOL>self.__update_canvas_xlim(description.time, description.separate)<EOL>

!
        @brief Append single dynamic to specified canvas (by default to the first with index '0').

        @param[in] t (list): Time points that corresponds to dynamic values and considered on a X axis.
        @param[in] dynamic (list): Value points of dynamic that are considered on an Y axis.
        @param[in] canvas (uint): Canvas where dynamic should be displayed.
        @param[in] color (string): Color that is used for drawing dynamic on the canvas.


@staticmethod<EOL><INDENT>def show_phase_matrix(sync_output_dynamic, grid_width = None, grid_height = None, iteration = None):<DEDENT>

_ = plt.figure();<EOL>phase_matrix = sync_output_dynamic.allocate_phase_matrix(grid_width, grid_height, iteration);<EOL>plt.imshow(phase_matrix, cmap = plt.get_cmap('<STR_LIT>'), interpolation='<STR_LIT>', vmin = <NUM_LIT:0.0>, vmax = <NUM_LIT> * math.pi); <EOL>plt.show()<EOL>

!
        @brief Shows 2D matrix of phase values of oscillators at the specified iteration.
        @details User should ensure correct matrix sizes in line with following expression grid_width x grid_height that should be equal to
                  amount of oscillators otherwise exception is thrown. If grid_width or grid_height are not specified than phase matrix size
                  will by calculated automatically by square root.

        @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network whose phase matrix should be shown.
        @param[in] grid_width (uint): Width of the phase matrix.
        @param[in] grid_height (uint): Height of the phase matrix.
        @param[in] iteration (uint): Number of iteration of simulation for which correlation matrix should be allocated.
                    If iternation number is not specified, the last step of simulation is used for the matrix allocation.


@staticmethod<EOL><INDENT>def animate_correlation_matrix(sync_output_dynamic, animation_velocity = <NUM_LIT>, colormap = '<STR_LIT>', save_movie = None):<DEDENT>

figure = plt.figure()<EOL>correlation_matrix = sync_output_dynamic.allocate_correlation_matrix(<NUM_LIT:0>)<EOL>artist = plt.imshow(correlation_matrix, cmap = plt.get_cmap(colormap), interpolation='<STR_LIT>', vmin = <NUM_LIT:0.0>, vmax = <NUM_LIT:1.0>)<EOL>def init_frame(): <EOL><INDENT>return [ artist ]<EOL><DEDENT>def frame_generation(index_dynamic):<EOL><INDENT>correlation_matrix = sync_output_dynamic.allocate_correlation_matrix(index_dynamic)<EOL>artist.set_data(correlation_matrix)<EOL>return [ artist ]<EOL><DEDENT>correlation_animation = animation.FuncAnimation(figure, frame_generation, len(sync_output_dynamic), init_func = init_frame, interval = animation_velocity , repeat_delay = <NUM_LIT:1000>, blit = True)<EOL>if (save_movie is not None):<EOL><INDENT>correlation_animation.save(save_movie, writer = '<STR_LIT>', fps = <NUM_LIT:15>, bitrate = <NUM_LIT>)<EOL><DEDENT>else:<EOL><INDENT>plt.show()<EOL><DEDENT>

!
        @brief Shows animation of correlation matrix between oscillators during simulation.

        @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network.
        @param[in] animation_velocity (uint): Interval between frames in milliseconds.
        @param[in] colormap (string): Name of colormap that is used by matplotlib ('gray', 'pink', 'cool', spring', etc.).
        @param[in] save_movie (string): If it is specified then animation will be stored to file that is specified in this parameter.


def _phase_kuramoto(self, teta, t, argv):

index = argv;<EOL>phase = <NUM_LIT:0>;<EOL>for k in range(<NUM_LIT:0>, self._num_osc):<EOL><INDENT>if (self.has_connection(index, k) == True):<EOL><INDENT>phase += math.sin(self._phases[k] - teta);<EOL><DEDENT><DEDENT>return ( self._freq[index] + (phase * self._weight / self._num_osc) )<EOL>

!
        @brief Returns result of phase calculation for specified oscillator in the network.

        @param[in] teta (double): Phase of the oscillator that is differentiated.
        @param[in] t (double): Current time of simulation.
        @param[in] argv (tuple): Index of the oscillator in the list.

        @return (double) New phase for specified oscillator (don't assign here).


exp_amount = <NUM_LIT:0.0>;<EOL>average_phase = <NUM_LIT:0.0>;<EOL>for phase in oscillator_phases:<EOL><INDENT>exp_amount += math.expm1( abs(<NUM_LIT> * phase) );<EOL>average_phase += phase;<EOL><DEDENT>exp_amount /= len(oscillator_phases);<EOL>average_phase = math.expm1( abs(<NUM_LIT> * (average_phase / len(oscillator_phases))) );<EOL>return abs(average_phase) / abs(exp_amount)<EOL>

!
        @brief Calculates level of global synchronization (order parameter) for input phases.
        @details This parameter is tend 1.0 when the oscillatory network close to global synchronization and it tend to 0.0 when
                  desynchronization is observed in the network.

        @param[in] oscillator_phases (list): List of oscillator phases that are used for level of global synchronization.

        @return (double) Level of global synchronization (order parameter).

        @see calculate_order_parameter()


def simulate(self, steps, time, solution = solve_type.FAST, collect_dynamic = True):

return self.simulate_static(steps, time, solution, collect_dynamic)<EOL>

!
        @brief Performs static simulation of Sync oscillatory network.

        @param[in] steps (uint): Number steps of simulations during simulation.
        @param[in] time (double): Time of simulation.
        @param[in] solution (solve_type): Type of solution (solving).
        @param[in] collect_dynamic (bool): If True - returns whole dynamic of oscillatory network, otherwise returns only last values of dynamics.

        @return (list) Dynamic of oscillatory network. If argument 'collect_dynamic' = True, than return dynamic for the whole simulation time,
                otherwise returns only last values (last step of simulation) of dynamic.

        @see simulate_dynamic()
        @see simulate_static()


def __init__(self, phase, time, ccore = None):

self._dynamic = phase;<EOL>self._time = time;<EOL>self._ccore_sync_dynamic_pointer = ccore<EOL>

!
        @brief Constructor of Sync dynamic.

        @param[in] phase (list): Dynamic of oscillators on each step of simulation. If ccore pointer is specified than it can be ignored.
        @param[in] time (list): Simulation time.
        @param[in] ccore (ctypes.pointer): Pointer to CCORE sync_dynamic instance in memory.


def simulate_static(self, steps, time, solution = solve_type.FAST, collect_dynamic = False):

if (self._ccore_network_pointer is not None):<EOL><INDENT>ccore_instance_dynamic = wrapper.sync_simulate_static(self._ccore_network_pointer, steps, time, solution, collect_dynamic);<EOL>return sync_dynamic(None, None, ccore_instance_dynamic);<EOL><DEDENT>dyn_phase = [];<EOL>dyn_time = [];<EOL>if (collect_dynamic == True):<EOL><INDENT>dyn_phase.append(self._phases);<EOL>dyn_time.append(<NUM_LIT:0>);<EOL><DEDENT>step = time / steps;<EOL>int_step = step / <NUM_LIT>;<EOL>for t in numpy.arange(step, time + step, step):<EOL><INDENT>self._phases = self._calculate_phases(solution, t, step, int_step);<EOL>if (collect_dynamic == True):<EOL><INDENT>dyn_phase.append(self._phases);<EOL>dyn_time.append(t);<EOL><DEDENT><DEDENT>if (collect_dynamic != True):<EOL><INDENT>dyn_phase.append(self._phases);<EOL>dyn_time.append(time);<EOL><DEDENT>output_sync_dynamic = sync_dynamic(dyn_phase, dyn_time);<EOL>return output_sync_dynamic<EOL>

!
        @brief Performs static simulation of oscillatory network.

        @param[in] steps (uint): Number steps of simulations during simulation.
        @param[in] time (double): Time of simulation.
        @param[in] solution (solve_type): Type of solution.
        @param[in] collect_dynamic (bool): If True - returns whole dynamic of oscillatory network, otherwise returns only last values of dynamics.

        @return (list) Dynamic of oscillatory network. If argument 'collect_dynamic' = True, than return dynamic for the whole simulation time,
                otherwise returns only last values (last step of simulation) of dynamic.

        @see simulate()
        @see simulate_dynamic()


@staticmethod<EOL><INDENT>def show_correlation_matrix(sync_output_dynamic, iteration = None):<DEDENT>

_ = plt.figure();<EOL>correlation_matrix = sync_output_dynamic.allocate_correlation_matrix(iteration);<EOL>plt.imshow(correlation_matrix, cmap = plt.get_cmap('<STR_LIT>'), interpolation='<STR_LIT>', vmin = <NUM_LIT:0.0>, vmax = <NUM_LIT:1.0>); <EOL>plt.show()<EOL>

!
        @brief Shows correlation matrix between oscillators at the specified iteration.

        @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network.
        @param[in] iteration (uint): Number of interation of simulation for which correlation matrix should be allocated.
                                      If iternation number is not specified, the last step of simulation is used for the matrix allocation.


def simulate_dynamic(self, order = <NUM_LIT>, solution = solve_type.FAST, collect_dynamic = False, step = <NUM_LIT:0.1>, int_step = <NUM_LIT>, threshold_changes = <NUM_LIT>):

if (self._ccore_network_pointer is not None):<EOL><INDENT>ccore_instance_dynamic = wrapper.sync_simulate_dynamic(self._ccore_network_pointer, order, solution, collect_dynamic, step, int_step, threshold_changes);<EOL>return sync_dynamic(None, None, ccore_instance_dynamic);<EOL><DEDENT>time_counter = <NUM_LIT:0>;<EOL>previous_order = <NUM_LIT:0>;<EOL>current_order = self.sync_local_order();<EOL>dyn_phase = [];<EOL>dyn_time = [];<EOL>if (collect_dynamic == True):<EOL><INDENT>dyn_phase.append(self._phases);<EOL>dyn_time.append(<NUM_LIT:0>);<EOL><DEDENT>while (current_order < order):<EOL><INDENT>self._phases = self._calculate_phases(solution, time_counter, step, int_step);<EOL>time_counter += step;<EOL>if (collect_dynamic == True):<EOL><INDENT>dyn_phase.append(self._phases);<EOL>dyn_time.append(time_counter);<EOL><DEDENT>previous_order = current_order;<EOL>current_order = self.sync_local_order();<EOL>if (abs(current_order - previous_order) < threshold_changes):<EOL><INDENT>break;<EOL><DEDENT><DEDENT>if (collect_dynamic != True):<EOL><INDENT>dyn_phase.append(self._phases);<EOL>dyn_time.append(time_counter);<EOL><DEDENT>output_sync_dynamic = sync_dynamic(dyn_phase, dyn_time, None);<EOL>return output_sync_dynamic<EOL>

!
        @brief Performs dynamic simulation of the network until stop condition is not reached. Stop condition is defined by input argument 'order'.

        @param[in] order (double): Order of process synchronization, distributed 0..1.
        @param[in] solution (solve_type): Type of solution.
        @param[in] collect_dynamic (bool): If True - returns whole dynamic of oscillatory network, otherwise returns only last values of dynamics.
        @param[in] step (double): Time step of one iteration of simulation.
        @param[in] int_step (double): Integration step, should be less than step.
        @param[in] threshold_changes (double): Additional stop condition that helps prevent infinite simulation, defines limit of changes of oscillators between current and previous steps.

        @return (list) Dynamic of oscillatory network. If argument 'collect_dynamic' = True, than return dynamic for the whole simulation time,
                otherwise returns only last values (last step of simulation) of dynamic.

        @see simulate()
        @see simulate_static()


if ( (self._ccore_sync_dynamic_pointer is not None) and ( (self._dynamic is None) or (len(self._dynamic) == <NUM_LIT:0>) ) ):<EOL><INDENT>self._dynamic = wrapper.sync_dynamic_get_output(self._ccore_sync_dynamic_pointer);<EOL><DEDENT>return self._dynamic<EOL>

!
        @brief (list) Returns output dynamic of the Sync network (phase coordinates of each oscillator in the network) during simulation.


@staticmethod<EOL><INDENT>def show_local_order_parameter(sync_output_dynamic, oscillatory_network, start_iteration = None, stop_iteration = None):<DEDENT>

(start_iteration, stop_iteration) = sync_visualizer.__get_start_stop_iterations(sync_output_dynamic, start_iteration, stop_iteration);<EOL>order_parameter = sync_output_dynamic.calculate_local_order_parameter(oscillatory_network, start_iteration, stop_iteration);<EOL>axis = plt.subplot(<NUM_LIT>);<EOL>plt.plot(sync_output_dynamic.time[start_iteration:stop_iteration], order_parameter, '<STR_LIT>', linewidth = <NUM_LIT>);<EOL>set_ax_param(axis, "<STR_LIT:t>", "<STR_LIT>", None, [<NUM_LIT:0.0>, <NUM_LIT>]);<EOL>plt.show()<EOL>

!
        @brief Shows evolution of local order parameter (level of local synchronization in the network).

        @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network whose evolution of global synchronization should be visualized.
        @param[in] oscillatory_network (sync): Sync oscillatory network whose structure of connections is required for calculation.
        @param[in] start_iteration (uint): The first iteration that is used for calculation, if 'None' then the first is used
        @param[in] stop_iteration (uint): The last iteration that is used for calculation, if 'None' then the last is used.


draw_dynamics_set(sync_output_dynamics, "<STR_LIT:t>", "<STR_LIT>", None, [<NUM_LIT:0>, <NUM_LIT:2> * <NUM_LIT>], False, False)<EOL>

!
        @brief Shows several output dynamics (output of each oscillator) during simulation.
        @details Each dynamic is presented on separate plot.

        @param[in] sync_output_dynamics (list): list of output dynamics 'sync_dynamic' of the Sync network.

        @see show_output_dynamic


if (self._ccore_network_pointer is not None):<EOL><INDENT>return wrapper.sync_order(self._ccore_network_pointer);<EOL><DEDENT>return order_estimator.calculate_sync_order(self._phases)<EOL>

!
        @brief Calculates current level of global synchorization (order parameter) in the network.
        @details This parameter is tend 1.0 when the oscillatory network close to global synchronization and it tend to 0.0 when
                  desynchronization is observed in the network. Order parameter is calculated using following equation:

                  \f[
                  r_{c}=\frac{1}{Ne^{i\varphi }}\sum_{j=0}^{N}e^{i\theta_{j}};
                  \f]

                  where \f$\varphi\f$ is a average phase coordinate in the network, \f$N\f$ is an amount of oscillators in the network.

        Example:
        @code
            oscillatory_network = sync(16, type_conn = conn_type.ALL_TO_ALL);
            output_dynamic = oscillatory_network.simulate_static(100, 10);

            if (oscillatory_network.sync_order() < 0.9): print("Global synchronization is not reached yet.");
            else: print("Global synchronization is reached.");
        @endcode

        @return (double) Level of global synchronization (order parameter).

        @see sync_local_order()


if ( (self._ccore_sync_dynamic_pointer is not None) and ( (self._time is None) or (len(self._time) == <NUM_LIT:0>) ) ):<EOL><INDENT>self._time = wrapper.sync_dynamic_get_time(self._ccore_sync_dynamic_pointer);<EOL><DEDENT>return self._time<EOL>

!
        @brief (list) Returns sampling times when dynamic is measured during simulation.


@staticmethod<EOL><INDENT>def animate_output_dynamic(sync_output_dynamic, animation_velocity = <NUM_LIT>, save_movie = None):<DEDENT>

figure = plt.figure();<EOL>dynamic = sync_output_dynamic.output[<NUM_LIT:0>];<EOL>artist, = plt.polar(dynamic, [<NUM_LIT:1.0>] * len(dynamic), '<STR_LIT:o>', color = '<STR_LIT>');<EOL>def init_frame():<EOL><INDENT>return [ artist ];<EOL><DEDENT>def frame_generation(index_dynamic):<EOL><INDENT>dynamic = sync_output_dynamic.output[index_dynamic];<EOL>artist.set_data(dynamic, [<NUM_LIT:1.0>] * len(dynamic));<EOL>return [ artist ];<EOL><DEDENT>phase_animation = animation.FuncAnimation(figure, frame_generation, len(sync_output_dynamic), interval = animation_velocity, init_func = init_frame, repeat_delay = <NUM_LIT>);<EOL>if (save_movie is not None):<EOL><INDENT>phase_animation.save(save_movie, writer = '<STR_LIT>', fps = <NUM_LIT:15>, bitrate = <NUM_LIT>);<EOL><DEDENT>else:<EOL><INDENT>plt.show();<EOL><DEDENT>

!
        @brief Shows animation of output dynamic (output of each oscillator) during simulation on a circle from [0; 2pi].

        @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network.
        @param[in] animation_velocity (uint): Interval between frames in milliseconds.
        @param[in] save_movie (string): If it is specified then animation will be stored to file that is specified in this parameter.


def _calculate_phases(self, solution, t, step, int_step):

next_phases = [<NUM_LIT:0.0>] * self._num_osc;    <EOL>for index in range (<NUM_LIT:0>, self._num_osc, <NUM_LIT:1>):<EOL><INDENT>if (solution == solve_type.FAST):<EOL><INDENT>result = self._phases[index] + self._phase_kuramoto(self._phases[index], <NUM_LIT:0>, index);<EOL>next_phases[index] = self._phase_normalization(result);<EOL><DEDENT>elif ( (solution == solve_type.RK4) or (solution == solve_type.RKF45) ):<EOL><INDENT>result = odeint(self._phase_kuramoto, self._phases[index], numpy.arange(t - step, t, int_step), (index , ));<EOL>next_phases[index] = self._phase_normalization(result[len(result) - <NUM_LIT:1>][<NUM_LIT:0>]);<EOL><DEDENT>else:<EOL><INDENT>raise NameError("<STR_LIT>" + str(solution) + "<STR_LIT>");<EOL><DEDENT><DEDENT>return next_phases<EOL>

!
        @brief Calculates new phases for oscillators in the network in line with current step.

        @param[in] solution (solve_type): Type solver of the differential equation.
        @param[in] t (double): Time of simulation.
        @param[in] step (double): Step of solution at the end of which states of oscillators should be calculated.
        @param[in] int_step (double): Step differentiation that is used for solving differential equation.

        @return (list) New states (phases) for oscillators.


def __init__(self, num_osc, weight = <NUM_LIT:1>, frequency = <NUM_LIT:0>, type_conn = conn_type.ALL_TO_ALL, representation = conn_represent.MATRIX, initial_phases = initial_type.RANDOM_GAUSSIAN, ccore = True):

self._ccore_network_pointer = None;      <EOL>if ( (ccore is True) and ccore_library.workable() ):<EOL><INDENT>self._ccore_network_pointer = wrapper.sync_create_network(num_osc, weight, frequency, type_conn, initial_phases);<EOL>self._num_osc = num_osc;<EOL>self._conn_represent = conn_represent.MATRIX;<EOL><DEDENT>else:   <EOL><INDENT>super().__init__(num_osc, type_conn, representation);<EOL>self._weight = weight;<EOL>self._phases = list();<EOL>self._freq = list();<EOL>random.seed();<EOL>for index in range(<NUM_LIT:0>, num_osc, <NUM_LIT:1>):<EOL><INDENT>if (initial_phases == initial_type.RANDOM_GAUSSIAN):<EOL><INDENT>self._phases.append(random.random() * <NUM_LIT:2> * pi);<EOL><DEDENT>elif (initial_phases == initial_type.EQUIPARTITION):<EOL><INDENT>self._phases.append( pi / num_osc * index);<EOL><DEDENT>self._freq.append(random.random() * frequency);<EOL><DEDENT><DEDENT>

!
        @brief Constructor of oscillatory network is based on Kuramoto model.

        @param[in] num_osc (uint): Number of oscillators in the network.
        @param[in] weight (double): Coupling strength of the links between oscillators.
        @param[in] frequency (double): Multiplier of internal frequency of the oscillators.
        @param[in] type_conn (conn_type): Type of connection between oscillators in the network (all-to-all, grid, bidirectional list, etc.).
        @param[in] representation (conn_represent): Internal representation of connection in the network: matrix or list.
        @param[in] initial_phases (initial_type): Type of initialization of initial phases of oscillators (random, uniformly distributed, etc.).
        @param[in] ccore (bool): If True simulation is performed by CCORE library (C++ implementation of pyclustering).


@staticmethod<EOL><INDENT>def animate_phase_matrix(sync_output_dynamic, grid_width = None, grid_height = None, animation_velocity = <NUM_LIT>, colormap = '<STR_LIT>', save_movie = None):<DEDENT>

figure = plt.figure();<EOL>def init_frame(): <EOL><INDENT>return frame_generation(<NUM_LIT:0>);<EOL><DEDENT>def frame_generation(index_dynamic):<EOL><INDENT>figure.clf();<EOL>axis = figure.add_subplot(<NUM_LIT>);<EOL>phase_matrix = sync_output_dynamic.allocate_phase_matrix(grid_width, grid_height, index_dynamic);<EOL>axis.imshow(phase_matrix, cmap = plt.get_cmap(colormap), interpolation='<STR_LIT>', vmin = <NUM_LIT:0.0>, vmax = <NUM_LIT> * math.pi);<EOL>artist = figure.gca();<EOL>return [ artist ];<EOL><DEDENT>phase_animation = animation.FuncAnimation(figure, frame_generation, len(sync_output_dynamic), init_func = init_frame, interval = animation_velocity , repeat_delay = <NUM_LIT:1000>);<EOL>if (save_movie is not None):<EOL><INDENT>phase_animation.save(save_movie, writer = '<STR_LIT>', fps = <NUM_LIT:15>, bitrate = <NUM_LIT>);<EOL><DEDENT>else:<EOL><INDENT>plt.show();<EOL><DEDENT>

!
        @brief Shows animation of phase matrix between oscillators during simulation on 2D stage.
        @details If grid_width or grid_height are not specified than phase matrix size will by calculated automatically by square root.

        @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network.
        @param[in] grid_width (uint): Width of the phase matrix.
        @param[in] grid_height (uint): Height of the phase matrix.
        @param[in] animation_velocity (uint): Interval between frames in milliseconds.
        @param[in] colormap (string): Name of colormap that is used by matplotlib ('gray', 'pink', 'cool', spring', etc.).
        @param[in] save_movie (string): If it is specified then animation will be stored to file that is specified in this parameter.


def allocate_sync_ensembles(self, tolerance = <NUM_LIT>, indexes = None, iteration = None):

if (self._ccore_sync_dynamic_pointer is not None):<EOL><INDENT>ensembles = wrapper.sync_dynamic_allocate_sync_ensembles(self._ccore_sync_dynamic_pointer, tolerance, iteration);<EOL>if (indexes is not None):<EOL><INDENT>for ensemble in ensembles:<EOL><INDENT>for index in range(len(ensemble)):<EOL><INDENT>ensemble[index] = indexes[ ensemble[index] ];<EOL><DEDENT><DEDENT><DEDENT>return ensembles;<EOL><DEDENT>if ( (self._dynamic is None) or (len(self._dynamic) == <NUM_LIT:0>) ):<EOL><INDENT>return [];<EOL><DEDENT>number_oscillators = len(self._dynamic[<NUM_LIT:0>]);<EOL>last_state = None;<EOL>if (iteration is None):<EOL><INDENT>last_state = self._dynamic[len(self._dynamic) - <NUM_LIT:1>];<EOL><DEDENT>else:<EOL><INDENT>last_state = self._dynamic[iteration];<EOL><DEDENT>clusters = [];<EOL>if (number_oscillators > <NUM_LIT:0>):<EOL><INDENT>clusters.append([<NUM_LIT:0>]);<EOL><DEDENT>for i in range(<NUM_LIT:1>, number_oscillators, <NUM_LIT:1>):<EOL><INDENT>cluster_allocated = False;<EOL>for cluster in clusters:<EOL><INDENT>for neuron_index in cluster:<EOL><INDENT>last_state_shifted = abs(last_state[i] - <NUM_LIT:2> * pi);<EOL>if ( ( (last_state[i] < (last_state[neuron_index] + tolerance)) and (last_state[i] > (last_state[neuron_index] - tolerance)) ) or<EOL>( (last_state_shifted < (last_state[neuron_index] + tolerance)) and (last_state_shifted > (last_state[neuron_index] - tolerance)) ) ):<EOL><INDENT>cluster_allocated = True;<EOL>real_index = i;<EOL>if (indexes is not None):<EOL><INDENT>real_index = indexes[i];<EOL><DEDENT>cluster.append(real_index);<EOL>break;<EOL><DEDENT><DEDENT>if (cluster_allocated == True):<EOL><INDENT>break;<EOL><DEDENT><DEDENT>if (cluster_allocated == False):<EOL><INDENT>clusters.append([i]);<EOL><DEDENT><DEDENT>return clusters<EOL>

!
        @brief Allocate clusters in line with ensembles of synchronous oscillators where each synchronous ensemble corresponds to only one cluster.

        @param[in] tolerance (double): Maximum error for allocation of synchronous ensemble oscillators.
        @param[in] indexes (list): List of real object indexes and it should be equal to amount of oscillators (in case of 'None' - indexes are in range [0; amount_oscillators]).
        @param[in] iteration (uint): Iteration of simulation that should be used for allocation.

        @return (list) Grours (lists) of indexes of synchronous oscillators.
                For example [ [index_osc1, index_osc3], [index_osc2], [index_osc4, index_osc5] ].


def calculate_order_parameter(self, start_iteration = None, stop_iteration = None):

(start_iteration, stop_iteration) = self.__get_start_stop_iterations(start_iteration, stop_iteration);<EOL>if (self._ccore_sync_dynamic_pointer is not None):<EOL><INDENT>return wrapper.sync_dynamic_calculate_order(self._ccore_sync_dynamic_pointer, start_iteration, stop_iteration);<EOL><DEDENT>sequence_order = [];<EOL>for index in range(start_iteration, stop_iteration):<EOL><INDENT>sequence_order.append(order_estimator.calculate_sync_order(self.output[index]));<EOL><DEDENT>return sequence_order<EOL>

!
        @brief Calculates level of global synchorization (order parameter).
        @details This parameter is tend 1.0 when the oscillatory network close to global synchronization and it tend to 0.0 when
                  desynchronization is observed in the network. Order parameter is calculated using following equation:

                  \f[
                  r_{c}=\frac{1}{Ne^{i\varphi }}\sum_{j=0}^{N}e^{i\theta_{j}};
                  \f]

                  where \f$\varphi\f$ is a average phase coordinate in the network, \f$N\f$ is an amount of oscillators in the network.

        @param[in] start_iteration (uint): The first iteration that is used for calculation, if 'None' then the last iteration is used.
        @param[in] stop_iteration (uint): The last iteration that is used for calculation, if 'None' then 'start_iteration' + 1 is used.

        Example:
        @code
            oscillatory_network = sync(16, type_conn = conn_type.ALL_TO_ALL);
            output_dynamic = oscillatory_network.simulate_static(100, 10);

            print("Order parameter at the last step: ", output_dynamic.calculate_order_parameter());
            print("Order parameter at the first step:", output_dynamic.calculate_order_parameter(0));
            print("Order parameter evolution between 40 and 50 steps:", output_dynamic.calculate_order_parameter(40, 50));
        @endcode

        @return (list) List of levels of global synchronization (order parameter evolution).

        @see order_estimator


def calculate_local_order_parameter(self, oscillatory_network, start_iteration = None, stop_iteration = None):

(start_iteration, stop_iteration) = self.__get_start_stop_iterations(start_iteration, stop_iteration);<EOL>if (self._ccore_sync_dynamic_pointer is not None):<EOL><INDENT>network_pointer = oscillatory_network._ccore_network_pointer;<EOL>return wrapper.sync_dynamic_calculate_local_order(self._ccore_sync_dynamic_pointer, network_pointer, start_iteration, stop_iteration);<EOL><DEDENT>sequence_local_order = [];<EOL>for index in range(start_iteration, stop_iteration):<EOL><INDENT>sequence_local_order.append(order_estimator.calculate_local_sync_order(self.output[index], oscillatory_network));<EOL><DEDENT>return sequence_local_order<EOL>

!
        @brief Calculates local order parameter.
        @details Local order parameter or so-called level of local or partial synchronization is calculated by following expression:

        \f[
        r_{c}=\left | \sum_{i=0}^{N} \frac{1}{N_{i}} \sum_{j=0}e^{ \theta_{j} - \theta_{i} } \right |;
        \f]

        where N - total amount of oscillators in the network and \f$N_{i}\f$ - amount of neighbors of oscillator with index \f$i\f$.

        @param[in] oscillatory_network (sync): Sync oscillatory network whose structure of connections is required for calculation.
        @param[in] start_iteration (uint): The first iteration that is used for calculation, if 'None' then the last iteration is used.
        @param[in] stop_iteration (uint): The last iteration that is used for calculation, if 'None' then 'start_iteration' + 1 is used.

        @return (list) List of levels of local (partial) synchronization (local order parameter evolution).


norm_teta = teta;<EOL>while (norm_teta > (<NUM_LIT> * pi)) or (norm_teta < <NUM_LIT:0>):<EOL><INDENT>if (norm_teta > (<NUM_LIT> * pi)):<EOL><INDENT>norm_teta -= <NUM_LIT> * pi;<EOL><DEDENT>else:<EOL><INDENT>norm_teta += <NUM_LIT> * pi;<EOL><DEDENT><DEDENT>return norm_teta<EOL>

!
        @brief Normalization of phase of oscillator that should be placed between [0; 2 * pi].

        @param[in] teta (double): phase of oscillator.

        @return (double) Normalized phase.


<EOL>self.membrane_potential      = <NUM_LIT:0.0>;<EOL>self.active_cond_sodium      = <NUM_LIT:0.0>;<EOL>self.inactive_cond_sodium    = <NUM_LIT:0.0>;<EOL>self.active_cond_potassium   = <NUM_LIT:0.0>;<EOL>self.pulse_generation = False;<EOL>self.pulse_generation_time = []<EOL>

!
        @brief Constructor of central element.


def __update_peripheral_neurons(self, t, step, next_membrane, next_active_sodium, next_inactive_sodium, next_active_potassium):

self._membrane_potential = next_membrane[:];<EOL>self._active_cond_sodium = next_active_sodium[:];<EOL>self._inactive_cond_sodium = next_inactive_sodium[:];<EOL>self._active_cond_potassium = next_active_potassium[:];<EOL>for index in range(<NUM_LIT:0>, self._num_osc):<EOL><INDENT>if (self._pulse_generation[index] is False):<EOL><INDENT>if (self._membrane_potential[index] >= <NUM_LIT:0.0>):<EOL><INDENT>self._pulse_generation[index] = True;<EOL>self._pulse_generation_time[index].append(t);<EOL><DEDENT><DEDENT>elif (self._membrane_potential[index] < <NUM_LIT:0.0>):<EOL><INDENT>self._pulse_generation[index] = False;<EOL><DEDENT>if (self._link_weight3[index] == <NUM_LIT:0.0>):<EOL><INDENT>if (self._membrane_potential[index] > self._params.threshold):<EOL><INDENT>self._link_pulse_counter[index] += step;<EOL>if (self._link_pulse_counter[index] >= <NUM_LIT:1> / self._params.eps):<EOL><INDENT>self._link_weight3[index] = self._params.w3;<EOL>self._link_activation_time[index] = t;<EOL><DEDENT><DEDENT><DEDENT>elif ( not ((self._link_activation_time[index] < t) and (t < self._link_activation_time[index] + self._params.deltah)) ):<EOL><INDENT>self._link_weight3[index] = <NUM_LIT:0.0>;<EOL>self._link_pulse_counter[index] = <NUM_LIT:0.0>;<EOL><DEDENT><DEDENT>

!
        @brief Update peripheral neurons in line with new values of current in channels.

        @param[in] t (doubles): Current time of simulation.
        @param[in] step (uint): Step (time duration) during simulation when states of oscillators should be calculated.
        @param[in] next_membrane (list): New values of membrane potentials for peripheral neurons.
        @Param[in] next_active_sodium (list): New values of activation conductances of the sodium channels for peripheral neurons.
        @param[in] next_inactive_sodium (list): New values of inactivaton conductances of the sodium channels for peripheral neurons.
        @param[in] next_active_potassium (list): New values of activation conductances of the potassium channel for peripheral neurons.


return "<STR_LIT>" % (self.membrane_potential, self.pulse_generation_time)<EOL>

!
        @brief Returns string that represents central element.


index = argv;<EOL>v = inputs[<NUM_LIT:0>]; <EOL>m = inputs[<NUM_LIT:1>]; <EOL>h = inputs[<NUM_LIT:2>]; <EOL>n = inputs[<NUM_LIT:3>]; <EOL>active_sodium_part = self._params.gNa * (m ** <NUM_LIT:3>) * h * (v - self._params.vNa);<EOL>inactive_sodium_part = self._params.gK * (n ** <NUM_LIT:4>) * (v - self._params.vK);<EOL>active_potassium_part = self._params.gL * (v - self._params.vL);<EOL>Iion = active_sodium_part + inactive_sodium_part + active_potassium_part;<EOL>Iext = <NUM_LIT:0.0>;<EOL>Isyn = <NUM_LIT:0.0>;<EOL>if (index < self._num_osc): <EOL><INDENT>Iext = self._stimulus[index] * self._noise[index];    <EOL>memory_impact1 = <NUM_LIT:0.0>;<EOL>for i in range(<NUM_LIT:0>, len(self._central_element[<NUM_LIT:0>].pulse_generation_time)):<EOL><INDENT>memory_impact1 += self.__alfa_function(t - self._central_element[<NUM_LIT:0>].pulse_generation_time[i], self._params.alfa_inhibitory, self._params.betta_inhibitory);<EOL><DEDENT>memory_impact2 = <NUM_LIT:0.0>;<EOL>for i in range(<NUM_LIT:0>, len(self._central_element[<NUM_LIT:1>].pulse_generation_time)):<EOL><INDENT>memory_impact2 += self.__alfa_function(t - self._central_element[<NUM_LIT:1>].pulse_generation_time[i], self._params.alfa_inhibitory, self._params.betta_inhibitory);<EOL><DEDENT>Isyn = self._params.w2 * (v - self._params.Vsyninh) * memory_impact1 + self._link_weight3[index] * (v - self._params.Vsyninh) * memory_impact2;<EOL><DEDENT>else:<EOL><INDENT>central_index = index - self._num_osc;<EOL>if (central_index == <NUM_LIT:0>):<EOL><INDENT>Iext = self._params.Icn1;   <EOL>memory_impact = <NUM_LIT:0.0>;<EOL>for index_oscillator in range(<NUM_LIT:0>, self._num_osc):<EOL><INDENT>for index_generation in range(<NUM_LIT:0>, len(self._pulse_generation_time[index_oscillator])):<EOL><INDENT>memory_impact += self.__alfa_function(t - self._pulse_generation_time[index_oscillator][index_generation], self._params.alfa_excitatory, self._params.betta_excitatory);<EOL><DEDENT><DEDENT>Isyn = self._params.w1 * (v - self._params.Vsynexc) * memory_impact;<EOL><DEDENT>elif (central_index == <NUM_LIT:1>):<EOL><INDENT>Iext = self._params.Icn2;   <EOL>Isyn = <NUM_LIT:0.0>;<EOL><DEDENT>else:<EOL><INDENT>assert <NUM_LIT:0>;<EOL><DEDENT><DEDENT>dv = -Iion + Iext - Isyn;<EOL>potential = v - self._params.vRest;<EOL>am = (<NUM_LIT> - <NUM_LIT:0.1> * potential) / (math.exp(<NUM_LIT> - <NUM_LIT:0.1> * potential) - <NUM_LIT:1.0>);<EOL>ah = <NUM_LIT> * math.exp(-potential / <NUM_LIT>);<EOL>an = (<NUM_LIT:0.1> - <NUM_LIT> * potential) / (math.exp(<NUM_LIT:1.0> - <NUM_LIT:0.1> * potential) - <NUM_LIT:1.0>);<EOL>bm = <NUM_LIT> * math.exp(-potential / <NUM_LIT>);<EOL>bh = <NUM_LIT:1.0> / (math.exp(<NUM_LIT> - <NUM_LIT:0.1> * potential) + <NUM_LIT:1.0>);<EOL>bn = <NUM_LIT> * math.exp(-potential / <NUM_LIT>);<EOL>dm = am * (<NUM_LIT:1.0> - m) - bm * m;<EOL>dh = ah * (<NUM_LIT:1.0> - h) - bh * h;<EOL>dn = an * (<NUM_LIT:1.0> - n) - bn * n;<EOL>return [dv, dm, dh, dn]<EOL>

!
        @brief Returns new values of excitatory and inhibitory parts of oscillator and potential of oscillator.

        @param[in] inputs (list): States of oscillator for integration [v, m, h, n] (see description below).
        @param[in] t (double): Current time of simulation.
        @param[in] argv (tuple): Extra arguments that are not used for integration - index of oscillator.

        @return (list) new values of oscillator [v, m, h, n], where:
                v - membrane potantial of oscillator,
                m - activation conductance of the sodium channel,
                h - inactication conductance of the sodium channel,
                n - activation conductance of the potassium channel.


def __init__(self, num_osc, stimulus = None, parameters = None, type_conn = None, type_conn_represent = conn_represent.MATRIX, ccore = True):

super().__init__(num_osc, conn_type.NONE, type_conn_represent);<EOL>if (stimulus is None):<EOL><INDENT>self._stimulus = [<NUM_LIT:0.0>] * num_osc;<EOL><DEDENT>else:<EOL><INDENT>self._stimulus = stimulus;<EOL><DEDENT>if (parameters is not None):<EOL><INDENT>self._params = parameters;<EOL><DEDENT>else:<EOL><INDENT>self._params = hhn_parameters();<EOL><DEDENT>self.__ccore_hhn_pointer = None;<EOL>self.__ccore_hhn_dynamic_pointer = None;<EOL>if ( (ccore is True) and ccore_library.workable() ):<EOL><INDENT>self.__ccore_hhn_pointer = wrapper.hhn_create(num_osc, self._params);<EOL><DEDENT>else:<EOL><INDENT>self._membrane_dynamic_pointer = None;        <EOL>self._membrane_potential        = [<NUM_LIT:0.0>] * self._num_osc;<EOL>self._active_cond_sodium        = [<NUM_LIT:0.0>] * self._num_osc;<EOL>self._inactive_cond_sodium      = [<NUM_LIT:0.0>] * self._num_osc;<EOL>self._active_cond_potassium     = [<NUM_LIT:0.0>] * self._num_osc;<EOL>self._link_activation_time      = [<NUM_LIT:0.0>] * self._num_osc;<EOL>self._link_pulse_counter        = [<NUM_LIT:0.0>] * self._num_osc;<EOL>self._link_deactivation_time    = [<NUM_LIT:0.0>] * self._num_osc;<EOL>self._link_weight3              = [<NUM_LIT:0.0>] * self._num_osc;<EOL>self._pulse_generation_time     = [ [] for i in range(self._num_osc) ];<EOL>self._pulse_generation          = [False] * self._num_osc;<EOL>self._noise = [random.random() * <NUM_LIT> - <NUM_LIT:1.0> for i in range(self._num_osc)];<EOL>self._central_element = [central_element(), central_element()];<EOL><DEDENT>

!
        @brief Constructor of oscillatory network based on Hodgkin-Huxley neuron model.

        @param[in] num_osc (uint): Number of peripheral oscillators in the network.
        @param[in] stimulus (list): List of stimulus for oscillators, number of stimulus should be equal to number of peripheral oscillators.
        @param[in] parameters (hhn_parameters): Parameters of the network.
        @param[in] type_conn (conn_type): Type of connections between oscillators in the network (ignored for this type of network).
        @param[in] type_conn_represent (conn_represent): Internal representation of connection in the network: matrix or list.
        @param[in] ccore (bool): If 'True' then CCORE is used (C/C++ implementation of the model).


if self.__ccore_pcnn_dynamic_pointer is not None:<EOL><INDENT>return wrapper.pcnn_dynamic_allocate_spike_ensembles(self.__ccore_pcnn_dynamic_pointer)<EOL><DEDENT>spike_ensembles = []<EOL>number_oscillators = len(self.__dynamic[<NUM_LIT:0>])<EOL>for t in range(len(self.__dynamic)):<EOL><INDENT>spike_ensemble = []<EOL>for index in range(number_oscillators):<EOL><INDENT>if self.__dynamic[t][index] == self.__OUTPUT_TRUE:<EOL><INDENT>spike_ensemble.append(index)<EOL><DEDENT><DEDENT>if len(spike_ensemble) > <NUM_LIT:0>:<EOL><INDENT>spike_ensembles.append(spike_ensemble)<EOL><DEDENT><DEDENT>return spike_ensembles<EOL>

!
        @brief Analyses output dynamic of network and allocates spikes on each iteration as a list of indexes of oscillators.
        @details Each allocated spike ensemble represents list of indexes of oscillators whose output is active.

        @return (list) Spike ensembles of oscillators.


if self.__ccore_pcnn_dynamic_pointer is not None:<EOL><INDENT>return wrapper.pcnn_dynamic_allocate_time_signal(self.__ccore_pcnn_dynamic_pointer)<EOL><DEDENT>signal_vector_information = []<EOL>for t in range(<NUM_LIT:0>, len(self.__dynamic)):<EOL><INDENT>signal_vector_information.append(sum(self.__dynamic[t]))<EOL><DEDENT>return signal_vector_information<EOL>

!
        @brief Analyses output dynamic and calculates time signal (signal vector information) of network output.

        @return (list) Time signal of network output.


if self.__ccore_pcnn_dynamic_pointer is not None:<EOL><INDENT>wrapper.pcnn_dynamic_destroy(self.__ccore_pcnn_dynamic_pointer)<EOL><DEDENT>

!
        @brief Default destructor of PCNN dynamic.


if self.__ccore_pcnn_dynamic_pointer is not None:<EOL><INDENT>return wrapper.pcnn_dynamic_get_time(self.__ccore_pcnn_dynamic_pointer)<EOL><DEDENT>return list(range(len(self)))<EOL>

!
        @brief (list) Returns sampling times when dynamic is measured during simulation.


@staticmethod<EOL><INDENT>def show_output_dynamic(pcnn_output_dynamic, separate_representation = False):<DEDENT>

draw_dynamics(pcnn_output_dynamic.time, pcnn_output_dynamic.output, x_title = "<STR_LIT:t>", y_title = "<STR_LIT>", separate = separate_representation)<EOL>

!
        @brief Shows output dynamic (output of each oscillator) during simulation.

        @param[in] pcnn_output_dynamic (pcnn_dynamic): Output dynamic of the pulse-coupled neural network.
        @param[in] separate_representation (list): Consists of lists of oscillators where each such list consists of oscillator indexes that will be shown on separated stage.


def allocate_sync_ensembles(self, tolerance = <NUM_LIT:0.1>):

return pyclustering.utils.allocate_sync_ensembles(self.__amplitude, tolerance, <NUM_LIT:0.0>)<EOL>

!
        @brief Allocate clusters in line with ensembles of synchronous oscillators where each synchronous ensemble corresponds to only one cluster.

        @param[in] tolerance (double): Maximum error for allocation of synchronous ensemble oscillators.

        @return (list) Grours of indexes of synchronous oscillators, for example, [ [index_osc1, index_osc3], [index_osc2], [index_osc4, index_osc5] ].


def __init__(self, num_osc, factor_frequency = <NUM_LIT:1.0>, factor_radius = <NUM_LIT:1.0>, factor_coupling = <NUM_LIT:1.0>, type_conn = conn_type.ALL_TO_ALL, representation = conn_represent.MATRIX):

super().__init__(num_osc, type_conn, representation);<EOL>self.__frequency = factor_frequency if isinstance(factor_frequency, list) else [ fsync_network.__DEFAULT_FREQUENCY_VALUE * factor_frequency for _ in range(num_osc) ];<EOL>self.__radius = factor_radius if isinstance(factor_radius, list) else [ fsync_network.__DEFAULT_RADIUS_VALUE * factor_radius for _ in range(num_osc) ];<EOL>self.__coupling_strength = fsync_network.__DEFAULT_COUPLING_STRENGTH * factor_coupling;<EOL>self.__properties = [ self.__oscillator_property(index) for index in range(self._num_osc) ];<EOL>random.seed();<EOL>self.__amplitude = [ random.random() for _ in range(num_osc) ]<EOL>

!
        @brief Constructor of oscillatory network based on synchronization Kuramoto model and Landau-Stuart oscillator.

        @param[in] num_osc (uint): Amount oscillators in the network.
        @param[in] factor_frequency (double|list): Frequency of oscillators, it can be specified as common value for all oscillators by
                    single double value and for each separately by list.
        @param[in] factor_radius (double|list): Radius of oscillators that affects amplitude, it can be specified as common value for all oscillators by
                    single double value and for each separately by list.
        @param[in] factor_coupling (double): Coupling strength between oscillators.
        @param[in] type_conn (conn_type): Type of connection between oscillators in the network (all-to-all, grid, bidirectional list, etc.).
        @param[in] representation (conn_represent): Internal representation of connection in the network: matrix or list.


def __landau_stuart(self, amplitude, index):

return (self.__properties[index] - numpy.absolute(amplitude) ** <NUM_LIT:2>) * amplitude<EOL>

!
        @brief Calculate Landau-Stuart state.

        @param[in] amplitude (double): Current amplitude of oscillator.
        @param[in] index (uint): Oscillator index whose state is calculated.

        @return (double) Landau-Stuart state.


return self.__time<EOL>

!
        @brief (list) Returns time-points corresponds to dynamic-points points.


def simulate(self, steps, time, collect_dynamic = False):

dynamic_amplitude, dynamic_time = ([], []) if collect_dynamic is False else ([self.__amplitude], [<NUM_LIT:0>]);<EOL>step = time / steps;<EOL>int_step = step / <NUM_LIT>;<EOL>for t in numpy.arange(step, time + step, step):<EOL><INDENT>self.__amplitude = self.__calculate(t, step, int_step);<EOL>if collect_dynamic is True:<EOL><INDENT>dynamic_amplitude.append([ numpy.real(amplitude)[<NUM_LIT:0>] for amplitude in self.__amplitude ]);<EOL>dynamic_time.append(t);<EOL><DEDENT><DEDENT>if collect_dynamic is False:<EOL><INDENT>dynamic_amplitude.append([ numpy.real(amplitude)[<NUM_LIT:0>] for amplitude in self.__amplitude ]);<EOL>dynamic_time.append(time);<EOL><DEDENT>output_sync_dynamic = fsync_dynamic(dynamic_amplitude, dynamic_time);<EOL>return output_sync_dynamic<EOL>

!
        @brief Performs static simulation of oscillatory network.

        @param[in] steps (uint): Number simulation steps.
        @param[in] time (double): Time of simulation.
        @param[in] collect_dynamic (bool): If True - returns whole dynamic of oscillatory network, otherwise returns only last values of dynamics.

        @return (list) Dynamic of oscillatory network. If argument 'collect_dynamic' is True, than return dynamic for the whole simulation time,
                 otherwise returns only last values (last step of simulation) of output dynamic.

        @see simulate()
        @see simulate_dynamic()