2016-07-01 8 views
0

Ich habe eine Matrix gegeben worden:Wie zu finden, wenn eine Matrix mit einer Schleife konvergiert

P <- matrix(c(0, 0, 0, 0.5, 0, 0.5, 0.1, 0.1, 0, 0.4, 0, 0.4, 0, 0.2, 0.2, 0.3, 0, 0.3, 0, 0, 0.3, 0.5, 0, 0.2, 0, 0, 0, 0.4, 0.6, 0, 0, 0, 0, 0, 0.4, 0.6), nrow = 6, ncol = 6, byrow = TRUE) 

die Funktionen verwenden, mpow, rows_equal, matrices_equal. Ich möchte herausfinden, wenn P^n konvergiert, mit anderen Worten, was n ist, wenn alle Zeilen in der Matrix gleich sind und wenn P^n = P^(n+1).

Durch nur Blick auf die Funktionen i haben es geschafft zu schließen, dass um n=19-21 die Matrix konvergieren wird.

Obwohl ich die richtige n mit einer Schleife finden wollen. Hier sind die Funktionen mpow, rows_equal und matrices_equal. Ich weiß, dass sie anders geschrieben werden können, aber behalte sie so, wie sie sind.

mpow <- function(P, n, d=4) { 
    if (n == 0) diag(nrow(P))) 
    else if (n== 1) P 
    else P %*% mpow(P, n - 1)) 
    } 

rows_equal <- function(P, d = 4) { 
    P_new <- trunc(P * 10^d) 
    for (k in 2:nrow(P_new)) { 
    if (!all(P_new[1, ] == P_new[k, ])) { 
     return(FALSE)} 
     } 
    return(TRUE) 
    } 

matrices_equal <- function(A, B, d = 4) { 
    A_new <- trunc(A * 10^d) 
    B_new <-trunc(B * 10^d) 
    if (all(A_new == B_new)) TRUE else FALSE 
    } 

Nun, die Schleife zu schreiben, sollten wir es etwas entlang der Linien von tun:

Zuerst eine Funktion wie so erstellen:

when_converged <- function(P) {...} 

und

for (n in 1:50) 

Um zu versuchen, wenn t.ex n = 50.

Obwohl ich nicht weiß, wie man den Code richtig schreibt, kann mir dann jemand helfen?

Vielen Dank für das Lesen meiner Frage.

+0

Nun, ich möchte herausfinden, wenn P konvergiert mit den Funktionen mpow, rows_equal und matrices_equal. Mein Lehrer gab den Ratschlag, dass wir eine Funktion machen könnten, die eine Matrix P als Eingabe nimmt und uns zeigt, für welches n, P^n = P^n + 1. Das sollten wir beispielsweise mit einer Schleife wie "for (n in 1:50)" machen. – PeterNiklas

+0

Fügen Sie Ihrem Code Zeilenumbrüche hinzu. Es ist nicht lesbar. Ich nehme an, dass Sie "Konvergenz" als Gleichheit definieren bis zu der Genauigkeit, die durch "d" gesteuert wird? Sie wissen wahrscheinlich, dass Konvergenz bewiesen werden muss und nicht wirklich durch eine numerische Übung gezeigt werden kann. – Roland

+0

