2014-04-15 12 views
5

trzeba kod funkcji w C++, który skutecznie znajdzie współczynników Taylor Seria danej funkcji wymiernej (P (x)/P (x)).Najlepszy algorytm rozszerzania seryjnej funkcji wymiernej

Parametry funkcji będą potęgą wielomianów (równe w nominatorze i mianowniku), dwiema tablicami o współczynnikach wielomianów i liczbą terminów w ekspansji.

Mój pomysł był następujący. Rozważmy tożsamość

P(x)/Q(x) = R(x) + ... 

Gdzie R(x) jest wielomianem o liczbie równych pod względem liczby współczynników muszę znaleźć. Wtedy mogę pomnożyć obie strony z Q(x) i dostać

P(x) = R(x) * Q(x) 

R(x) * Q(x) - P(x) = 0 

Dlatego wszystkie współczynniki powinny być zero. Jest to układ równań, które mają rozwiązać algorytm. O (n^3) nie jest tak szybki, jak chciałem.

Czy istnieje szybszy algorytm?

wiem, że współczynniki serii są zadowalające zależność liniowa nawrót. To powoduje, że myślę, że algorytm jest możliwy (O (n)).

+0

@ DavidEisenstat Dzięki, to upraszcza zadanie. Ale jak mogę znaleźć '1/Q (x)' z długim podziałem? Myślałem, że z podziałem znajduję tylko iloraz i pozostałość. – Somnium

+0

@DavidEisenstat Dzięki! Unikanie separacji przyspieszy również rzeczy, ponieważ mnożenie będzie wynosiło * O (n * m) *, gdzie n - liczba terminów, m - stopień. Nawiasem mówiąc, nie rozumiem, dlaczego moja odpowiedź jest oznaczona jako zbyt szeroka, że ​​wymaga jednego określonego algorytmu. – Somnium

+0

@DavidEisenstat Idź tam :) Może powinniśmy rozpocząć temat o stanie [algorytmu] na meta. Jest zdecydowanie kilka ogólnych decyzji, które należy podjąć, aby przesłać te pytania do CS –

Odpowiedz

5

Algorytm że mam zamiar opisać jest uzasadniony matematycznie przez formal power series. Każda funkcja z serią Taylora ma formalną serię mocy. Odwrotność nie jest prawdą, ale jeśli wykonamy arytmetykę funkcji z serią Taylora i otrzymamy funkcję z serią Taylora, to możemy wykonać tę samą arytmetykę z formalną serią mocy i uzyskać tę samą odpowiedź.

Długa algorytm podziału dla formalnego szeregu potęgowego jest jak algorytm long division abyście nauczyli się w szkole. Pokażę to na przykładzie (1 + 2 x)/(1 - x - x^2), który ma współczynniki równe Lucas numbers.

Mianownik musi mieć niezerową stałą termin. Zaczynamy od napisania licznika, który jest pierwszym pozostałym.

   -------- 
1 - x - x^2) 1 + 2 x 

[ dzielimy określenie resztkowych najniższy rzędu (1) przez stałą perspektywie mianowniku'S (1) i umieścić iloraz się do góry.

   1 
      -------- 
1 - x - x^2) 1 + 2 x 

Teraz mnożymy 1 - x - x^2 przez 1 i odjąć go od prądu różnicowego.

   1 
      -------- 
1 - x - x^2) 1 + 2 x 
       1 - x - x^2 
       ------------- 
        3 x + x^2 

Zrób to jeszcze raz.

   1 + 3 x 
      -------- 
1 - x - x^2) 1 + 2 x 
       1 - x - x^2 
       --------------- 
        3 x + x^2 
        3 x - 3 x^2 - 3 x^3 
        ------------------- 
         4 x^2 + 3 x^3 

I znowu.

   1 + 3 x + 4 x^2 
      ---------------- 
1 - x - x^2) 1 + 2 x 
       1 - x - x^2 
       --------------- 
        3 x + x^2 
        3 x - 3 x^2 - 3 x^3 
        ------------------- 
         4 x^2 + 3 x^3 
         4 x^2 - 4 x^3 - 4 x^4 
         --------------------- 
           7 x^3 + 4 x^4 

I znowu.

   1 + 3 x + 4 x^2 + 7 x^3 
      ------------------------ 
1 - x - x^2) 1 + 2 x 
       1 - x - x^2 
       --------------- 
        3 x + x^2 
        3 x - 3 x^2 - 3 x^3 
        ------------------- 
         4 x^2 + 3 x^3 
         4 x^2 - 4 x^3 - 4 x^4 
         --------------------- 
           7 x^3 + 4 x^4 
           7 x^3 - 7 x^4 - 7 x^4 
           --------------------- 
             11 x^4 + 7 x^5 

poszczególne przegrody były trochę nudny ponieważ stosowane dzielnik z czołową 1, ale jeśli stosuje się, na przykład, 2 - 2 x - 2 x^2, to wszystkie współczynniki w iloraz będzie podzielona przez 2.

+0

