Подтвердить что ты не робот

Эффективное пересечение множества - решить, будет ли пересечение больше k

Я столкнулся с проблемой, когда мне приходится вычислять пересечения между всеми парами в наборе множеств. Ни один из наборов не меньше небольшой константы k, и меня интересует только то, имеют ли два набора пересечение больше, чем k-1, или нет. Мне не нужны фактические пересечения или точный размер, только если он больше, чем k-1 или нет. Есть ли какой-то умный трюк предварительной обработки или опрятный алгоритм пересечения, который я мог бы использовать для ускорения работы?

Дополнительная информация, которая может быть полезна для ответа на вопрос:

  • Наборы представляют максимальные клики в большом, неориентированном, разреженном графике. Количество наборов может быть порядка десятков тысяч или более, но большинство наборов, вероятно, будут небольшими.
  • Наборы уже отсортированы члены каждого набора в порядке возрастания. Эффективно они отсортированы списки - я получаю их таким образом из базовой библиотеки для максимального поиска клики.
  • Ничего не известно о распределении элементов в наборах (т.е. находятся ли они в узких группах или нет).
  • Большинство установленных пересечений, вероятно, будут пустыми, поэтому идеальным решением будет умная структура данных, которая поможет мне сократить количество заданных пересечений, которые я должен выполнить.
4b9b3361

Ответ 1

Рассмотрим отображение со всеми наборами размера k в качестве ключей и соответствующими значениями списков всех наборов из вашей коллекции, которые содержат ключ в качестве подмножества. Учитывая это сопоставление, вам не нужно выполнять какие-либо тесты пересечения: для каждого ключа все пары наборов из списка будут иметь пересечение с размером не менее k. Этот подход может производить одни и те же пары множеств более одного раза, поэтому их необходимо будет проверить.

Отображение достаточно просто для вычисления. Для каждого набора в коллекции вычислите все подмножества size-k и добавьте исходный набор в список для этого набора ключей. Но разве это быстрее? В общем, нет. Производительность этого подхода будет зависеть от распределения размеров наборов в коллекции и значения k. С d различными элементами в наборах вы могли бы выбрать до k ключей, которые могут быть очень большими.

Однако основная идея позволяет сократить количество пересечений. Вместо использования наборов размера k используйте меньшие фиксированные размеры q в качестве ключей. Значения снова представляют списки всех наборов, у которых есть ключ в качестве подмножества. Теперь проверьте каждую пару наборов из списка для пересечения. Таким образом, при q = 1 вы проверяете только те пары множеств, у которых есть хотя бы один общий элемент, при q = 2 вы проверяете только те пары множеств, которые имеют как минимум два элемента, и так далее. Оптимальное значение для q будет зависеть от распределения размеров наборов, я думаю.

Для рассматриваемых множеств хорошим выбором может быть q = 2. Ключи - это только края графа, дающие предсказуемый размер отображения. Поскольку ожидается, что большинство множеств будут непересекающимися, q = 2 должно устранить множество сравнений без особых дополнительных издержек.

Ответ 2

Одна возможная оптимизация, которая более эффективна, чем меньше диапазон значений, содержащихся в каждом наборе:

  • Создайте список всех наборов, отсортированных по их k-му наибольшему элементу (это легко найти, поскольку вы уже имеете каждый набор со своими элементами в порядке). Вызовите этот список L.
  • Для любых двух множеств A и B их пересечение не может содержать в себе k элементов, если k-й наибольший элемент в меньше наименьшего элемента в B.
  • Итак, для каждого набора, в свою очередь, вычислите его пересечение только с наборами в соответствующей части L.

Вы можете использовать тот же самый факт, чтобы выходить раньше из вычисления пересечения любых двух наборов - если осталось только n-1 элементов для сравнения в одном из множеств, а пересечение пока содержит не более kn элементов, то стоп. Вышеприведенная процедура - это просто это правило, применяемое ко всем наборам в L одновременно, с n = k, в точке, где мы смотрим на наименьший элемент множества B и k-й наибольший элемент A.

Ответ 3

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

Сначала я предполагаю, что у вас есть какая-то очередность приоритета (если нет, то перемещение вашей собственной кучи довольно просто). И быстрый поиск ключа/значения (btree, hash, что угодно).

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

# Initial setup
sets = array of all sets
intersection_count = key/value lookup with keys = (set_pos, set_pos) and values are counts.
p_queue = priority queue whose elements are (set[0], 0, set_pos), organized by set[0]

# helper function
def process_intersections(current_sets):
    for all pairs of current_sets:
        if pair in intersection_count:
            intersection_count[pair] += 1
        else:
            intersection_count[pair] = 1

# Find all intersections
current_sets = []
last_element = first element of first thing in p_queue
while p_queue is not empty:
    (element, ind, set_pos) = get top element from p_queue
    if element != last_element:
        process_intersections(current_sets)
        last_element = element
        current_sets = []
    current_sets.append(set_pos)
    ind += 1
    if ind < len(sets[set_pos]):
        add (sets[set_pos][ind], ind, set_pos) to p_queue
# Don't forget the last one!
process_intersections(current_sets)

final answer = []
for (pair, count) in intersection_count.iteritems():
    if k-1 < count:
        final_answer.append(pair)

Время работы будет O(sum(sizes of sets) * log(number of sets) + count(times a point is in a pair of sets). В частности, обратите внимание, что если два набора не имеют пересечения, вы никогда не пытаетесь пересечь их.

Ответ 4

Что делать, если вы использовали предсказуемое подмножество. Предварительно сортируйте, но используйте пересечение подмножества в качестве порогового условия. Если пересечение подмножествa > n%, то завершите пересечение, иначе откажитесь. n затем становится обратным вашему уровню комфорта с перспективой ложного позитива.

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

Это действительно начинает рассматривать проблему как NP-Complete.