Finden von "Fingerabdruck" -Sätzen


11

Nehmen wir an, wir haben 10 Leute mit jeweils einer Liste von Lieblingsbüchern. Für eine bestimmte Person X möchte ich eine spezielle Untergruppe von Xs Büchern finden, die nur von X gemocht werden, dh es gibt keine andere Person, die alle Bücher in Xs spezieller Untergruppe mag. Ich betrachte diese spezielle Untergruppe als einen einzigartigen "Fingerabdruck" für X.

Ich würde mich über Vorschläge für einen Ansatz zur Suche nach solchen Sets freuen. (Während dies wie ein Hausaufgabenproblem liest, hängt es mit einem Problem in meiner Biologieforschung zusammen, das ich zu lösen versuche.)


1
Ist der Bereich / die Anzahl der möglichen Bücher endlich? Kann diese "Fingerabdruck" -Identifizierung im Handumdrehen durchgeführt werden - da jedes Buch zur Favoritenliste einer Person hinzugefügt wird - oder erhalten Sie die Listen zuvor?
Paresh

Antworten:


6

Ich gehe davon aus, dass der Fingerabdruck so klein wie möglich sein soll. Dann ist dies das Hitting Set- Problem: Erstellen Sie für jede Person eine Liste aller Bücher, die X gefallen, aber nicht dieser Person. Ziel ist es dann, mindestens ein Buch aus jeder Liste auszuwählen. Das Problem ist NP-schwer, daher können Sie nicht erwarten, einen Algorithmus zu finden, der es in der Polynomzeit immer optimal löst. Der gierige Algorithmus hat eine schlechte theoretische Worst-Case-Grenze, funktioniert aber in der Praxis oft recht anständig. Wenn Sie es optimal lösen möchten, sollte ein Integer Linear Programming Solver in der Lage sein, Instanzen von bis zu 1000 oder vielleicht 10000 Büchern zu lösen. Wenn Sie mehr Details zur Größe und Struktur Ihrer Instanzen angeben, können wir andere Ansätze vorschlagen.


+1 Natürlich hast du recht! :) Es ist nicht schwer, Beispiele zu konstruieren, bei denen mein gieriger Algorithmus fehlt. Hoppla.
Patrick87

OP: Vielen Dank für das Feedback - die ursprüngliche gierige Algorithmuslösung hat mich in die richtige Richtung gebracht. Der gesamte Speicherplatz, an dem ich arbeite, betrifft Hunderte von Einzelpersonen und Tausende von "Büchern". Wenn dies mit dem ganzzahligen Programmieransatz möglich ist, würde ich gerne mehr darüber erfahren.
Merbs

4

Dies ist kein besonders cleverer Algorithmus, aber er ist polynomisch und ich denke, er sollte funktionieren. Nimm ein beliebiges Set. Zählen Sie für jedes Element in dieser Menge die Anzahl der verbleibenden Mengen, die es nicht enthalten, und merken Sie sich, welche Mengen es enthalten. Wählen Sie das Element mit der höchsten Anzahl aus und wiederholen Sie die Anzahl der verbleibenden Elemente. Ignorieren Sie dabei die Mengen, denen das gerade ausgewählte Element fehlt. Fahren Sie fort, bis alle verbleibenden Sätze nicht mehr berücksichtigt wurden.

A={1,2,3}B={2,3,4}}C={2,4,6}}D.={1,3,5}}c1=2c2=1c3=1B.C.c2=1c3=0D.{1,2}}{3,4}}{6}}{5}}

Ich habe nicht viel darüber nachgedacht, aber intuitiv scheint es, als sollte es funktionieren. Die Idee ist, gierig als nächstes Element des Fingerabdrucksatzes den Gegenstand zu nehmen, der die am meisten ungedeckten Sätze abdeckt.


Siehe Falk Huffners Antwort, in der er Ihr Problem korrekt als NP-Hard Hitting Set-Problem identifiziert. Es scheint, dass meine Antwort die übliche gierige Annäherung für das Problem gibt, was nicht schlecht, aber auch nicht optimal ist.
Patrick87

0

MM[book]]fingerprint books

Lassen Sie mich am Python-Code demonstrieren:

%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

Der Code druckt:

{'Frank': ['X'], 'Matt': [], 'Andy': ['G'], 'Joe': ['B'], 'Anna': ['Y', 'Z']}

0

Dies ist das OP (wurde bei der ersten Einreichung nicht registriert, daher kann ich jetzt nicht richtig kommentieren). Vielen Dank für das Feedback - die ursprüngliche gierige Algorithmuslösung hat mich in die richtige Richtung gebracht. Der gesamte Speicherplatz, an dem ich arbeite, betrifft Hunderte von Einzelpersonen und Tausende von "Büchern". Wenn dies mit dem ganzzahligen Programmieransatz möglich ist, würde ich gerne mehr darüber erfahren.


Ich habe Ihren Kommentar so platziert, dass Falk benachrichtigt wird.
Merbs
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.