Всех приветствую.
Встала такая практическая задача: хотя бы грубо и лучше сверху оценить количество уникальных элементов некоторого итерационно вычисляемого множества. Т.е. на каждом шаге к имеющемуся множеству применяется некий оператор, добавляющий (или не добавляющий) в него элементы. После нескольких первых шагов элементы добавляться перестают (оператор переводит элементы только в уже существующие) и размер множества застывает - вот этот размер и надо бы оценить. Порядок размера множества в точности неизвестен, но самая грубая оценка даёт много триллионов элементов, ни в память ни на диск полный список не влезает. Каждый элемент множества - число в интервале
(16 байтов). Если это чем-то поможет, то единиц в этом числе максимум четверть (скорее даже 28-30), но как это применить не представляю.
Основная трудность - проверить что новый вычисленный элемент уже встречался.
Какие методы знаю:
0. Тривиальный битовый массив всех возможных состояний элементов. Но объём
битов за гранью даже фантастики.
1. Сортированный массив всех элементов. Проверка наличия относительно быстрая
, но вот добавление элемента - смерть, пересортировка массива.
2. Двоичное дерево поиска. В каждом узле - сам элемент множества (16 байтов) плюс 2-3 указателя (8-24 байтов). Всё бы хорошо, все операции тоже относительно быстрые
, но хотелось бы ещё быстрее.
3. Несколько последовательных (в следующую класть лишь коллизии предыдущей) хеш-таблиц с разными хеш-функциями (одной мало или слишком трудно вычислимая). Проверка наличия элемента моментальная
, удаление (оно требуется на нескольких первых шагах пока суммарный объём меньше миллионов элементов) тоже в общем не сильно сложно, вопрос только в объёме.
3а. Не хранить в хеш-таблицах сами числа/элементы, только бит наличия (фактически гарантированного отсутствия) элементов с заданным хешем, памяти всего 1 бит на элемент, с коллизиями разбираться отдельно в надежде что их будет намного меньше.
4. Сделать хеш-таблицы не последовательными, а одновременными, как в китайской теореме об остатках. Пока размеры каждой хеш-таблицы меньше суммарного размера множества будет потеря информации и соответственно оценка выйдет сверху - вопрос насколько грубой окажется. Ну и с удалением элементов засада (но в принципе обходимая).
Насколько понимаю ни один из методов не позволяет даже примерно оценить количество если оно сильно больше размера памяти (на крайний случай диска). А на то есть подозрения.
Запускать несколько (реально как бы не миллионы) раз для подсчёта таблиц/массивов по частям тоже не вариант (в основном из-за итерационности построения множества).
Есть какие-то ещё хитрые способы? Или ограничение в бит/элемент не улучшаемо (как и подозреваю)? Даже если отказаться от точного подсчёта и допустить не слишком большую (максимум полпорядка) погрешность?