<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ruslanlazovskiy</id>
	<title>Алговики - Вклад [ru]</title>
	<link rel="self" type="application/atom+xml" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ruslanlazovskiy"/>
	<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/ru/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Ruslanlazovskiy"/>
	<updated>2026-10-22T19:58:27Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=19456</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=19456"/>
		<updated>2016-11-29T10:10:21Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy &amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] (разделы 1.1 - 1.4 , 1.7 , 1.8),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87 &amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] (разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2)&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики (простейший пример — евклидова метрика). Не следует путать задачу кластеризации с задачей классификации: в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик (возможные метрики будут подробно описаны далее). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt;, возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа (т.е. объекты), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа (т.е. построенные связи между ближайшими соседями). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; (имеется ввиду количество вершин) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; (имеется ввиду количество вершин). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений (для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON (см. раздел &amp;quot;Существующие реализации&amp;quot;). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации (такая кластеризация, очевидно, не будет иметь практического смысла), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью, включающий в себя значительную модификацию исходного алгоритма, но не приводится рабочая реализация.&lt;br /&gt;
&lt;br /&gt;
В силу вышескасновного основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла. Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
Для исследования такой масштабируемости вширь использовалась референсная последовательная реализация алгоритма (cм. раздел &amp;quot;Существующие реализации&amp;quot;). Соответствующая программа запускалась на системе BG/P на одном вычислительном узле. Характеристики вычислительного узла, а также микропроцессорного ядра - элемента такого узла, приводятся в &amp;lt;ref&amp;gt;http://hpc.cmc.msu.ru/bgp&amp;lt;/ref&amp;gt; Таким образом, удостоверенными экспериментальными данными являются только значения, полученные для случая 1 процесса. Значения для случаев 2 и 4 процессов являются ОЦЕНОЧНЫМИ и выводятся из результатов работы модифицированной версии алгоритма, исследуемой в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. К сожалению, указанной реализации авторы не предоставляют. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Теоретически возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=19455</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=19455"/>
		<updated>2016-11-29T10:10:02Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] (разделы 1.1 - 1.4 , 1.7 , 1.8),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87 &amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] (разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2)&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики (простейший пример — евклидова метрика). Не следует путать задачу кластеризации с задачей классификации: в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик (возможные метрики будут подробно описаны далее). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt;, возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа (т.е. объекты), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа (т.е. построенные связи между ближайшими соседями). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; (имеется ввиду количество вершин) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; (имеется ввиду количество вершин). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений (для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON (см. раздел &amp;quot;Существующие реализации&amp;quot;). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации (такая кластеризация, очевидно, не будет иметь практического смысла), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью, включающий в себя значительную модификацию исходного алгоритма, но не приводится рабочая реализация.&lt;br /&gt;
&lt;br /&gt;
В силу вышескасновного основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла. Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
Для исследования такой масштабируемости вширь использовалась референсная последовательная реализация алгоритма (cм. раздел &amp;quot;Существующие реализации&amp;quot;). Соответствующая программа запускалась на системе BG/P на одном вычислительном узле. Характеристики вычислительного узла, а также микропроцессорного ядра - элемента такого узла, приводятся в &amp;lt;ref&amp;gt;http://hpc.cmc.msu.ru/bgp&amp;lt;/ref&amp;gt; Таким образом, удостоверенными экспериментальными данными являются только значения, полученные для случая 1 процесса. Значения для случаев 2 и 4 процессов являются ОЦЕНОЧНЫМИ и выводятся из результатов работы модифицированной версии алгоритма, исследуемой в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. К сожалению, указанной реализации авторы не предоставляют. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Теоретически возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=19379</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=19379"/>
		<updated>2016-11-28T15:16:00Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] (разделы 1.1 - 1.4 , 1.7 , 1.8),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] (разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2)&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики (простейший пример — евклидова метрика). Не следует путать задачу кластеризации с задачей классификации: в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик (возможные метрики будут подробно описаны далее). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt;, возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа (т.е. объекты), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа (т.е. построенные связи между ближайшими соседями). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; (имеется ввиду количество вершин) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; (имеется ввиду количество вершин). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений (для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON (см. раздел &amp;quot;Существующие реализации&amp;quot;). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации (такая кластеризация, очевидно, не будет иметь практического смысла), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью, включающий в себя значительную модификацию исходного алгоритма, но не приводится рабочая реализация.&lt;br /&gt;
&lt;br /&gt;
В силу вышескасновного основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла. Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
Для исследования такой масштабируемости вширь использовалась референсная последовательная реализация алгоритма (cм. раздел &amp;quot;Существующие реализации&amp;quot;). Соответствующая программа запускалась на системе BG/P на одном вычислительном узле. Характеристики вычислительного узла, а также микропроцессорного ядра - элемента такого узла, приводятся в &amp;lt;ref&amp;gt;http://hpc.cmc.msu.ru/bgp&amp;lt;/ref&amp;gt; Таким образом, удостоверенными экспериментальными данными являются только значения, полученные для случая 1 процесса. Значения для случаев 2 и 4 процессов являются ОЦЕНОЧНЫМИ и выводятся из результатов работы модифицированной версии алгоритма, исследуемой в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. К сожалению, указанной реализации авторы не предоставляют. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Теоретически возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Ruslanlazovskiy&amp;diff=19378</id>
		<title>Обсуждение участника:Ruslanlazovskiy</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Ruslanlazovskiy&amp;diff=19378"/>
		<updated>2016-11-28T15:15:25Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Скобки. */ новая тема&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:Ruslanlazovskiy/CHAMELEON]] ==&lt;br /&gt;
