How to find when a matrix converges with a loop

前端 未结 1 1979
情书的邮戳
情书的邮戳 2021-01-26 12:36

I\'ve been given a 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,          


        
相关标签:
1条回答
  • 2021-01-26 13:26

    Actually, a much better way is to do this:

    ## 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, ]
      }
    

    Then when you call the function:

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

    The function stydis, essentially continuously does:

    P <- P %*% P0
    

    until convergence of P is reached. Convergence is numerically determined by the L1 norm of discrepancy matrix:

    sweep(P, 2, colMeans(P))
    

    The L1 norm is the maximum, absolute value of all matrix elements. When the L1 norm drops below 1e-16, convergence occurs.

    As you can see, convergence takes 71 steps. Now, we can obtain faster "convergence" by controlling tol (tolerance):

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

    But if you check:

    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
    

    Only the first 4 digits are the same, as you put tol = 1e-4.

    A floating point number has a maximum of 16 digits, so I would suggest you use tol = 1e-16 for reliable convergence test.

    0 讨论(0)
提交回复
热议问题