寻找“指纹”集合


11

假设我们有10个人,每个人都有喜爱的书籍清单。对于给定的人X,我想找到X的一个特殊子集,该子集仅被X所喜欢,也就是说,没有其他人喜欢X的特殊子集中的所有书。我认为这个特殊子集是X的唯一“指纹”。

我希望能找到有关找到此类集合的方法的建议。(虽然这听起来像是一个家庭作业问题,但它与我要解决的生物学研究中的问题有关。)


1
可能的书籍的范围/数量是否有限?可以随时进行这种“指纹”识别-将每本书添加到某个人的收藏夹中-还是事先获得了一组清单?
Paresh

Answers:


6

我假设您希望指纹尽可能小。这就是“ 命中集”问题:对于每个人,列出X而不是此人喜欢的所有书籍的列表。然后,目标是从每个列表中至少选择一本书。问题是NP难题,因此您不能期望找到一个总是在多项式时间内最优解决问题的算法。贪婪算法在理论上存在最坏情况下的局限性,但在实践中通常效果不错。如果要最佳地求解,则整数线性规划求解器应能够求解多达1000甚至10000本书籍的实例。如果您提供有关实例大小和结构的更多详细信息,我们可以建议其他方法。


+1当然你是对的!:)不难构建我的贪婪算法遗漏的示例。哎呀
Patrick87 2012年

OP:非常感谢您的反馈-原始的贪婪算法解决方案使我朝着正确的方向前进。我正在处理的总空间涉及100个个体和1000个“书”-如果整数编程方法可行,那么我想听听更多。
Merbs 2012年

4

这不是一个特别聪明的算法,但是它是多项式,我认为它应该可以工作。采取任何设置。对于此集合中的每个元素,计算不包含该元素的剩余集合的数量,并记住包含这些元素的集合。选择计数最高的元素,然后重做其余元素的计数,而忽略缺少刚选择的元素的集合。继续进行,直到所有剩余的设置都被排除在考虑之外。

例如:让= { 2 3 4 }c ^ = { 2 4 6 },和d = { 1 3 5 }。然后我们有计数c 1 = 2c 2 = 1c 3 = 1一种={1个23}={234}C={246}d={1个35}C1个=2C2=1个C3=1个。我们选择1,消除不包含集合C的集合;重做计数,我们有c 2 = 1c 3 = 0。我们选择2作为下一个元素,并从考虑中删除D。我们现在做的,我们的“指纹”是集合{ 1 2 }。编辑:要完成这个例子,你应该得到的其他指纹套出来为{ 3 4 }{ 6 }{ 5 }CC2=1个C3=0d{1个2}{34}{6}{5}

我没有考虑太多,但是从直观上看,它似乎应该起作用。这个想法是贪婪地将覆盖最多未发现集的项目作为指纹集的下一个元素。


请参阅Falk Huffner的答案,在那里他可以正确地将您的问题识别为NP-Hard Hitting Set问题。看来我的回答给出了问题的通常贪婪近似,虽然不错,但也不是最优的。
Patrick87 2012年

0

中号中号[bØØķ]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

这是OP(初次提交时未注册,所以现在我不能正确评论)。非常感谢您的反馈-原始的贪婪算法解决方案使我朝着正确的方向前进。我正在处理的总空间涉及100个个体和1000个“书”-如果整数编程方法可行,那么我想听听更多。


我发表了您的评论,以使福尔克得到通知。
Merbs 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.