Module:AbsorbingMarkovChain

--- see https://en.wikipedia.org/wiki/Absorbing_Markov_chain

local p = {} local vector = require 'Module:Vector' local matrix = require 'Module:Matrix'

function p.CanonicalForm(P) local m=P.rows local n=P.columns local R = nil if m==n then local rowPermutationMatrix=matrix.id(m) local columnPermutationMatrix=matrix.id(m) local s		local t=P:copy local k=0 local ridx,cidx=t:find(1) while(ridx.size~=0) do			t=t:swap(ridx[ridx.size],m,1) rowPermutationMatrix=rowPermutationMatrix:swap(ridx[ridx.size],m,1) t=t:swap(cidx[cidx.size],n,2) columnPermutationMatrix=columnPermutationMatrix:swap(cidx[cidx.size],n,2) k=k+1 s=t:submatrix(1,1,m-k,n-k) ridx,cidx=s:find(1) end R={} R["rowPermutationMatrix"]=rowPermutationMatrix R["columnPermutationMatrix"]=columnPermutationMatrix R["r"]=k R["t"]=s.rows R["P"]=t R["Q"]=s R["R"]=t:submatrix(1,n-k+1,m-k,n) end return R end

function p.FundamentalMatrix(Q,t) local FI=matrix.id(t)-Q return FI:inverse end

function p.Properties(P) local canonical=p.CanonicalForm(P) local Q=canonical["Q"] local t=canonical["t"] local R=canonical["R"] local N=p.FundamentalMatrix(Q,t) local dgs=N:diagonals local dia={} dia[0]=dgs[0] local Ndg=matrix.diag(dia) local It=matrix.id(t) local N2=N*(2*Ndg-It)-matrix.Hadamard(N,N) local T=N*vector.ones(t) local stepsVariance=(2*N-It)*T-vector.Hadamard(T,T) local H=(N-It)*(Ndg:inverse) local B=N*R

canonical["stepsVariance"]=stepsVariance canonical["visitsVariance"]=N2 canonical["stepsNumber"]=T canonical["transientProbabilities"]=H canonical["absorbingProbabilities"]=B canonical["fundamentalMatrix"]=N return canonical end

return p