2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 Алгоритм Хошена-Копельмана и маркировка кластеров в целом
Сообщение09.11.2015, 01:29 
Заслуженный участник


29/12/14
504
Доброго времени суток, уважаемые форумчане.

Вот уже довольно долго пытаюсь побороть такую проблему - максимально быстро находить кластеры для заданной системы хаотично расположенных сфер (причём система полидисперсна). Впрочем, вид системы особой роли-то не играет. Собственно, есть ряд проблем и связанных с ними вопросов.

На данный момент я использую, по сути, классический алгоритм Хошена-Копельмана, суть которого сводится к следующему:

1. Изначально всем элементам ставится значение кластерной метки "0". Задаём $k = 0$
2. Затем мы начинаем методично пробегать по всем элементам. Для каждого элемента просматриваем его ближайшее окружение (потенциальные соседи могут находиться только в пределах $2R_\max$).
3. Если два элемента соединены и не принадлежат ни одному из кластеров, они образуют новый кластер с меткой k. После этого это увеличиваем k на единицу.
4. Если один из элементов уже принадлежит какому-либо кластеру, а другой - нет, то элемент без кластера присоединяется к кластеру другого.
5. Если же оба элемента принадлежат каким-либо кластерам, то происходит объединение кластеров.

В общем, алгоритм прост, как апельсин. При этом, что хорошо, для этого алгоритма нет необходимости изначально выделять память для кластеров, что критично, так как априорно неизвестно, сколько кластеров будет вообще и каких они будут размеров (хотя бы максимально).

А теперь о том, что плохо. Алгоритм работает медленно (в смысле недостаточно для меня быстро). Для ускорения процесса по совету, взятому отсюда, перед перемаркировкой я начал проверять размеры систем, перемаркировка которых требуется, чтобы потом изменять поменьше значений. Практика показывает, что это ни черта не помогает, поскольку основной вклад по времени в эту операцию входит именно опознавание элементов с определённой меткой (в fortran за это отвечает, например, оператор where(...)), которая от числа опознаваемых элементов особо не зависит (по итогу даже медленнее выходит из-за проверки). В MATLAB я пытался пойти немного по-другому: сделать сначала массив ячеек под массивы (поскольку массив одномерный, то памяти должно заведомо хватать), а потом туда "засовывать" элементы. Слияние двух кластеров тогда есть просто объединение двух ячеек, что гораздо быстрее. Однако MATLAB в целом довольно медленная штука, поэтому всё равно не хватает полученной скорости.

Опять же, например, здесь и здесь предлагается для ускорения работать по "древовидной" схеме. То есть вместо маркировки кластерной меткой использовать систему "родитель(родитель(...(корень)))". Но вот как это реализуется и как потом это "распутывается" (чтобы в итоге иметь на руках именно что кластеры), я не совсем понимаю. Был бы очень благодарен, если бы кто-нибудь всё это дело "разжевал".

Лишний раз обращу внимание, что меня интересует именно что полное описание системы. То есть интересует, какому кластеру каждый элемент принадлежит. В принципе, достаточно было бы и знания того, какие элементы принадлежат перколяционному кластеру, но первое всё же лучше.

Короче говоря, хотелось бы узнать, как реализуется "древовидный" метод, а также возможность его распараллеливания, послушать какие-нибудь общие рекомендации по вопросу.

P.S. Кроме того, хотелось бы узнать мнение на счёт следующего вопроса. Предположим, у нас есть перколяционный кластер хаотично расположенных сфер. И пусть мы убираем одну из сфер. Пересматривать после этого весь кластер по новой, чтобы понять, "порвался" ли кластер большого желания нет. С другой стороны, как я понимаю, рассмотрения ближайшего окружения не хватит для однозначного ответа на вопрос. Да и вообще любого окружения не хватит в общем случае. В принципе, понятно, что при этом можно, исходя из рассмотрения окружения некоторого порядка (скажем, ближайшие соседи и их соседи; или разбить всё пространство на кубики размером $2R_\max$ и в качестве окружения брать 2 ближайших клетки) выдвинуть некоторую гипотезу. Можно ли при этом как-нибудь оценить в среднем, насколько часто мы будем при этом ошибаться? Если кто-нибудь сможет подсказать по этому поводу или скинь статью, где подобный вопрос обсуждается, то я был бы безмерно благодарен.

 Профиль  
                  
 
 Re: Алгоритм Хошена-Копельмана и маркировка кластеров в целом
Сообщение09.11.2015, 18:37 


