Подходящий тип объекта для 2D-справочной таблицы неизвестного размера, созданной во время выполнения.

Я пишу скрипт Python 3.4, который выполняет для меня большие вычисления. Этот расчет включает в себя вычисление много-много биномиальных коэффициентов и использование каждого из них. много раз в суммах и умножениях с другими числами. Каждый раз, когда для расчета требуется bc (биномиальный коэффициент), он проверяет, был ли уже рассчитан bc. Если это так, он возвращает это уже рассчитанное значение. В противном случае он вычисляет его и сохраняет для последующего поиска. В настоящее время моя функция bc(n,k), которая вычисляет bc "n, выбирает k", выглядит следующим образом:

bcvalues = {}

def bc(n,k):
    k = min(k,n-k) # take advantage of symmetry
    if (n,k) in bcvalues: # check whether value has already been calculated
        return bcvalues[(n,k)] # if so, return that already calculated value
    if k == 0 or n <= 1: # base case
        return 1
    result = bc(n-1,k) + bc(n-1,k-1) # Use formula for Pascal's triangle
    bcvalues[(n,k)] = result # store the value for later look-up
    return result

Моя справочная таблица представляет собой словарь с кортежем (n,k) в качестве ключа и bc(n,k) в качестве значения. Он удовлетворяет всем

Строгие требования

  1. Может быть заполнен/расширен до произвольного размера во время выполнения (до запуска расчета я понятия не имею, сколько bc нужно вычислить, но это много bc)
  2. Значения могут быть сколь угодно большими (либо int (тип Python 3), либо тип gmpy2 mpz, Я еще не уверен). Это важно, так как значения могут стать очень большими.
  3. Его можно проиндексировать двумя натуральными числами n и k
  4. Bc для некоторых кортежей (n,k) можно пропустить (например, может быть запись для (100,50), но нет записи для (100,49))

Однако я не уверен, является ли это оптимальным решением (если оно вообще существует) с точки зрения

Требования к производительности (в порядке важности)

  1. Быстрый просмотр/считывание
  2. Низкое потребление памяти (в тестах мой словарь уже занимал несколько ГБ; в конечном итоге я могу арендовать вычислительную мощность на машинах с большой памятью)
  3. Быстрая запись в справочную таблицу

В тестах с очень небольшим размером входных данных, которые я только что провел, функция bc была вызвана 16 миллионов раз, и это число, вероятно, сильно возрастет для размеров входных данных, которые меня действительно интересуют. Следовательно, производительность имеет значение.

Мое текущее решение (словарь) имеет то преимущество, что в конце прогона вычислений я могу сериализовать справочную таблицу (используя рассол), так что, когда я выполняю новый прогон с более высокими входными значениями, я могу распаковать его и иметь все имеющиеся БК, которые были рассчитаны в предыдущих прогонах. Это сильный бонус:

Бонусный балл

  1. Справочную таблицу можно легко сериализовать.

Мой вопрос

Что, кроме словаря, может быть кандидатом на соответствие этим критериям?

Я подумал о написании функции, которая биективно сопоставляет кортежи (n,k) треугольника с натуральными числами, а затем использует список для справочной таблицы. Насколько это перспективно? Другие идеи?


person Corsin Pfister    schedule 16.07.2015    source источник


Ответы (1)


Отказ от ответственности: я поддерживаю gmpy2.

Как только вы начнете работать с целыми числами, длина которых превышает 50–100 десятичных цифр, вам следует использовать gmpy2.mpz.

Словарь кажется лучшим выбором. Индексирование списка немного быстрее, чем поиск по словарю, но накладные расходы на сопоставление (n,k) со значением индекса замедляют его работу в моей системе.

Возможно, есть способ уменьшить использование памяти. Вы вычисляете биномиальный коэффициент рекурсивно и сохраняете все промежуточные значения. bcvalues станет очень большим. Если вам не нужны все биномиальные коэффициенты для меньших значений n и k, вы можете попробовать использовать gmpy2.comb для вычисления биномиального коэффициента и не сохранять все промежуточные значения.

person casevh    schedule 18.07.2015
comment
Спасибо за Ваш ответ! Я хотел бы знать, что делает gmpy2.comb. Где я могу найти его исходный код? - person Corsin Pfister; 19.07.2015
comment
@CorsinPfister Код является частью библиотеки GMP (www.gmplib.org). gmpy2.comb звонит mpz_bin_ui. Можно использовать более быструю версию под названием mpz_bin_uiui, если оба аргумента достаточно малы. Я сделал несколько быстрых тестов, и, похоже, это работает быстрее. Я обновлю свой ответ, когда закончу тестирование. Кстати, каковы диапазоны значений n и k? Часто ли вы повторно используете одни и те же значения? - person casevh; 20.07.2015