Поиск наборов «отпечатков пальцев»

11

Скажем, у нас есть 10 людей, каждый из которых со списком любимых книг. Для данного лица X, я хотел бы найти особое подмножество книг иксов понравившихся только X, т.е. нет другого человека, который любит все книги в специальном подмножестве Х. Я думаю, что этого специального подмножества в качестве уникального «отпечатка пальца» для X.

Буду признателен за предложения о подходе для поиска таких наборов. (Хотя это выглядит как проблема с домашней работой, это связано с проблемой в моем исследовании биологии, которую я пытаюсь решить.)

edron79
источник
1
Является ли диапазон / количество возможных книг конечным? Может ли эта идентификация «отпечатка пальца» быть сделана на лету - поскольку каждая книга добавлена ​​в список избранных какого-то человека - или вам заранее дали набор списков?
Пареш

Ответы:

6

Я предполагаю, что вы хотите, чтобы отпечаток был как можно меньше. Тогда это проблема набора ударов : для каждого человека составьте список всех книг, которые понравились Х, но не этому человеку. Затем цель состоит в том, чтобы выбрать хотя бы одну книгу из каждого списка. Проблема NP-сложна, поэтому вы не можете ожидать найти алгоритм, который всегда решает ее оптимально за полиномиальное время. Жадный алгоритм имеет плохую теоретическую оценку для наихудшего случая, но на практике часто работает вполне прилично. Если вы хотите решить ее оптимально, решатель целочисленного линейного программирования должен уметь обрабатывать до 1000 или, возможно, 10000 книг. Если вы предоставите более подробную информацию о размере и структуре ваших экземпляров, мы могли бы предложить другие подходы.

Фальк Хюффнер
источник
+1 Конечно ты прав! :) Нетрудно построить примеры, в которых мой жадный алгоритм отсутствует. К сожалению.
Patrick87
ОП: Огромное спасибо за отзыв - оригинальное жадное алгоритмическое решение заставило меня двигаться в правильном направлении. Общее пространство, над которым я работаю, касается сотен человек и тысяч «книг» - если это возможно с помощью целочисленного программирования, я хотел бы услышать больше об этом.
Merbs
4

Это не очень умный алгоритм, но он полиномиальный, и я думаю, что он должен работать. Возьми любой комплект. Для каждого элемента в этом наборе подсчитайте количество оставшихся наборов, которые его не содержат, и запомните, какие наборы содержат его. Выберите элемент с наибольшим количеством и восстановите счет для остальных элементов, игнорируя наборы, в которых отсутствует элемент, который вы только что выбрали. Продолжайте, пока все оставшиеся комплекты не будут исключены из рассмотрения.

Пример: пусть , , и . Тогда мы имеем счетчики , и . Мы выбираем 1, исключая множества и которые его не содержали; повторяя счет, мы имеем и . Мы выбираем 2 в качестве следующего элемента и удаляем из рассмотрения. Теперь мы закончили, и наш набор «отпечатков» - . РЕДАКТИРОВАТЬ: чтобы завершить пример, вы должны получить другие наборы отпечатков пальцев, как ,, 2 } { 3 , 4 } { 6 } { 5 }A={1,2,3}B={2,3,4}C={2,4,6}D={1,3,5}c1=2c2=1c3=1BCc2=1c3=0D{1,2}{3,4}{6} и .{5}

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

Patrick87
источник
См. Ответ Фалька Хаффнера, где он правильно идентифицирует вашу проблему как проблему NP-Hard Hitting Set. Похоже, мой ответ дает обычное жадное приближение для задачи, что неплохо, но и не оптимально.
Patrick87
0

Может быть, я не правильно понял вопрос (основываясь на несколько сложных ответах), но здесь идет речь. Вы просто просматриваете всех людей и все их книги, которые им нравятся. Вы создаете структуру данных (предпочтительно Hash Map ), где ключ - это книга, а значение - это список людей, которым нравится эта книга. Вы заполняете эту структуру данных интуитивно понятным способом (для каждой пары человек / книга вы добавляете человека в список ). Затем вы пролистываете ключи карты, и если длина списка равна единице, то эта книга относится к этой конкретной личности.M [ b o o k ]MM[book]fingerprint books

Позвольте мне продемонстрировать на коде Python:

%persons with books they like (it could also be a list or a set)
joe='ABCD'
andy='CDG'
frank='AHX'
anna='HAYZ'
matt='ACH'
%just transformation form variables, to names
names={joe:"Joe",andy:"Andy",frank:"Frank",anna:"Anna", matt:"Matt"}
%the map, from books to persons who like this book
books={}

%for each person
for p in names:
    %go through his liked books
    for book in p:
        %if book is already in the map, then append the person
        if book in books:
            books[book].append(names[p])
        else:
            %if not, then create a new book, and append the current person
            books[book]=[names[p]]

%create the fingerprint map (from person to books he likes)
fingerprint={}

%for each person create an empty list
for p in names:
    fingerprint[names[p]]=[]

%for each book in the map
for book in books:
    %if only one person likes this book, then it must be a part of his fingerprint
    if len(books[book])==1:
        fingerprint[books[book][0]].append(book)

print fingerprint

Код печатает:

{'Frank': ['X'], 'Matt': [], 'Andy': ['G'], 'Joe': ['B'], 'Anna': ['Y', 'Z']}
Nejc
источник
0

Это ОП (не регистрировался при первоначальном представлении, поэтому теперь я не могу правильно комментировать). Большое спасибо за обратную связь - оригинальное жадное алгоритмическое решение заставило меня двигаться в правильном направлении. Общее пространство, над которым я работаю, касается сотен человек и тысяч «книг» - если это возможно с помощью целочисленного программирования, я хотел бы услышать больше об этом.

edron79
источник
Я разместил ваш комментарий так, что Фальк будет уведомлен.
Merbs