좋아하는 책 목록이있는 10 명의 사람이 있다고 가정하겠습니다. 주어진 사람 X의 경우, X만이 좋아하는 X 책의 특별한 부분 집합을 찾고 싶습니다. 즉, X의 특별한 부분 집합에서 모든 책을 좋아하는 사람은 없습니다. 이 특수한 부분 집합을 X의 고유 한 "지문"이라고 생각합니다.
그런 세트를 찾는 접근법에 대한 제안을 부탁드립니다. (이것은 숙제 문제처럼 보이지만, 내가 해결하려는 생물학 연구의 문제와 관련이 있습니다.)
좋아하는 책 목록이있는 10 명의 사람이 있다고 가정하겠습니다. 주어진 사람 X의 경우, X만이 좋아하는 X 책의 특별한 부분 집합을 찾고 싶습니다. 즉, X의 특별한 부분 집합에서 모든 책을 좋아하는 사람은 없습니다. 이 특수한 부분 집합을 X의 고유 한 "지문"이라고 생각합니다.
그런 세트를 찾는 접근법에 대한 제안을 부탁드립니다. (이것은 숙제 문제처럼 보이지만, 내가 해결하려는 생물학 연구의 문제와 관련이 있습니다.)
답변:
지문을 최대한 작게 만들고 싶다고 가정합니다. 그렇다면 이것은 타격 세트 문제입니다 : 각 사람마다,이 사람이 아닌 X가 좋아하는 모든 책의 목록을 만드십시오. 그런 다음 각 목록에서 하나 이상의 책을 선택하는 것이 목표입니다. 문제는 NP-hard이므로 다항식 시간에 항상 최적으로 해결하는 알고리즘을 찾을 수 없습니다. 욕심 많은 알고리즘은 이론상 최악의 경우가 좋지 않지만 실제로는 꽤 괜찮습니다. 최적으로 해결하려면 Integer Linear Programming 솔버가 최대 1000 개 또는 10000 권의 인스턴스를 해결할 수 있어야합니다. 인스턴스의 크기와 구조에 대한 자세한 내용을 제공하면 다른 방법을 제안 할 수 있습니다.
이것은 특히 영리한 알고리즘은 아니지만 다항식이며 작동해야한다고 생각합니다. 어떤 세트를 가져 가십시오. 이 세트의 각 요소에 대해 포함되지 않은 나머지 세트 수를 세고 어떤 세트를 포함하는지 기억하십시오. 개수가 가장 큰 요소를 선택하고 방금 선택한 요소가없는 세트를 무시하고 나머지 요소의 개수를 다시 실행하십시오. 나머지 세트가 모두 고려되지 않을 때까지 계속하십시오.
예 : , B = { 2 , 3 , 4 } , C = { 2 , 4 , 6 } , D = { 1 , 3 , 5 }로 지정하십시오 . 그런 다음 c 1 = 2 , c 2 = 1 , c 3 = 1입니다.. 포함하지 않은 세트 와 C 를 제거하고 1을 선택 합니다. 카운트를 다시 실행하면 c 2 = 1 및 c 3 = 0이 됩니다. 다음 요소로 2를 선택 하고 고려에서 D 를 제거 합니다. 이제 "지문"세트는 { 1 , 2 } 입니다. 편집 : 예제를 완료하려면 다른 지문 세트가 { 3 , 4 } , { 6 } 및 { 5 } 로 나오도록해야합니다 .
나는 이것을 많이 생각하지 않았지만 직관적으로 작동 해야하는 것처럼 보입니다. 아이디어는 지문의 다음 요소가 가장 많이 발견되지 않은 세트를 다루는 항목을 탐욕스럽게 생각하는 것입니다.
fingerprint books
파이썬 코드를 보여 드리겠습니다.
%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']}