нужна помощь в разработке алгоритма поиска более эффективным способом - PullRequest
6 голосов
/ 09 сентября 2011

У меня есть проблема, которая касается области биологии. Прямо сейчас у меня есть 4 ОЧЕНЬ БОЛЬШИХ файла (каждый с 0,1 миллиардами строк), но структура довольно проста, каждая строка этих файлов имеет только 2 поля, оба обозначают тип гена.

Моя цель: разработать эффективный алгоритм, который может достичь следующего: Найдите круг в содержимом этих 4 файлов. Круг определяется как:

field #1 in a line in file 1 == field #1 in a line in file 2 and
field #2 in a line in file 2 == field #1 in a line in file 3 and
field #2 in a line in file 3 == field #1 in a line in file 4 and
field #2 in a line in file 4 == field #2 in a line in file 1

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

Ответы [ 4 ]

1 голос
/ 09 сентября 2011

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

Учитывая это, вы можете соединить два файла, отсортировав их так, чтобы первый сортировался в поле № 1, а второй - в поле № 2. Затем вы можете создать одну запись для каждого совпадения, объединяя все поля и сохраняя в памяти только фрагмент каждого файла, в котором все поля, по которым вы отсортировали, имеют одинаковое значение. Это позволит вам связать результат с другим файлом - четыре таких соединения должны решить вашу проблему.

В зависимости от ваших данных, время, необходимое для решения вашей проблемы, может зависеть от порядка, в котором вы устанавливаете соединения. Один из довольно наивных способов использовать это на каждом этапе - брать небольшую случайную выборку из каждого файла и использовать ее, чтобы увидеть, сколько результатов последует из каждого возможного соединения, и выбрать соединение, которое дает наименьшее количество результатов. Один из способов получить случайную выборку из N элементов из большого файла - это взять первые N строк в файле, а затем, когда вы уже прочитали m строк, прочитать следующую строку, а затем с вероятностью N / (m + 1) обменять одну из N строк, удерживаемых для него, иначе выбросить. Продолжайте, пока не прочитаете весь файл.

0 голосов
/ 09 сентября 2011

Немного проще объяснить, если ваш Файл 1 работает наоборот (поэтому каждый второй элемент указывает на первый элемент в следующем файле).

  1. Начните с файла 1, скопируйте его в новый файл, записав каждую пару A, B как B, A, 'REV'

  2. Добавьте к нему содержимое файла 2, записав каждую пару A, B как A, B, 'FWD'

  3. Сортировка файла

  4. Обрабатывать файл кусками с одинаковым начальным значением

    • Внутри этой порции сгруппируйте строки в REV и FWD
    • Возьмите декартово произведение числа оборотов и вперёд (вложенная петля)
    • Напишите строку с обратным (fwd) concat (rev), исключая повторный токен
    • например. B, A, «REV» и B, C, «FWD» -> C, B, A, «REV»
  5. Добавить следующий файл к этому новому выходному файлу (добавляя 'FWD' к каждой строке)

  6. Повторите с шага 3

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

Конечно, было бы еще проще просто прочитать эти файлы в базу данных и позволить ей выполнить всю работу ...

0 голосов
/ 09 сентября 2011

Вот один подход:

Мы будем использовать обозначение Fxy, где x = номер поля, y = file_no

Сортировка каждого из 4 файлов по первым полям.

Для каждого поля F11 найдите соответствие в файле 2. Это будет линейным. Сохраните эти совпадения со всеми четырьмя полями в новый файл. Теперь используйте этот файл и используйте соответствующее поле в этом файле и получите все совпадения из file3. Продолжить для file4 и вернуться к file1.

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

Здесь сложность в O (n log n) для сортировки и O (m log n) для поиска, предполагая, что m << n. </p>

0 голосов
/ 09 сентября 2011

Вот один алгоритм:

  • Выберите подходящую структуру поиска: Если поле # 1 является целым числом, используйте битовые поля или словарь (или набор), если это строка;Используйте структуру поиска для каждого файла, т.е. 4 в вашем случае
  • Фаза инициализации: Для каждого файла: анализируйте файл построчно и устанавливайте соответствующий бит в битовом поле или добавляйте поле в словарь всоответствующая структура поиска для файла.
  • После инициализации структуры поиска выше, проверьте условие в вашем вопросе.

Сложность этого зависит от реализации структуры поиска.Для битовых полей это будет O (1), а для набора или словаря - O (lg (n)), поскольку они обычно реализуются как сбалансированное дерево поиска.Полная сложность будет O (n) или O (n lg (n));Ваше решение в вопросе имеет сложность O (n ^ 4)

Код и решение для битовых полей можно получить по адресу здесь

HTH

...