&lt;br /&gt;
1) все ссылки в статье не работают&lt;br /&gt;
&lt;br /&gt;
2) список литературы оформлен неправильно - см. как сделано в [[Разложение_Холецкого_(метод_квадратного_корня)]]&lt;br /&gt;
&lt;br /&gt;
3) для оформления (псевдо) кода следует использовать тег &amp;lt;nowiki&amp;gt;&amp;lt;source lang=&amp;quot;...&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Мои правки ==&lt;br /&gt;
&lt;br /&gt;
2) и 3) теперь сделаны как надо. В 1) не удалось поправить самую первую ссылку, ресурс с последовательной реализацией действительно умер.&lt;br /&gt;
&lt;br /&gt;
== Замечания к статье про Хамелеон (ещё порция) ==&lt;br /&gt;
&lt;br /&gt;
* Ссылки на авторов и список литературы - присоединяюсь к замечаниям. Список литературы действительно всего из одного наименования? [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* В разделе 1 пояснить, нужно ли заранее знать число кластеров. Это неясно и из описания входных и выходных данных, должно же оно быть хоть где-нибудь [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* Раздел 1.2. Когда вводим граф, желательно пояснить аргументы V и E в скобках. Аналогично с параметром m, который встречается впервые [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* Раздел 1.6. Стоит сделать логарифм красивей [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
== Правки - порция 2. ==&lt;br /&gt;
&lt;br /&gt;
* В список литературы добавлена статья с исследованием параллелизма. Остальные найденные статьи по Chameleon представляют собой кальку с оригинальной статьи ( первый пункт в списке ) в разделе описания алгоритма + описание задачи, для которой применялся алгоритм, для примера добавил одну из таких статей.&lt;br /&gt;
* Сделано&lt;br /&gt;
* Сделано&lt;br /&gt;
* Поправил, добавил описание &amp;quot;предельного&amp;quot; случая.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Изменил статью в соответствии с замечаниями к 2.4&lt;br /&gt;
&lt;br /&gt;
== Замечания к пункту 2.4 == &lt;br /&gt;
&lt;br /&gt;
* Отсутствуют подписи к меткам на оси числа процессов&lt;br /&gt;
* Желательно сделать крупнее размер шрифта подписей&lt;br /&gt;
&lt;br /&gt;
== Ещё замечание ==&lt;br /&gt;
&lt;br /&gt;
* Все, кажется, хорошо, но плохо оформлены скобки в тексте, их надо писать без пробела (так), а не с пробелом по краям ( так не надо ). Я начал исправлять, но их слишком много, поправьте пожалуйста. [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 11:43, 28 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
== Скобки. ==&lt;br /&gt;
&lt;br /&gt;
Готово.&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=19375</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=19375"/>
		<updated>2016-11-28T15:13:52Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] (разделы 1.1 - 1.4 , 1.7 , 1.8),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] (разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2)&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики (простейший пример — евклидова метрика). Не следует путать задачу кластеризации с задачей классификации: в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик (возможные метрики будут подробно описаны далее). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа (т.е. объекты), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа (т.е. построенные связи между ближайшими соседями). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; (имеется ввиду количество вершин) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; (имеется ввиду количество вершин). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений (для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON (см. раздел &amp;quot;Существующие реализации&amp;quot;). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации (такая кластеризация, очевидно, не будет иметь практического смысла), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью, включающий в себя значительную модификацию исходного алгоритма, но не приводится рабочая реализация.&lt;br /&gt;
&lt;br /&gt;
В силу вышескасновного основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла. Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
Для исследования такой масштабируемости вширь использовалась референсная последовательная реализация алгоритма (cм. раздел &amp;quot;Существующие реализации&amp;quot;). Соответствующая программа запускалась на системе BG/P на одном вычислительном узле. Характеристики вычислительного узла, а также микропроцессорного ядра - элемента такого узла, приводятся в &amp;lt;ref&amp;gt;http://hpc.cmc.msu.ru/bgp&amp;lt;/ref&amp;gt; Таким образом, удостоверенными экспериментальными данными являются только значения, полученные для случая 1 процесса. Значения для случаев 2 и 4 процессов являются ОЦЕНОЧНЫМИ и выводятся из результатов работы модифицированной версии алгоритма, исследуемой в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. К сожалению, указанной реализации авторы не предоставляют. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Теоретически возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=19374</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=19374"/>
		<updated>2016-11-28T15:13:28Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] (разделы 1.1 - 1.4 , 1.7 , 1.8),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] (разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2)&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики (простейший пример — евклидова метрика). Не следует путать задачу кластеризации с задачей классификации: в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик (возможные метрики будут подробно описаны далее). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа (т.е. объекты), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа (т.е. построенные связи между ближайшими соседями). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; (имеется ввиду количество вершин) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; (имеется ввиду количество вершин). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений (для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON (см. раздел &amp;quot;Существующие реализации&amp;quot;). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации (такая кластеризация, очевидно, не будет иметь практического смысла), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью, включающий в себя значительную модификацию исходного алгоритма, но не приводится рабочая реализация.&lt;br /&gt;
&lt;br /&gt;
В силу вышескасновного основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла. Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
Для исследования такой масштабируемости вширь использовалась референсная последовательная реализация алгоритма (м. раздел &amp;quot;Существующие реализации&amp;quot;). Соответствующая программа запускалась на системе BG/P на одном вычислительном узле. Характеристики вычислительного узла, а также микропроцессорного ядра - элемента такого узла, приводятся в &amp;lt;ref&amp;gt;http://hpc.cmc.msu.ru/bgp&amp;lt;/ref&amp;gt; Таким образом, удостоверенными экспериментальными данными являются только значения, полученные для случая 1 процесса. Значения для случаев 2 и 4 процессов являются ОЦЕНОЧНЫМИ и выводятся из результатов работы модифицированной версии алгоритма, исследуемой в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. К сожалению, указанной реализации авторы не предоставляют. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Теоретически возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18598</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18598"/>
		<updated>2016-11-20T15:56:32Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью, включающий в себя значительную модификацию исходного алгоритма, но не приводится рабочая реализация.&lt;br /&gt;
&lt;br /&gt;
В силу вышескасновного основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла. Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
Для исследования такой масштабируемости вширь использовалась референсная последовательная реализация алгоритма ( м. раздел &amp;quot;Существующие реализации&amp;quot; ). Соответствующая программа запускалась на системе BG/P на одном вычислительном узле. Характеристики вычислительного узла, а также микропроцессорного ядра - элемента такого узла, приводятся в &amp;lt;ref&amp;gt;http://hpc.cmc.msu.ru/bgp&amp;lt;/ref&amp;gt; Таким образом, удостоверенными экспериментальными данными являются только значения, полученные для случая 1 процесса. Значения для случаев 2 и 4 процессов являются ОЦЕНОЧНЫМИ и выводятся из результатов работы модифицированной версии алгоритма, исследуемой в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. К сожалению, указанной реализации авторы не предоставляют. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Теоретически возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Ruslanlazovskiy&amp;diff=18418</id>
		<title>Обсуждение участника:Ruslanlazovskiy</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Ruslanlazovskiy&amp;diff=18418"/>
		<updated>2016-11-18T21:59:52Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Правки - порция 2. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:Ruslanlazovskiy/CHAMELEON]] ==&lt;br /&gt;
&lt;br /&gt;
1) все ссылки в статье не работают&lt;br /&gt;
&lt;br /&gt;
2) список литературы оформлен неправильно - см. как сделано в [[Разложение_Холецкого_(метод_квадратного_корня)]]&lt;br /&gt;
&lt;br /&gt;
3) для оформления (псевдо) кода следует использовать тег &amp;lt;nowiki&amp;gt;&amp;lt;source lang=&amp;quot;...&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Мои правки ==&lt;br /&gt;
&lt;br /&gt;
2) и 3) теперь сделаны как надо. В 1) не удалось поправить самую первую ссылку, ресурс с последовательной реализацией действительно умер.&lt;br /&gt;
&lt;br /&gt;
== Замечания к статье про Хамелеон (ещё порция) ==&lt;br /&gt;
&lt;br /&gt;
* Ссылки на авторов и список литературы - присоединяюсь к замечаниям. Список литературы действительно всего из одного наименования? [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* В разделе 1 пояснить, нужно ли заранее знать число кластеров. Это неясно и из описания входных и выходных данных, должно же оно быть хоть где-нибудь [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* Раздел 1.2. Когда вводим граф, желательно пояснить аргументы V и E в скобках. Аналогично с параметром m, который встречается впервые [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* Раздел 1.6. Стоит сделать логарифм красивей [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
== Правки - порция 2. ==&lt;br /&gt;
&lt;br /&gt;
* В список литературы добавлена статья с исследованием параллелизма. Остальные найденные статьи по Chameleon представляют собой кальку с оригинальной статьи ( первый пункт в списке ) в разделе описания алгоритма + описание задачи, для которой применялся алгоритм, для примера добавил одну из таких статей.&lt;br /&gt;
* Сделано&lt;br /&gt;
* Сделано&lt;br /&gt;
* Поправил, добавил описание &amp;quot;предельного&amp;quot; случая.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Изменил статью в соответствии с замечаниями к 2.4&lt;br /&gt;
&lt;br /&gt;
== Замечания к пункту 2.4 == &lt;br /&gt;
&lt;br /&gt;
* Отсутствуют подписи к меткам на оси числа процессов&lt;br /&gt;
* Желательно сделать крупнее размер шрифта подписей&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18417</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18417"/>
		<updated>2016-11-18T21:59:04Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью, включающий в себя значительную модификацию исходного алгоритма, но не приводится рабочая реализация.&lt;br /&gt;
&lt;br /&gt;
В силу вышескасновного основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла. Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Теоретически возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18383</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18383"/>
		<updated>2016-11-18T21:10:52Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью, включающий в себя значительную модификацию исходного алгоритма, но не приводится рабочая реализация.&lt;br /&gt;
&lt;br /&gt;
В силу вышескасновного основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла. Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Теоретически возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18382</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18382"/>
		<updated>2016-11-18T21:10:38Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью, включающий в себя значительную модификацию исходного алгоритма, но не приводится рабочая реализация.&lt;br /&gt;
&lt;br /&gt;
В силу вышескасновного основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла. Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Теоретически возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18264</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18264"/>
		<updated>2016-11-18T19:18:40Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью, включающий в себя значительную модификацию исходного алгоритма, но не приводится рабочая реализация.&lt;br /&gt;
&lt;br /&gt;
В силу вышескасновного основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла. Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи. Для исследования такой масштабируемости вширь использовалась референсная последовательная реализация алгоритма ( м. раздел &amp;quot;Существующие реализации&amp;quot; ). Соответствующая программа запускалась на системе BG/P на одном вычислительном узле. Характеристики вычислительного узла, а также микропроцессорного ядра - элемента такого узла, приводятся в &amp;lt;ref&amp;gt;http://hpc.cmc.msu.ru/bgp&amp;lt;/ref&amp;gt; Таким образом, удостоверенными экспериментальными данными являются только значения, полученные для случая 1 процесса. Значения для случаев 2 и 4 процессов являются ОЦЕНОЧНЫМИ и выводятся из результатов работы модифицированной версии алгоритма, исследуемой в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. К сожалению, указанной реализации авторы не предоставляют. &lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Теоретически возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18261</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18261"/>
		<updated>2016-11-18T19:17:19Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью, включающий в себя значительную модификацию исходного алгоритма, но не приводится рабочая реализация.&lt;br /&gt;
&lt;br /&gt;
В силу вышескасновного основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла. Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи. Для исследования такой масштабируемости вширь использовалась референсная последовательная реализация алгоритма ( м. раздел &amp;quot;Существующие реализации&amp;quot; ). Соответствующая программа запускалась на системе BG/P на одном вычислительном узле. Характеристики вычислительного узла, а также микропроцессорного ядра - элемента такого узла, приводятся в &amp;lt;ref&amp;gt;http://hpc.cmc.msu.ru/bgp&amp;lt;/ref&amp;gt; Таким образом, удостоверенными экспериментальными данными являются только значения, полученные для случая 1 процесса. Значения для случаев 2 и 4 процессов являются ОЦЕНОЧНЫМИ и выводятся из результатов работы модифицированной версии алгоритма, исследуемой в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. К сожалению, указанной реализации авторы не предоставляют. &lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18256</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18256"/>
		<updated>2016-11-18T19:10:23Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью, но не приводится рабочая реализация.&lt;br /&gt;
&lt;br /&gt;
В силу вышескасновного основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла. Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи. Для исследования такой масштабируемости вширь использовалась референсная последовательная реализация алгоритма ( м. раздел &amp;quot;Существующие реализации&amp;quot; ). Таким образом, удостоверенными экспериментальными данными являются только значения, полученные для случая 1 процесса. Значения для случаев 2 и 4 процессов являются ОЦЕНОЧНЫМИ и выводятся из результатов работы модифицированной версии алгоритма, исследуемой в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18253</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=18253"/>
		<updated>2016-11-18T19:09:28Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью, но не приводится рабочая реализация.&lt;br /&gt;
&lt;br /&gt;
В силу вышескасновного основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла. Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи. Для исследования такой масштабируемости вширь использовалась референсная последовательная реализация алгоритма ( м. раздел &amp;quot;Существующие реализации&amp;quot; ). Таким образом, удостоверенными экспериментальными данными являются только значения, полученные для случая 1 процесса. Значения для случаев 2 и 4 процессов являются ОЦЕНОЧНЫМИ и выводятся из результатов работы модифицированной версии алгоритма, исследуемой в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17294</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17294"/>
		<updated>2016-11-15T14:44:46Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью.&lt;br /&gt;
&lt;br /&gt;
Основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ). Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Ruslanlazovskiy&amp;diff=17293</id>
		<title>Обсуждение участника:Ruslanlazovskiy</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Ruslanlazovskiy&amp;diff=17293"/>
		<updated>2016-11-15T14:44:00Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Правки - порция 2. */ новая тема&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:Ruslanlazovskiy/CHAMELEON]] ==&lt;br /&gt;
&lt;br /&gt;
1) все ссылки в статье не работают&lt;br /&gt;
&lt;br /&gt;
2) список литературы оформлен неправильно - см. как сделано в [[Разложение_Холецкого_(метод_квадратного_корня)]]&lt;br /&gt;
&lt;br /&gt;
3) для оформления (псевдо) кода следует использовать тег &amp;lt;nowiki&amp;gt;&amp;lt;source lang=&amp;quot;...&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Мои правки ==&lt;br /&gt;
&lt;br /&gt;
2) и 3) теперь сделаны как надо. В 1) не удалось поправить самую первую ссылку, ресурс с последовательной реализацией действительно умер.&lt;br /&gt;
&lt;br /&gt;
== Замечания к статье про Хамелеон (ещё порция) ==&lt;br /&gt;
&lt;br /&gt;
* Ссылки на авторов и список литературы - присоединяюсь к замечаниям. Список литературы действительно всего из одного наименования? [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* В разделе 1 пояснить, нужно ли заранее знать число кластеров. Это неясно и из описания входных и выходных данных, должно же оно быть хоть где-нибудь [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* Раздел 1.2. Когда вводим граф, желательно пояснить аргументы V и E в скобках. Аналогично с параметром m, который встречается впервые [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* Раздел 1.6. Стоит сделать логарифм красивей [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
== Правки - порция 2. ==&lt;br /&gt;
&lt;br /&gt;
* В список литературы добавлена статья с исследованием параллелизма. Остальные найденные статьи по Chameleon представляют собой кальку с оригинальной статьи ( первый пункт в списке ) в разделе описания алгоритма + описание задачи, для которой применялся алгоритм, для примера добавил одну из таких статей.&lt;br /&gt;
* Сделано&lt;br /&gt;
* Сделано&lt;br /&gt;
* Поправил, добавил описание &amp;quot;предельного&amp;quot; случая.&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17292</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17292"/>
		<updated>2016-11-15T14:43:38Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью.&lt;br /&gt;
&lt;br /&gt;
Основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ). Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17288</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17288"/>
		<updated>2016-11-15T14:35:00Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью.&lt;br /&gt;
&lt;br /&gt;
Основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ). Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17283</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17283"/>
		<updated>2016-11-15T14:28:46Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью.&lt;br /&gt;
&lt;br /&gt;
Основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ). Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17282</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17282"/>
		<updated>2016-11-15T14:28:11Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью.&lt;br /&gt;
&lt;br /&gt;
Основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ). Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией последовательной реализации алгоритма, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17281</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17281"/>
		<updated>2016-11-15T14:21:24Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью.&lt;br /&gt;