11/12/14
893
По ссылкам требуется регистрация.
Есть подозрение, что под "древовидной схемой" имеется ввиду space partition (типа BSP/Quadtree/Octree) для решения задачи быстрого поиска соседних узлов.
Не знаю как на матлабе, а в чём нибудь типа C++/Java, если бы производительность упиралась бы плотно именно в соединение кластеров, то навскидку я бы попробовал сделал сферы элентами интрузивного циклического двунаправленного списка. Изначально каждый элемент замкнут на себя. Первый проход для ближайших делает операцию link за O(1). Второй проход уже размечает образовавшиеся циклы любым нужным образом.

 Профиль  
                  
 
 Re: Алгоритм Хошена-Копельмана и маркировка кластеров в целом
Сообщение11.11.2015, 22:46 
Заслуженный участник


29/12/14
504
Чтобы темы не плодить, напишу здесь опять. В общем, более-менее разобрался, что там за "древовидная" схема (по моей терминологии). Суть проста (вдруг кому нужно когда-нибудь будет):

1. Формируем массив элементов, с которыми работать будем потом. Ну или делаем это на ходу, если возможность есть.
2. "Бросаем" элементы по одному и выполняем проверку:
а) если текущий элемент ни с кем не пересекается, то он объявляется корнем кластера;
б) если текущий элемент пересекается с корнем кластера, то он начинает на него ссылаться;
в) если текущий элемент пересекается только с элементом (элементами), ссылающимся (ссылающимися) на корень i, то текущий элемент начинает ссылаться на корень i;
г) если же текущий элемент пересекается с хотя бы двумя элементами, ссылающимися на разные корни, то текущий элемент начинает ссылаться на корень большего "подкластера", а корень меньшего "подкластера" начинает ссылаться на корень большего.

Таким вот фокусом мы избавляемся от невероятно длительной процедуры перемаркировки. Для того чтобы потом получить кластеры, нужно просто прыгать от корня к корню и собирать все элементы, на них ссылающиеся.

Распараллелить это дело тоже довольно нетрудно, как мне представляется. Разбить всю область на K частей, работать в каждой из них обособленно, а потом пройтись по граничным линиям (толщиной $2R_\max$) для сшивки всего этого дела.

По поводу второй части вопроса (по разрыву кластера) тоже появились мысли и вопросы. Есть идея представить кластер в виде графа. Тут заранее прошу прощения за возможные ошибки в терминологии, так как тема мне незнакомая. В общем, в процессе работы отслеживать ещё, кто с кем пересекается конкретно, и составить (или в процессе составлять) список смежности. Тогда задача о том, разорвёт ли убирание одной из сфер наш кластер, сводится к вопросу является ли данный элемент (сфера то есть) точкой сочленения (шарниром) нашего графа. То есть варианта два:

а) Найти все точки сочленения для изначального графа, а потом просто просматривать, является ли вершина, которую мы выбрасываем, точкой сочленения.
б) Каждый раз проверять, является ли выбрасываемая вершина точкой сочленения.

Я пытался найти какие-нибудь пакеты или команды для MATLAB (более предпочтительный для меня вариант) или Fortran, которые это реализуют. Для MATLAB я нашёл вот это. Эта штука реализует пункт (а), но, к сожалению, там граф нужно представлять в виде матрицы смежности, а не списка смежности. А у меня на это дело памяти не хватит ну никак вообще.

В общем, если у кого-нибудь есть, кто-нибудь знает, где взять, продукт для решения описанной выше проблемы, я был бы очень признателен. Ещё больше было бы хорошо (просто идеально, я бы сказал) иметь готовую штуку, работающую с графами, представленными в виде списка смежности, которая возвращала бы два подграфа, на который разбивает данная точка сочленения (если она таковой является).

aa_dav
К большому сожалению, я в C++/Java ни бе ни ме вообще. Да и в целом программирую достаточно посредственно, а то, что вы написали, звучит довольно сложно. :-)

 Профиль  
                  
 
 Re: Алгоритм Хошена-Копельмана и маркировка кластеров в целом
Сообщение23.03.2016, 19:06 


23/03/16
1
День добрый, уважаемый коллега :)
Я так и не понял, вы решили проблему скорости?
которая, как я понял, и побудила вас искать замену алгоритму Хошена-Копельмана...

 Профиль  
                  
 
 Re: Алгоритм Хошена-Копельмана и маркировка кластеров в целом
Сообщение24.03.2016, 13:16 
Заслуженный участник


26/05/14
981
disjoint set сделан специально для быстрого объединения неперсекающихся множеств: https://ru.wikipedia.org/wiki/%D0%A1%D0 ... 1%82%D0%B2

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 5 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group