Localizando conjuntos de "impressões digitais"


11

Digamos que temos 10 pessoas, cada uma com uma lista de livros favoritos. Para uma determinada pessoa X, gostaria de encontrar um subconjunto especial dos livros de X gostado apenas de X, ou seja, não há outra pessoa que goste de todos os livros no subconjunto especial de X. Penso neste subconjunto especial como uma "impressão digital" única para o X.

Gostaria muito de receber sugestões sobre uma abordagem para encontrar esses conjuntos. (Embora isso pareça um problema de lição de casa, está relacionado a um problema na minha pesquisa de biologia que estou tentando resolver.)


1
O intervalo / número de possíveis livros é finito? Essa identificação de "impressão digital" pode ser feita rapidamente - à medida que cada livro é adicionado à lista de favoritos de uma pessoa - ou você recebe o conjunto de listas antecipadamente?
Par12

Respostas:


6

Suponho que você queira que a impressão digital seja a menor possível. Então, este é o problema do Conjunto de ocorrências : Para cada pessoa, faça uma lista de todos os livros de que o X gostou, mas não dessa pessoa. Em seguida, o objetivo é selecionar pelo menos um livro de cada lista. O problema é difícil para o NP, então você não pode esperar encontrar um algoritmo que sempre o resolva de maneira ideal em tempo polinomial. O algoritmo ganancioso tem um péssimo limite teórico, mas geralmente funciona bastante decente na prática. Se você deseja resolvê-lo da melhor maneira possível, um solucionador de Programação Linear Inteira deve ser capaz de resolver instâncias de até 1000 ou talvez 10000 livros. Se você fornecer mais detalhes sobre o tamanho e a estrutura de suas instâncias, sugerimos outras abordagens.


+1 Claro que você está certo! :) Não é difícil construir exemplos em que meu algoritmo ganancioso erra. Opa
precisa saber é o seguinte

OP: Muito obrigado pelo feedback - a solução original do algoritmo guloso levou-me na direção certa. O espaço total em que estou trabalhando diz respeito a centenas de indivíduos e milhares de "livros" - se isso for possível com a abordagem de programação inteira, eu adoraria ouvir mais sobre isso.
Merbs

4

Este não é um algoritmo particularmente inteligente, mas é polinomial e acho que deve funcionar. Pegue qualquer conjunto. Para cada elemento deste conjunto, conte o número de conjuntos restantes que não o contêm e lembre-se de quais conjuntos o contêm. Escolha o elemento com a contagem mais alta e refaça as contagens dos elementos restantes, ignorando os conjuntos que não possuem o elemento que você acabou de escolher. Continue até que todos os conjuntos restantes tenham sido eliminados de consideração.

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}

Não pensei muito nisso, mas intuitivamente, parece que deveria funcionar. A idéia é tomar avidamente como o próximo elemento da impressão digital definir o item que cobre os conjuntos mais descobertos.


Veja a resposta de Falk Huffner, onde ele identifica corretamente o seu problema como o problema do NP-Hard Hitting Set. Parece que minha resposta fornece a aproximação gananciosa usual para o problema, o que não é ruim, mas também não é o ideal.
precisa saber é o seguinte

0

MM[book]fingerprint books

Deixe-me demonstrar no código 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

O código é impresso:

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

0

Este é o OP (não foi registrado no envio inicial, agora não posso comentar corretamente). Muito obrigado pelo feedback - a solução original do algoritmo guloso levou-me na direção certa. O espaço total em que estou trabalhando diz respeito a centenas de indivíduos e milhares de "livros" - se isso for possível com a abordagem de programação inteira, eu adoraria ouvir mais sobre isso.


Coloquei seu comentário para que Falk fosse notificado.
Merbs
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.