Data structures 布卢姆过滤器的对面?

Data structures 布卢姆过滤器的对面?,data-structures,bloom-filter,Data Structures,Bloom Filter,我正在尝试优化一个软件,它基本上运行着数百万个测试。这些测试是以这样一种方式生成的,即可以有一些重复。当然,如果我能有效避免的话,我不想花时间运行我已经运行过的测试 因此,我正在考虑使用Bloom过滤器来存储已经运行的测试。然而,布鲁姆过滤器对我来说是不安全的。它给出了误报。也就是说,它可能会报告我已经运行了一个测试,但我没有。虽然这在我正在研究的场景中是可以接受的,但我想知道是否有一个与Bloom过滤器等效的过滤器,但在另一方面出错,即只给出假阴性 我很幸运地浏览了一下这些文献。没有,如果你仔

我正在尝试优化一个软件,它基本上运行着数百万个测试。这些测试是以这样一种方式生成的,即可以有一些重复。当然,如果我能有效避免的话,我不想花时间运行我已经运行过的测试

因此,我正在考虑使用Bloom过滤器来存储已经运行的测试。然而,布鲁姆过滤器对我来说是不安全的。它给出了误报。也就是说,它可能会报告我已经运行了一个测试,但我没有。虽然这在我正在研究的场景中是可以接受的,但我想知道是否有一个与Bloom过滤器等效的过滤器,但在另一方面出错,即只给出假阴性


我很幸运地浏览了一下这些文献。

没有,如果你仔细想想,那就没什么用处了。在您的情况下,您无法确定您的测试运行是否会停止,因为如果始终存在“错误否定”,那么将始终存在需要运行的测试


我想说,您只需要使用散列。

是否可以存储您运行的测试?这应该会改变过滤器的行为。

LRUCache怎么样?

对不起,我帮不了什么忙-我认为这是不可能的。如果测试执行无法排序,可以使用压缩格式(每个字节8个测试!)或良好的稀疏数组库将结果存储在内存中。

我认为您遗漏了部分解决方案;为了完全避免误报,您仍然需要跟踪哪些测试已经运行,并且基本上使用bloom过滤器作为快捷方式来确定测试是否确实没有运行

也就是说,由于您事先知道测试的数量,因此可以使用一些众所周知的公式调整过滤器的大小,以提供可接受的错误率;对于1%的误报概率,您需要约9.5位/条目,因此对于一百万条条目,1.2兆字节就足够了。如果将可接受的错误率降低到0.1%,这只会增加到1.8 MB


Wikipedia的文章给出了一个很好的分析,并对所涉及的数学进行了有趣的概述。

是的,有损哈希表或LRUCache是一种具有快速O(1)查找的数据结构,只会给出错误的否定结果——如果你问“我是否运行过测试X”,它会告诉你“是的,你肯定有”,或者“我记不起来了”

请原谅这个极其粗糙的伪代码:

setup_test_table():
    create test_table( some large number of entries )
    clear each entry( test_table, NEVER )
    return test_table

has_test_been_run_before( new_test_details, test_table ):
    index = hash( test_details , test_table.length )
    old_details = test_table[index].detail
    // unconditionally overwrite old details with new details, LRU fashion.
    // perhaps some other collision resolution technique might be better.
    test_table[index].details = new_test_details
    if ( old_details === test_details ) return YES
    else if ( old_details === NEVER ) return NEVER
    else return PERHAPS    

main()
    test_table = setup_test_table();
    loop
        test_details = generate_random_test()
        status = has_test_been_run_before( test_details, test_table )
        case status of
           YES: do nothing;
           NEVER: run test (test_details);
           PERHAPS: if( rand()&1 ) run test (test_details);
    next loop
end.

完成此任务的确切数据结构是a,并且通常在CPU中使用

function set_member(set, item)
    set[hash(item) % set.length] = item

function is_member(set, item)
    return set[hash(item) % set.length] == item

您期望的数据结构不存在。因为这样的数据结构必须是一个多对一映射,或者说是一个有限的状态集。必须至少有两个不同的输入映射到相同的内部状态。因此,您无法判断这两个(或多个)输入是否都在集合中,只能知道至少存在一个这样的输入

只有在寻找内存效率高的数据结构时,编辑此语句才为真。如果内存是无限的,通过存储每个成员项,您总是可以得到一个数据结构,以提供100%的准确结果

  • 如上所述,使用位集。如果您事先知道要运行的测试的数量,您将始终从数据结构中获得正确的结果(存在,不存在)
  • 你知道你将散列哪些键吗?如果是这样的话,您应该运行一个实验来查看BloomFilter中键的分布,这样您就可以对其进行微调,以重现误报,或者您所拥有的一切
  • 您可能还需要签出HyperLogLog

  • 谢谢你的回复。我认为它仍然有用,因为我总是可以在固定的时间后停止。事实上,我可以一直生成测试。但这样的数据结构将帮助我确保大多数测试实际上都是新的测试,而不会很快耗尽内存。你不能这样做,因为不可能从Bloom过滤器中取出元素。或者也可以使用数以百万计的布谷鸟过滤器,你可以使用一个简单的位数组。:)为了完整起见,这可能是有趣的:有一个这样的东西有一个有趣的名字“布卢姆过滤器的对面”。代码:blog:我希望他们称之为相反的bloom–>moold过滤器@MartinKällman如果内存效率不是一个要求,那么您是正确的,因为上面提出的所有解决方案都需要存储原始项(在您的案例中是set_成员)。在满足记忆限制后,它将给出假阴性和假阳性结果。Bloom Filter不会给出假阴性结果,即使由于输入太多导致假阳性率相当高。是的,这是任何关联阵列的要求。我想补充的是,任何将内存模型与逐出策略(如MRU、LFU或ARC)相结合的答案,是这个问题的有效答案。虽然任何具有离散成员资格的有损集合都可以说是被视为具有概率成员资格的集合的“相反”的数据结构家族,但LRU启发式是一个完全独立的问题,与该问题没有直接关联。诚然,我自己的答案也是如此(假设关联性为1),如果我们要概括的话。只要说有一个变换
    f(set,item)->set'
    就足够了,它的定义使得给定一个
    set
    和一个
    item
    ,就会产生一个新的
    set'
    ,它可能包括
    item
    作为一个成员,受基数约束。选择
    f
    是不相关的