Recherche d'ensembles «d'empreintes digitales»

11

Disons que nous avons 10 personnes, chacune avec une liste de livres préférés. Pour une personne donnée X, je voudrais trouver un sous-ensemble spécial de livres de X aimé seulement par X, c'est-à-dire qu'il n'y a aucune autre personne qui aime tous les livres du sous-ensemble spécial de X. Je pense que ce sous-ensemble spécial est une "empreinte" unique pour X.

J'apprécierais des suggestions sur une approche pour trouver de tels ensembles. (Bien que cela ressemble à un problème de devoirs, il est lié à un problème dans ma recherche en biologie que j'essaie de résoudre.)

edron79
la source
1
La gamme / le nombre de livres possibles est-il limité? Cette identification par "empreinte digitale" peut-elle être effectuée à la volée - au fur et à mesure que chaque livre est ajouté à la liste préférée d'une personne - ou vous donne-t-on au préalable l'ensemble des listes?
Paresh

Réponses:

6

Je suppose que vous voulez que l'empreinte digitale soit aussi petite que possible. Ensuite, c'est le problème de l' ensemble de frappe: pour chaque personne, faites une liste de tous les livres aimés par X mais pas par cette personne. Ensuite, l'objectif est de sélectionner au moins un livre dans chaque liste. Le problème est NP-difficile, vous ne pouvez donc pas vous attendre à trouver un algorithme qui le résoudra toujours de manière optimale en temps polynomial. L'algorithme gourmand a une mauvaise limite théorique dans le pire des cas, mais fonctionne souvent assez décent dans la pratique. Si vous souhaitez le résoudre de manière optimale, un solveur de programmation linéaire en nombre entier devrait être capable de résoudre des instances de 1 000 ou peut-être 10 000 livres. Si vous donnez plus de détails sur la taille et la structure de vos instances, nous pourrions suggérer d'autres approches.

Falk Hüffner
la source
+1 Bien sûr, vous avez raison! :) Il n'est pas difficile de construire des exemples où mon algorithme gourmand manque. Oops.
Patrick87
OP: Merci beaucoup pour les commentaires - la solution d'algorithme gourmande originale m'a fait avancer dans la bonne direction. L'espace total sur lequel je travaille concerne des centaines d'individus et des milliers de "livres" - si cela est possible avec l'approche de programmation entière, j'aimerais en savoir plus.
Merbs
4

Ce n'est pas un algorithme particulièrement intelligent, mais c'est un polynôme, et je pense que cela devrait fonctionner. Prenez n'importe quel ensemble. Pour chaque élément de cet ensemble, comptez le nombre d'ensembles restants qui ne le contiennent pas et rappelez-vous quels ensembles le contiennent. Choisissez l'élément avec le nombre le plus élevé et refaites le nombre des éléments restants, en ignorant les ensembles qui n'ont pas l'élément que vous venez de choisir. Continuez jusqu'à ce que tous les ensembles restants aient été éliminés de la considération.

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}

Je n'y ai pas beaucoup réfléchi, mais intuitivement, il semble que cela devrait fonctionner. L'idée est de prendre avidement comme prochain élément de l'ensemble d'empreintes digitales l'élément qui couvre les ensembles les plus découverts.

Patrick87
la source
Voir la réponse de Falk Huffner, où il identifie correctement votre problème comme le problème NP-Hard Hitting Set. Il semble que ma réponse donne l'approximation gourmande habituelle du problème, ce qui n'est pas mauvais, mais n'est pas optimal non plus.
Patrick87
0

MM[book]fingerprint books

Permettez-moi de démontrer sur le code 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

Le code imprime:

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

Ceci est l'OP (ne s'est pas enregistré lors de la soumission initiale, donc maintenant je ne peux pas commenter correctement). Merci beaucoup pour vos commentaires - la solution d'algorithme gourmande d'origine m'a fait avancer dans la bonne direction. L'espace total sur lequel je travaille concerne des centaines d'individus et des milliers de "livres" - si cela est possible avec l'approche de programmation entière, j'aimerais en savoir plus.

edron79
la source
J'ai placé votre commentaire de telle sorte que Falk en soit informé.
Merbs