Пошук наборів "відбитків пальців"


11

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

Я вдячний для пропозицій щодо підходу до пошуку таких наборів. (Хоча це і є як проблема домашнього завдання, вона пов'язана з проблемою в моїх дослідженнях біології, яку я намагаюся вирішити.)


1
Чи обмежений діапазон / кількість можливих книг? Чи можна цю ідентифікацію "відбитків пальців" здійснити на ходу - оскільки кожна книга додається до списку улюблених людей - або вам заздалегідь надано набір списків?
Пареш

Відповіді:


6

Я припускаю, що ви хочете, щоб відбиток пальців був якомога меншим. Тоді це проблема набору ударів : Для кожної людини складіть список усіх книг, які подобаються X, але не цій людині. Тоді мета - вибрати принаймні одну книгу з кожного списку. Проблема непроста, тому ви не можете розраховувати знайти алгоритм, який завжди оптимально вирішує його в поліноміальний час. Жадібний алгоритм має поганий теоретичний зріз, але на практиці він часто працює цілком пристойно. Якщо ви хочете вирішити це оптимально, розв'язувач лінійного програмування Integer повинен мати можливість вирішувати екземпляри до 1000 або, можливо, 10000 книг. Якщо ви дасте більше деталей щодо розміру та структури ваших примірників, ми можемо запропонувати інші підходи.


+1 Звичайно, ти маєш рацію! :) Не важко побудувати приклади, коли мій жадібний алгоритм не вистачає. На жаль
Patrick87

ОП: Велике спасибі за відгуки - оригінальне жадне рішення алгоритму змусило мене рухатись у правильному напрямку. Загальний простір, над яким я працюю, стосується 100 осіб та 1000 «книг» - якщо це можливо при цілому підході до програмування, я хотів би дізнатися більше про це.
Мербс

4

Це не особливо розумний алгоритм, але це многочлен, і я думаю, він повинен працювати. Візьміть будь-який набір. Для кожного елемента цього набору підраховуйте кількість решти наборів, які не містять його, і пам’ятайте, які набори містять його. Виберіть елемент з найбільшою кількістю та повторіть підрахунок для решти елементів, ігноруючи набори, у яких не вистачає вибраного вами елемента. Продовжуйте, поки всі інші набори не будуть усунені з розгляду.

Приклад: нехай , , і . Тоді маємо відліки , і . Вибираємо 1, виключаючи множини і які не містили його; повторюючи підрахунки, маємо і . Ми вибираємо 2 як наступний елемент і видаляємо з розгляду. Зараз ми закінчили, і наш набір «відбитків» - . EDIT: для завершення прикладу, ви повинні отримати інші набори відбитків пальців як ,A={1,2,3}B={2,3,4}C={2,4,6}D={1,3,5}c1=2c2=1c3=1BCc2=1c3=0D{ 3 , 4 } { 6 } { 5 }{1,2}{3,4}{6} і .{5}

Я не задумувався над цим багато, але інтуїтивно, схоже, це має спрацювати. Ідея полягає в тому, щоб жадібно взяти в якості наступного елемента набір відбитків елемент, який охоплює найбільш непокриті набори.


Дивіться відповідь Фалька Хаффнера, де він правильно ідентифікує вашу проблему як проблема NP-Hard Hitting Set. Здається, моя відповідь дає звичайне жадібне наближення до проблеми, що непогано, але й не оптимально.
Patrick87

0

Можливо, я питання не зрозумів правильно (на основі дещо складних відповідей), але тут іде. Ви просто переглядаєте всіх людей і всі їхні книги, які їм подобаються. Ви створюєте структуру даних (переважно Hash Map ), де ключовою є книга, а значення - список осіб, яким ця книга подобається. Ви заповнюєте цю структуру даних інтуїтивно зрозумілим способом (для кожної людини / пари книг ви додаєте особу до списку ). Потім ви переходите до клавіш карт і там, де довжина списку дорівнює одиниці, тоді ця книга є однією з конкретних осіб.М [ б о о к ]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']}

0

Це ОП (не було зареєстровано при первинному поданні, тому зараз я не можу коментувати належним чином). Дуже дякую за відгук - оригінальне жадне рішення алгоритму змусило мене рухатись у правильному напрямку. Загальний простір, над яким я працюю, стосується 100 осіб та 1000 «книг» - якщо це можливо при цілому підході до програмування, я хотів би дізнатися більше про це.


Я розмістив ваш коментар таким, що про Falk буде повідомлено.
Мербс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.