&lt;br /&gt;
Основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ). Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17277</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17277"/>
		<updated>2016-11-15T14:19:57Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью.&lt;br /&gt;
Основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ). Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17276</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17276"/>
		<updated>2016-11-15T14:19:00Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью.&lt;br /&gt;
Основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ). Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17269</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17269"/>
		<updated>2016-11-15T14:12:24Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью.&lt;br /&gt;
Основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ). Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17263</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17263"/>
		<updated>2016-11-15T13:59:40Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью.&lt;br /&gt;
Основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ). Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С последовательной реализацией алгоритма можно ознакомиться по адресу [http://us.codeforge.com/article/192925 Sequental]&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17262</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17262"/>
		<updated>2016-11-15T13:55:59Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью.&lt;br /&gt;
Основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ). Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17261</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17261"/>
		<updated>2016-11-15T13:52:46Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью. Поэтому основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ).&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17233</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17233"/>
		<updated>2016-11-15T12:15:48Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью. Поэтому основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ).&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17232</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17232"/>
		<updated>2016-11-15T12:11:42Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Общее описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью. Поэтому основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ).&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17231</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17231"/>
		<updated>2016-11-15T12:10:58Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью. Поэтому основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ).&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17230</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17230"/>
		<updated>2016-11-15T12:01:17Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью. Поэтому основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ).&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17229</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17229"/>
		<updated>2016-11-15T11:59:41Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью. Поэтому основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи.&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17228</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=17228"/>
		<updated>2016-11-15T11:55:20Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в () приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью.&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14747</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14747"/>
		<updated>2016-10-29T21:08:59Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Пока ничего нет.&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Ruslanlazovskiy&amp;diff=14746</id>
		<title>Обсуждение участника:Ruslanlazovskiy</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Ruslanlazovskiy&amp;diff=14746"/>
		<updated>2016-10-29T21:08:25Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Мои правки */ новая тема&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:Ruslanlazovskiy/CHAMELEON]] ==&lt;br /&gt;
