Оптимизация вычисления внутреннего цикла в Mathematica - PullRequest
3 голосов
/ 14 июля 2010

В настоящее время я делаю некоторые вычисления в Mathematica, связанные с квантовой механикой.По мере того как мы перешли от 1D к 2D решеточной модели, размер проблемы становится проблематичным

В настоящее время у нас есть суммирование, которое выглядит примерно так:

corr[r1_, r2_, i_, j_] = Sum[Cos[f[x1, x2] Angle[i] r1 + f[y1, y2] Angle[j] r2], {x1, HL}, {x2, HL}, {y1, HL + 1, 2 HL}, {y2, HL + 1, 2 HL}];

f [.,.] - это функция поиска для предварительно вычисленной корреляционной функции, и угол [.] также вычисляется заранее.

Нет никакого способа упростить это каким-либо образом.Мы уже взяли простую оптимизацию путем преобразования комплексной экспоненты (которая имела нулевую мнимую часть) в выражение косинуса выше.

Большая проблема состоит в том, что эти HL основаны на размерном размере: Для линейного измерения L вдоль оси, HL соответствует L ^ d (здесь d = 2).Таким образом, в действительности мы вычисляем O (n ^ 8), пренебрегая суммой по i, j.

Обычно это не так уж плохо для L = 8, если бы не тот факт, что мы повторяем это для 125 значений r1 и 125 для r2 для создания изображения 125 x 125.

Мой вопрос: как мне наиболее эффективно рассчитать это в Mathematica?Я бы сделал это на другом языке, но есть определенные проблемы, которые сделают его таким же медленным, если я попробую что-то вроде C ++.

Дополнительная информация: Это вычисление корреляции ND-ND (плотность чисел).Все x и y относятся к точкам разграничения на дискретной двумерной сетке.Единственная недискретная вещь здесь - это наши буквы.

1 Ответ

5 голосов
/ 16 июля 2010

Кажется, что замена преобразования Фурье на косинусное преобразование была неправильным временем для оптимизации, поскольку скрывает тот факт, что этот расчет корреляции действительно является просто продуктом двух преобразований Фурье (что является единственным эффективным способом вычисления корреляций. знать).
С ir1=Angle[i] r1 и ir2=Angle[j] r2 ваше выражение эквивалентно

Sum[Cos[f[x1, x2] ir1 + f[y1, y2] ir2], {x1, HL}, {x2, HL}, {y1, HL+1, 2 HL}, {y2, HL+1, 2 HL}]
== Re@Sum[Exp[I f[x1, x2] ir1] Exp[I f[y1, y2] ir2], {x1, HL}, {x2, HL},{y1, HL+1, 2 HL}, {y2, HL+1, 2 HL}]
== Re[corr1[ir1] corr2[ir2]]

где

corr1[ir_]:=Sum[Exp[I f[x1, x2] ir], {x1, HL}, {x2, HL}];
corr2[ir_]:=Sum[Exp[I f[y1, y2] ir], {y1, HL+1, 2 HL}, {y2, HL+1, 2 HL}];

Поскольку я уже сократил ваш показатель масштабирования пополам, я ожидаю, что вы счастливы :), но если f является действительным значением, вы можете сократить еще один фактор из двух показателей:
В этом случае мы можем выразить corr1 как интеграл по значениям f - учитывая, что вы можете каким-то образом получить весовую функцию w. Если ничего другого, вы можете сделать это численно с помощью простой процедуры биннинга.

corr1v2[ir_]:=Sum[ w[fval] Exp[I fval ir], {fval,fvals}],

, который проясняет, что corr1 на самом деле является просто преобразованием Фурье весовой функции f (так что вы должны вычислять его с БПФ, а не с суммой, указанной выше). То же самое касается corr2.
В качестве альтернативы, если f не является действительным значением, но имеет достаточную симметрию, чтобы позволить вам выполнить повторную параметризацию в форме, поэтому f зависит только от одного из новых параметров (скажем, r, phi), вы также сократить corr1 интегралы в одном измерении, хотя это может быть не просто преобразование Фурье.

...