Dzięki, to bardzo pomaga! Wszystkie ekspansje, które chciałem znaleźć, mają współczynniki całkowite, co prawdopodobnie gwarantuje, że współczynnik wiodący będzie wynosił 1. – Somnium

1

Jeśli przyjrzysz się bliżej systemowi, który uzyskasz ze swoim planem, zobaczysz, że jest już przekątna i nie wymaga rozwiązania O (n^3). Po prostu degeneruje się rekursji liniowa (P [] Q [], R [] są współczynnikami odpowiednich wielomianów):

R[0] = P[0]/Q[0] 
R[n] = (P[n] - sum{0..n-1}(R[i] * Q[n-i]))/Q[0] 

Ponieważ Q jest wielomianem suma nie ma więcej niż deg(Q) warunki (tym samym przyjmując stały czas na obliczenie), co sprawia, że ​​ogólna złożoność jest asymptotycznie liniowa. Możesz także spojrzeć na reprezentację macierzy rekurencji dla (możliwie) lepszego asymptotyka.

+0

Jest on liniowy dla jednej wartości R (i), jednak dla wszystkich wartości R (0), ..., R (n) staje się * O (n^2) * – Somnium

+0

Nie. Stałoby się O (n^2), gdyby Q miał nieskończoną liczbę współczynników. Suma nie ma więcej określeń niż deg (Q), więc obliczenie zajmuje stały czas. Będę edytować moją odpowiedź - jest niejasna. Dzięki. – user58697

+0

Następnie staje się O (n * q), gdzie q - stopień Q. Wydaje się taki sam jak w przyjętym poście. – Somnium

1

Można to zrobić w O(n log n) czasie arbitralnego P i Q stopnia n. Dokładniej można to zrobić w M(n), gdzie M(n) jest złożonością multiplikacji wielomianowej, która sama może być wykonana w O(n log n).

Po pierwsze, pierwsze rozszerzenia serii można zobaczyć po prostu jako wielomian stopnia n-1.

Załóżmy, że interesują Cię pierwsze warunki rozszerzenia serii n o rozszerzenie serii o P(x)/Q(x). Istnieje algorytm, który obliczy odwrotność czasu Q w M(n), jak zdefiniowano powyżej.

Odwrócony T(x) z Q(x) spełnia T(x) * Q(x) = 1 + O(x^N). To znaczy. T(x) * Q(x) to dokładnie 1 oraz pewne pojęcie błędu, którego współczynniki występują po pierwszych terminach n, którymi jesteśmy zainteresowani, więc możemy je po prostu upuścić.

Teraz P(x)/Q(x) jest po prostu P(x) * T(x) co jest kolejnym mnożnikiem wielomianu.

Możesz znaleźć implementację, która oblicza wspomnianą odwrotność w mojej bibliotece open source Altruct. Zobacz plik series.h. Zakładając, że masz już metodę, która oblicza iloczyn dwóch polinomials, kod, który oblicza odwrotność, ma długość około 10 linii (wariant dziel i rządź).

Rzeczywisty algorytm wygląda następująco: Załóżmy Q(x) = 1 + a1*x + a2*x^2 + .... Jeśli a0 nie jest 1, można po prostu podzielić Q(x), a później jego odwrotną T(x) z a0. Załóżmy, że na każdym etapie masz warunki odwrotne, aby Q(x) * T_L(x) = 1 + x^L * E_L(x) dla niektórych błędów E_L(x). Początkowo T_1(X) = 1. Jeśli podłączysz to w powyższym, otrzymasz Q(x) * T_1(x) = Q(x) = 1 + x^1 * E_1(x) dla niektórych E_1(x), co oznacza, że ​​dotyczy to L=1. Teraz podwójmy L w każdym kroku. Możesz uzyskać E_L(x) z poprzedniego kroku jako E_L(x) = (Q(x) * T_L(x) - 1)/x^L, lub pod względem implementacji, po prostu upuść pierwsze współczynniki L produktu. Następnie można obliczyć T_2L(x) z poprzedniego kroku jako T_2L(x) = T_L(x) - x^L * E_L(x) * T_L(x). Błąd będzie następujący: E_2L(x) = - E_L(x)^2.Sprawdźmy teraz, czy krok indukcyjny się utrzymuje.

Q(x) * T_2L(x) 
= Q(x) * (T_L(x) - x^L * E_L(x) * T_L(x)) 
= Q(x) * T_L(x) * (1 - x^L * E_L(x)) 
= (1 + x^L * E_L(x)) * (1 - x^L * E_L(x)) 
= 1^2 - (x^L * E_L(x))^2 
= 1 + x^2L * E_2L(x) 

Q.E.D.

jestem pewien, że nie jest możliwe, aby obliczyć wielomian podział bardziej wydajny niż mnożenia, a jak widać w poniższej tabeli, ten algorytm jest tylko 3 razy wolniej niż jednym mnożenia:

n  mul  inv  factor 
10^4  24 ms  80 ms 3,33x 
10^5  318 ms  950 ms 2,99x 
10^6 4.162 ms 12.258 ms 2,95x 
10^7 101.119 ms 294.894 ms 2,92x 
Powiązane problemy