Was wissen Sie über die Matrix? Ist es z.B. quadratisch und symmetrisch? Siehe [hier] (http://www.statmethods.net/advstats/matrix.html). – Christoph

Antwort

2

Eigentlich ein viel besserer Weg, dies zu tun:

## transition probability matrix 
P <- matrix(c(0, 0, 0, 0.5, 0, 0.5, 0.1, 0.1, 0, 0.4, 0, 0.4, 0, 0.2, 0.2, 0.3, 0, 0.3, 0, 0, 0.3, 0.5, 0, 0.2, 0, 0, 0, 0.4, 0.6, 0, 0, 0, 0, 0, 0.4, 0.6), nrow = 6, ncol = 6, byrow = TRUE) 

## a function to find stationary distribution 
stydis <- function(P, tol = 1e-16) { 
    n <- 1; e <- 1 
    P0 <- P ## transition matrix P0 
    while(e > tol) { 
    P <- P %*% P0 ## resulting matrix P 
    e <- max(abs(sweep(P, 2, colMeans(P)))) 
    n <- n + 1 
    } 
    cat(paste("convergence after",n,"steps\n")) 
    P[1, ] 
    } 

Dann, wenn Sie die Funktion aufrufen:

stydis(P) 
# convergence after 71 steps 
# [1] 0.002590674 0.025906736 0.116580311 0.310880829 0.272020725 0.272020725 

Die Funktion stydis, im Wesentlichen kontinuierlich tut:

P <- P %*% P0 

bis Konvergenz von P erreicht ist. Konvergenz wird numerisch durch die Norm L1 der Diskrepanz Matrix bestimmt:

sweep(P, 2, colMeans(P)) 

Die L1-Norm ist der maximale, absolute Wert aller Matrixelemente. Wenn die L1-Norm unter 1e-16 fällt, tritt eine Konvergenz auf.

Wie Sie sehen können, dauert die Konvergenz 71 Schritte. Jetzt können wir schneller „Konvergenz“ erhalten durch Steuern tol (Toleranz):

stydis(P, tol = 1e-4) 
# convergence after 17 steps 
# [1] 0.002589361 0.025898057 0.116564506 0.310881819 0.272068444 0.271997814 

Aber wenn Sie überprüfen:

mpow(P, 17) 
#    [,1]  [,2]  [,3]  [,4]  [,5]  [,6] 
# [1,] 0.002589361 0.02589806 0.1165645 0.3108818 0.2720684 0.2719978 
# [2,] 0.002589415 0.02589722 0.1165599 0.3108747 0.2720749 0.2720039 
# [3,] 0.002589738 0.02589714 0.1165539 0.3108615 0.2720788 0.2720189 
# [4,] 0.002590797 0.02590083 0.1165520 0.3108412 0.2720638 0.2720515 
# [5,] 0.002592925 0.02592074 0.1166035 0.3108739 0.2719451 0.2720638 
# [6,] 0.002588814 0.02590459 0.1166029 0.3109419 0.2720166 0.2719451 

Nur die ersten vier Ziffern sind die gleichen, wie Sie tol = 1e-4 setzen.

Eine Gleitkommazahl hat maximal 16 Stellen. Daher würde ich Ihnen empfehlen, tol = 1e-16 für einen zuverlässigen Konvergenztest zu verwenden.

+0

Hey! Vielen Dank für Ihre Antwort, ich sehe jetzt, dass ich nicht geschrieben habe, dass wir finden sollten, wenn die Matrix mit 4 Dezimalstellen konvergiert. Muss ich dafür den Code trotzdem ändern? – PeterNiklas

+0

Okej, gut, danke für deine Antwort! Es war eine große Hilfe. Ich habe eine Frage zu "Tol = 1e-4" Die Sache ist ja die ersten 4 Dezimalstellen sind alle gleich. jedoch aussehen, wenn wir zum Beispiel am 4. kolumn: finden wir: 0,3108412 und 0,3108615 Wenn gerundet nach oben/unten zu 4 Ziffern des oberen 0,3108 und die unteren 0,3109 wird. Das ist nicht das Gleiche. Gibt es eine Möglichkeit zu sehen, ob sie gleich 4 Dezimalstellen sind, wenn das Aufwärmen/Absenken enthalten ist? – PeterNiklas

+0

Hallo wieder, Ihre Antwort war sehr nützlich. Ich frage mich jedoch, gibt es eine Möglichkeit, eine Schleife mit der Funktion zu erstellen, die ich am Anfang abgeleitet habe, mpow, rows_equal und matrices_equal? Ich möchte eine Schleife erstellen, die das n ausspuckt, wenn P konvergiert ist. Unter was habe ich versucht, können Sie mir helfen, was fehlt, um es richtig zu machen? when_converged <- Funktion (P) für (n in 1:50) {A <- mpow (P, n) B <- mpow (P, n + 1)} {wenn rows_equal (mpow (P, n), 4) und matrices_equal (A, B, 4) zurück (n)} – PeterNiklas

Verwandte Themen