2012-09-07 20 views
16

Czy istnieje jakakolwiek szybsza metoda potęgowania macierzy do obliczania M^n (gdzie M jest macierzą, a n jest liczbą całkowitą) niż prosty algorytm dzielenia i podbijania.Szybka macierzowa potęgacja

+1

Hej Znalazłem jedno ogniwo w stackoverflow tylko to sprawdzić http://stackoverflow.com/questions/12268516/matrix-exponentiation -using-fermats-theorem –

+0

Expokit jest dobrze znanym pakietem do wykonywania potęgowania macierzy. http://fortranwiki.org/fortran/show/Expokit – Sayan

Odpowiedz

22

Można dokonać analizy macierzy na wartości własne i wektory własne. Otrzymasz wtedy:

M = V^-1 * D * V 

Gdzie V jest macierzą wektorów własnych, a D jest macierzą diagonalną. Aby podnieść tę wartość do N-tej potęgi, otrzymujesz coś takiego:

M^n = (V^-1 * D * V) * (V^-1 * D * V) * ... * (V^-1 * D * V) 
    = V^-1 * D^n * V 

Ponieważ wszystkie warunki V i V^-1 znoszą się.

Ponieważ D jest przekątną, wystarczy podnieść kilka (rzeczywistych) liczb do n-tej mocy, zamiast pełnych macierzy. Możesz to zrobić w logarytmicznym czasie w n.

Obliczanie wartości własnych i wektorów własnych to r^3 (gdzie r jest liczbą rzędów/kolumn M). W zależności od względnych rozmiarów r i n, może to być szybsze lub nie.

+0

O ile wiem, ta metoda ma taką samą złożoność jak potęgowanie przez Squaring. Czy istnieje szybsza metoda? –

+0

@AkashdeepSaluja: to jest szybsze niż potęgowanie przez kwadrowanie. Jest to czas O (r^3), potęgowanie przez kwadrowanie jest czasem O (r^3 logn). –

+0

dla lepszego wyjaśnienia metody wymienionej powyżej http://www.google.co.in/url?sa=t&rct=j&q=pdf%20nth%20power%20of%20matrix&source=web&cd=1&cad=rja&ved=0CCAQFjAA&url=http% 3A% 2F% 2Fwww.qc.edu.hk% 2Fmath% 2FTeaching_Learning% 2FNth% 2520power% 2520of% 2520a% 2520square% 2520matrix.pdf & ei = Jf9JULrwFsi8rAejh4C4DQ & usg = AFQjCNE7yqQce5jdtyyVLFpSZmYUnoWyVA –

4

Exponentiation by squaring jest często używany do uzyskania wysokiej mocy matryc.

+0

znam tę metodę, ale muszę ją przyspieszyć. –

+0

Dodaj tę nazwę algorytmu do pytania, aby uniknąć podobnych odpowiedzi :) – MBo

+0

Szybszy algorytm jest znacznie bardziej skomplikowany. – Ari

0

Polecam podejście stosowane do obliczenia sekwencji Fibbonacci w matrix form. AFAIK, jego wydajność to O (log (n)).

+1

Musisz to pomnożyć przez koszt pomnożenia macierzy.Ogólny czas działania to O (n^3 log n). – saadtaame

6

To dość prosty w obsłudze algorytm szybkiej mocy Eulera. Użyj następnego algorytmu.

#define SIZE 10 

//It's simple E matrix 
// 1 0 ... 0 
// 0 1 ... 0 
// .... 
// 0 0 ... 1 
void one(long a[SIZE][SIZE]) 
{ 
    for (int i = 0; i < SIZE; i++) 
     for (int j = 0; j < SIZE; j++) 
      a[i][j] = (i == j); 
} 

//Multiply matrix a to matrix b and print result into a 
void mul(long a[SIZE][SIZE], long b[SIZE][SIZE]) 
{ 
    long res[SIZE][SIZE] = {{0}}; 

    for (int i = 0; i < SIZE; i++) 
     for (int j = 0; j < SIZE; j++) 
      for (int k = 0; k < SIZE; k++) 
      { 
       res[i][j] += a[i][k] * b[k][j]; 
      } 

    for (int i = 0; i < SIZE; i++) 
     for (int j = 0; j < SIZE; j++) 
      a[i][j] = res[i][j]; 
} 

//Caluclate a^n and print result into matrix res 
void pow(long a[SIZE][SIZE], long n, long res[SIZE][SIZE]) 
{ 
    one(res); 

    while (n > 0) { 
     if (n % 2 == 0) 
     { 
      mul(a, a); 
      n /= 2; 
     } 
     else { 
      mul(res, a); 
      n--; 
     } 
    } 
} 

Poniżej znaleźć odpowiednik dla liczb:

long power(long num, long pow) 
{ 
    if (pow == 0) return 1; 
    if (pow % 2 == 0) 
     return power(num*num, pow/2); 
    else 
     return power(num, pow - 1) * num; 
}