2016-05-13 5 views
17

Я хочу решить Ax = b где A - очень большая квадратная положительно определенная симметричная матричная матрица и x и b - векторы. Когда я говорю «большой», я имею в виду матрицу nxnn размером 300,000.Решение больших линейных систем с блочными разреженными матрицами

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

Sparse matrix

А вот та же матрица увеличено, показывая, что она состоит из блоков плотных матриц,.

Sparze matrix zoomed in

Я ранее (см here, here, и еще в here) используется Чолески решатель Эйген, который работал отлично для n<10000 но с n=300000 решатель Cholesky слишком медленно. Однако я не воспользовался тем, что у меня есть блок-матрица. По-видимому, существуют алгоритмы для решения разреженных блочных матриц (например, block cholesky factorization).

Я хотел бы знать конкретно, если Eigen оптимизировал алгоритмы, используя факторизацию или итеративные методы, для разреженных плотных матричных матриц, которые я могу использовать?

Также вы можете предложить другие алгоритмы, которые могут быть идеальными для решения моей матрицы? Я имею в виду, насколько я понимаю, по крайней мере, для факторизации поиск матрицы перестановок является NP трудным, так что существует множество различных эвристических методов, и насколько я могу судить, что люди создают интуицию различных матричных структур (например, banded matrix) и какие алгоритмы работают лучше всего с их. У меня еще нет этой интуиции.

В настоящее время я изучаю conjugate gradient method. Я сам реализовал это на C++, но все еще не воспользовался тем, что матрица является блочной матрицей.

//solve A*rk = xk 
//Eigen::SparseMatrix<double> A; 
//Eigen::VectorXd rk(n); 
Eigen::VectorXd pk = rk; 

double rsold = rk.dot(rk); 
int maxiter = rk.size(); 
for (int k = 0; k < maxiter; k++) { 
    Eigen::VectorXd Ap = A*pk; 
    double ak = rsold /pk.dot(Ap); 
    xk += ak*pk, rk += -ak*Ap;  
    double rsnew = rk.dot(rk); 
    double xlength = sqrt(xk.dot(xk)); 
    //relaxing tolerance when x is large 
    if (sqrt(rsnew) < std::max(std::min(tolerance * 10000, tolerance * 10 * xlength), tolerance)) { 
     rsold = rsnew; 
     break; 
    } 
    double bk = rsnew/rsold; 
    pk *= bk; 
    pk += rk; 
    rsold = rsnew; 
} 
+0

Вы действительно хотите реализовать это самостоятельно? Может быть, вы должны попробовать некоторые доступные библиотеки, которые делают такие вещи? Например. [Элементный] (http://libelemental.org/). – sascha

+0

@sascha, я рад использовать библиотеки, я уже делаю это с Eigen (кроме специального метода сопряженного градиента), но я бы рассмотрел другие, если Eigen недостаточно для этого случая. –

+0

Eigen звучит как базовая линейная алгебра для меня, без (более сложного, структурирующего) алгоритма оптимизации как такового. Но я никогда не использовал его. Хотя у меня также нет опыта вообще с * elemental *, я действительно думаю, что материал, который вы делаете, как можно возможно (и, вероятно, очень оптимизирован). К сожалению, нет никаких намеков, которые я мог бы вам дать. Возможно, посмотрите часть [этого] (http://libelemental.org/documentation/dev/optimization/models.html) части документов. Удачи! – sascha

ответ

0

Я думаю, что ARPACK был разработан, чтобы быть эффективным для задач, как найти решение системы уравнений Ах = Ь, когда А sparce, как в вашем случае. Вы можете найти исходный код для ARPACK here.

1

Отъезд SuiteSparse, http://faculty.cse.tamu.edu/davis/suitesparse.html Автор, Тим Дэвис, известен в области редких матриц. Он также получил награду от Google за качество кода. Выполнение его кода также выдающееся.

Cheers

Смежные вопросы