&lt;br /&gt;
1) все ссылки в статье не работают&lt;br /&gt;
&lt;br /&gt;
2) список литературы оформлен неправильно - см. как сделано в [[Разложение_Холецкого_(метод_квадратного_корня)]]&lt;br /&gt;
&lt;br /&gt;
3) для оформления (псевдо) кода следует использовать тег &amp;lt;nowiki&amp;gt;&amp;lt;source lang=&amp;quot;...&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Мои правки ==&lt;br /&gt;
&lt;br /&gt;
2) и 3) теперь сделаны как надо. В 1) не удалось поправить самую первую ссылку, ресурс с последовательной реализацией действительно умер.&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14745</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14745"/>
		<updated>2016-10-29T21:05:38Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Пока ничего нет.&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14744</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14744"/>
		<updated>2016-10-29T20:47:44Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Пока ничего нет.&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из таких референсных реализаций можно ознакомиться по ссылке [http://www.codeforge.com/article/192925 референская реализация].&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14743</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14743"/>
		<updated>2016-10-29T20:45:18Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Пока ничего нет.&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из таких референсных реализаций можно ознакомиться по ссылке [http://www.codeforge.com/article/192925 референская реализация].&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview|] , hMETIS [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview|] и RANN [https://cran.r-project.org/web/packages/RANN/index.html|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14742</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14742"/>
		<updated>2016-10-29T20:42:01Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Пока ничего нет.&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из таких референсных реализаций можно ознакомиться по ссылке [http://www.codeforge.com/article/192925 референская реализация].&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview|] , hMETIS [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview|] и RANN [https://cran.r-project.org/web/packages/RANN/index.html|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14741</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14741"/>
		<updated>2016-10-29T20:40:33Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Общее описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Пока ничего нет.&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из таких референсных реализаций можно ознакомиться по ссылке [http://www.codeforge.com/article/192925|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview|] , hMETIS [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview|] и RANN [https://cran.r-project.org/web/packages/RANN/index.html|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14740</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14740"/>
		<updated>2016-10-29T20:39:44Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Литература */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье &amp;lt;ref&amp;gt;Commandant Benoit, Note sur une méthode de résolution des équations normales provenant de l&#039;application de la méthode des moindres carrés à un système d&#039;équations linéaires en nombre inférieur à celui des inconnues (Procédé du Commandant Cholesky), Bulletin Géodésique 2 (1924), 67-77.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Пока ничего нет.&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из таких референсных реализаций можно ознакомиться по ссылке [http://www.codeforge.com/article/192925|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview|] , hMETIS [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview|] и RANN [https://cran.r-project.org/web/packages/RANN/index.html|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14739</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14739"/>
		<updated>2016-10-29T20:39:28Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Свойства и структура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье &amp;lt;ref&amp;gt;Commandant Benoit, Note sur une méthode de résolution des équations normales provenant de l&#039;application de la méthode des moindres carrés à un système d&#039;équations linéaires en nombre inférieur à celui des inconnues (Procédé du Commandant Cholesky), Bulletin Géodésique 2 (1924), 67-77.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Пока ничего нет.&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из таких референсных реализаций можно ознакомиться по ссылке [http://www.codeforge.com/article/192925|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview|] , hMETIS [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview|] и RANN [https://cran.r-project.org/web/packages/RANN/index.html|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14303</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=14303"/>
		<updated>2016-10-27T23:17:07Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Схема реализации последовательного алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Пока ничего нет.&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из таких референсных реализаций можно ознакомиться по ссылке [http://www.codeforge.com/article/192925|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview|] , hMETIS [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview|] и RANN [https://cran.r-project.org/web/packages/RANN/index.html|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=12262</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=12262"/>
		<updated>2016-10-15T22:29:55Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Пока ничего нет.&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из таких референсных реализаций можно ознакомиться по ссылке [http://www.codeforge.com/article/192925|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview|] , hMETIS [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview|] и RANN [https://cran.r-project.org/web/packages/RANN/index.html|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=9065</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=9065"/>
		<updated>2016-10-15T10:36:16Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Пока ничего нет.&lt;br /&gt;
&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из таких референсных реализаций можно ознакомиться по ссылке [http://www.codeforge.com/article/192925|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview|] , hMETIS [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview|] и RANN [https://cran.r-project.org/web/packages/RANN/index.html|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|].&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=8831</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=8831"/>
		<updated>2016-10-15T09:24:57Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 1-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Пока ничего нет.&lt;br /&gt;
&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из таких референсных реализаций можно ознакомиться по ссылке [http://www.codeforge.com/article/192925|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview|] , hMETIS [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview|] и RANN [https://cran.r-project.org/web/packages/RANN/index.html|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|].&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=8828</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=8828"/>
		<updated>2016-10-15T09:23:44Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии их анализа. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 1-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Пока ничего нет.&lt;br /&gt;
&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из таких референсных реализаций можно ознакомиться по ссылке [http://www.codeforge.com/article/192925|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview|] , hMETIS [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview|] и RANN [https://cran.r-project.org/web/packages/RANN/index.html|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|].&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=8818</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=8818"/>
		<updated>2016-10-15T09:19:26Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии их анализа. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;p - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 1-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Пока ничего нет.&lt;br /&gt;
&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из таких референсных реализаций можно ознакомиться по ссылке [http://www.codeforge.com/article/192925|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview|] , hMETIS [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview|] и RANN [https://cran.r-project.org/web/packages/RANN/index.html|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|].&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=8586</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy/CHAMELEON&amp;diff=8586"/>
		<updated>2016-10-15T00:48:28Z</updated>

		<summary type="html">&lt;p&gt;Ruslanlazovskiy: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * p&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ).&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии их анализа. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; кластера, к которому они принадлежат. После завершения алгоритма возможно перенумеровать кластеры. В любом случае на выходе будет иметься &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; значений, так как число объектов в процессе работы алгоритма не изменялось.&lt;br /&gt;
&lt;br /&gt;
===Вычислительное ядро алгоритма===&lt;br /&gt;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;. Однако эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов, что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Итоговая оценка составляет &amp;lt;math&amp;gt;O(n*n + n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;p - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 1-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Пока ничего нет.&lt;br /&gt;
&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из таких референсных реализаций можно ознакомиться по ссылке [http://www.codeforge.com/article/192925|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview|] , hMETIS [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview|] и RANN [https://cran.r-project.org/web/packages/RANN/index.html|].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|].&lt;/div&gt;</summary>
		<author><name>Ruslanlazovskiy</name></author>
	</entry>
</feed>