Напротив фильтра Блума?

Я пытаюсь оптимизировать программу, которая в основном выполняет миллионы тестов. Эти тесты созданы таким образом, что могут быть некоторые повторения. Конечно, я не хочу тратить время на выполнение тестов, которые я уже проводил, если я могу избежать этого эффективно.

Итак, я думаю об использовании фильтра Блума для хранения уже проведенных тестов. Однако фильтр Блума для меня небезопасен. Дает ложные срабатывания. То есть он может сообщить, что я провел тест, которого не делал. Хотя это может быть приемлемо в сценарии, над которым я работаю, мне было интересно, есть ли эквивалент фильтра Блума, но с ошибкой на противоположной стороне, то есть дающий только ложноотрицательные результаты.

Я безуспешно пролистал литературу.


person Community    schedule 11.03.2009    source источник
comment
cstheory.stackexchange.com / questions / 6596 /   -  person Mauricio Scheffer    schedule 22.10.2012
comment
Для полноты картины это может быть интересно: github.com/jmhodges/opposite_of_a_bloom_filter   -  person Dave    schedule 25.10.2012
comment
Есть такая штука со смешным названием «Противоположность фильтра Блума». Код: github.com/jmhodges/opposite_of_a_bloom_filter блог: somethingsimilar.com/2012/05/21/the-opposite-of-a-bloom- фильтр   -  person ib84    schedule 26.05.2013
comment
Надеюсь, они называют обратное цветением - ›фильтр moold!   -  person mLuby    schedule 03.03.2019


Ответы (9)


Да, хеш-таблица с потерями или 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.
person Community    schedule 15.06.2010
comment
Я бы добавил, что любой ответ, сочетающий модель памяти со стратегией выселения, такой как MRU, LFU или ARC, является правильным ответом на этот вопрос. - person Pimin Konstantin Kefaloukos; 30.09.2016
comment
в то время как любой набор с потерями с дискретным членством можно сказать, что он принадлежит к семейству структур данных, рассматриваемых как противоположность множеств с вероятностным членством, эвристика LRU представляет собой совершенно отдельную проблему и не имеет прямого отношения к вопросу. по общему признанию, то же самое и мой собственный ответ (он предполагает ассоциативность 1), если мы будем обобщать. достаточно сказать, что существует преобразование f(set, item) -> set', определенное таким образом, что при заданных set и item создается новый set', который может включать item в качестве члена с учетом ограничений по количеству элементов. выбор f не имеет значения - person awdz9nld; 20.05.2017

Точная структура данных, которая выполняет эту задачу, представляет собой кеш с прямым отображением и является обычно используется в процессорах.

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

function is_member(set, item)
    return set[hash(item) % set.length] == item
person awdz9nld    schedule 13.06.2012
comment
Также порядка миллионов вы можете использовать простой битовый массив. :) - person awdz9nld; 18.10.2012

Можно ли сохранить тесты, которые вы не запускали? Это должно изменить поведение фильтра.

person Tobiesque    schedule 09.05.2009
comment
Вы не можете этого сделать, потому что невозможно удалить элементы из фильтра Блума. - person RarrRarrRarr; 06.04.2010
comment
или фильтр кукушки cs.cmu.edu/~dga/papers/ cuckoo-conext2014.pdf bdupras.github.io/filter-tutorial - person Viktor Mellgren; 24.11.2016

  1. Используйте набор бит, как указано выше. Если вы знаете, что нет. тестов, которые вы собираетесь запустить заранее, вы всегда получите правильные результаты (присутствующие, отсутствующие) из структуры данных.
  2. Вы знаете, какие ключи вы будете хешировать? Если это так, вам следует провести эксперимент, чтобы увидеть распределение ключей в BloomFilter, чтобы вы могли точно настроить его для воспроизведения ложных срабатываний или чего-то еще.
  3. Вы также можете проверить HyperLogLog.
person Mohamed Bana    schedule 17.02.2015

Нет, и если подумать, это было бы не очень полезно. В вашем случае вы не могли быть уверены, что ваш тестовый прогон когда-либо остановится, потому что, если всегда есть «ложноотрицательные», всегда будут тесты, которые нужно запустить ...

Я бы сказал, вам просто нужно использовать хеш.

person f3lix    schedule 11.03.2009
comment
Спасибо за ваш ответ. Я думаю, что это все еще полезно, так как я всегда могу остановиться по прошествии определенного времени. Фактически, я могу создавать тесты вечно. Но такая структура данных поможет мне убедиться, что большинство тестов действительно новые, и при этом быстро не исчерпывается память. - person ; 11.03.2009

Как насчет LRUCache?

person Community    schedule 17.06.2009

Извините, я не очень помог - я не думаю, что это возможно. Если выполнение теста не может быть заказано, возможно, используйте упакованный формат (8 тестов на байт!) Или хорошую библиотеку разреженных массивов для хранения результатов в памяти.

person Einstein    schedule 17.06.2009

Я думаю, вы упускаете часть решения; чтобы полностью избежать ложных срабатываний, вам все равно придется отслеживать, какие из них были выполнены, и, по сути, использовать фильтр цветения в качестве ярлыка для определения того, что тест определенно не запускался.

Тем не менее, поскольку вы заранее знаете количество тестов, вы можете настроить фильтр таким образом, чтобы обеспечить приемлемую частоту ошибок с использованием некоторых хорошо известных формул; для 1% вероятности возврата ложного срабатывания вам потребуется ~ 9,5 бит на запись, поэтому для одного миллиона записей достаточно 1,2 мегабайта. Если вы уменьшите допустимую частоту ошибок до 0,1%, она увеличится только до 1,8 МБ.

Статья в Википедии Bloom Filters дает отличный анализ и интересный обзор задействованной математики.

person Andy Lynch    schedule 08.05.2010

Ожидаемая структура данных не существует. Потому что такая структура данных должна быть отображением "многие-к-одному" или, скажем, ограниченным набором состояний. Должно быть как минимум два разных входа, отображаемых в одно и то же внутреннее состояние. Таким образом, вы не можете сказать, есть ли оба (или более) из них в наборе, только зная, что существует хотя бы один из таких входных данных.

РЕДАКТИРОВАТЬ Это утверждение верно только тогда, когда вы ищете структуру данных с эффективным использованием памяти. Если память не ограничена, вы всегда можете получить структуру данных, которая дает 100% точные результаты, сохраняя каждый элемент элемента.

person roam    schedule 24.07.2012
comment
@ MartinKällman Вы правы, если эффективность памяти не является требованием, потому что все предложенные выше решения требуют хранения исходных элементов (set_member в вашем случае). После того, как предел памяти достигнут, он будет давать как ложноотрицательные, так и ложноположительные результаты. Фильтр Блума никогда не дает ложноотрицательных результатов, даже если частота ложных срабатываний довольно высока из-за слишком большого количества входных данных. - person roam; 28.05.2013
comment
Да, это требование для любого ассоциативного массива - person awdz9nld; 29.05.2013