Я хотел бы уменьшить и ограничить объем памяти, используемый при сравнении всех комбинаций элементов в наборе друг с другом, где набор может увеличиться до любого размера. Я думал о том, чтобы разбить набор на более мелкие части, но тогда, когда требуются все комбинации, я не могу понять, как это сделать, не заканчивая тем, что в какой-то момент не потребовались все комбинации в памяти.
например, если у меня есть пункты A, B, C, D, E, FI, необходимо сравнить все различные комбинации
A B C D E F
A
B x
C x x
D x x x
E x x x x
F x x x x x
и так далее. Наборы, как правило, состоят из 100–10 000 документов с метаданными, которые проверяются различными эвристиками.
В настоящее время я достигаю этого (не загружая все элементы в память одновременно), дважды повторяя набор в два идентичных вложенных запроса к базе данных с использованием курсора в каждом для итерации по двум измерениям комбинаций. Это теоретически не ограничено в масштабе и использует очень мало памяти, но кажется немного расточительным, так как я буду запрашивать каждый элемент N + 1 раз (где N - размер набора). Конечно, это немного напрягает базу данных.
Это текущий простой алгоритм:
- Подготовить запрос для набора
- , когда cursor.next A:
- Подготовить запрос к набору, исключая A
- во время курсора. Следующий B:
Это приводит к последовательности AB, A C, AD, AE, AF, BA, B C, BD et c. и я храню только два документа одновременно, но у него две проблемы. Во-первых, внутренний запрос происходит N раз. Если бы я не исключал A в запросе, это был бы тот же самый запрос, повторный N раз, который просто кажется расточительным. Вторая проблема - это перестановки, поэтому я выполняю вдвое больше работы, чем необходимо, и вынужден выводить результаты.
Я думал о кэшировании элементов по мере продвижения, но понял, что со временем он просто возрастет содержат все предметы, чтобы завершить все комбинации. Таким образом, это привело к полному кругу идеи базового c простого выбора всего набора один раз в память и сканирования комбинаций из одного массива. Это просто, но, конечно, не масштабируемо.
Итак, существует ли алгоритм для сравнения всех комбинаций различных пар в наборе, используя только разделы набора в любой момент времени, что гарантированно суммирует, чтобы покрыть все комбинации?
Я не мог придумать одну наивно. например, если вы разделите его на две половины, вам все равно нужно загрузить комбинацию двух подмножеств в какой-то момент. Возможно, «все шансы» и «все четы», но это только вдвое уменьшит проблему масштабируемости.
B D F
B
D x
F x x
, затем
A C E
A
C x
E x x
, но это пропускает половину комбинаций.
У меня есть ощущение, что это теоретически невозможно, но мне интересно, может быть, есть хитрый математический трюк? Или я упускаю что-то действительно очевидное.
ОБНОВЛЕНИЕ - вопрос отредактирован и, надеюсь, прояснен после первоначальных комментариев.
Nikos.M дал мне идею предварительно сгенерировать "индексы" пары комбинации. тогда я мог бы запросить для каждой пары.
Изначально я надеялся достичь того, что MicSim называет «сладким пятном» некоторого среднего уровня размеров партий. Так что не атомная загрузка каждой пары в одном крайнем случае, ни загрузка всего набора на другом конце, а некоторый метод пакетной обработки фиксированного размера, чтобы сохранить объем обработки на одном уровне.