library(reticulate)Introduction to Continuous Time Markov Chains
from symbulate import *
from matplotlib import pyplot as pltSeagull
Q = [[-1, 0.4, 0.6],
[0.8 / 3, -1 / 3, 0.2 / 3],
[0.9 / 5, 0.1 / 5, -1 / 5]]
pi0 = [1, 0, 0]
states = [1, 2, 3]
X = ContinuousTimeMarkovChain(Q, pi0, states)plt.figure();
X.sim(1).plot()
plt.show();
plt.figure();
X.sim(3).plot()
plt.show();
plt.figure();
X[1 / 60].sim(10000).plot()
plt.show();
plt.figure();
X[0.5].sim(10000).plot()
plt.show();
plt.figure();
X[1].sim(10000).plot()
plt.show();
plt.figure();
X[5].sim(10000).plot()
plt.show();
plt.figure();
X[60].sim(10000).plot()
plt.show();
Times between jumps
P = ContinuousTimeMarkovChainProbabilitySpace(Q, pi0, states)
W = RV(P, interarrival_times)plt.figure();
W[0].sim(10000).plot()
plt.show();
plt.figure();
W[1].sim(10000).plot()
plt.show();
plt.figure();
(W[0] & W[1]).sim(10000).plot()
plt.show();
A few paths from scratch
states = 1:3 # state space
pi0 = c(1, 0, 0) # initial distribution
P = rbind(
c(0, 0.6, 0.4),
c(0.8, 0, 0.2),
c(0.9, 0.1, 0)
) # transition matrix of embedded DTMC
lambda = c(1, 1 / 3, 1 / 5) # transition rates for each state
Nruns = 3 # number of paths to simulate
Njump = 10 # number of transitions to sim for each path
Xt = matrix(rep(NA, Nruns * (Njump + 1)), nrow = Njump + 1) # +1 to include time 0
Wn = Xt
for (r in 1:Nruns){
Xt[1, r] = sample(states, 1, prob = pi0) # initial state
Wn[1, r] = 0 # time 0
for (n in 2:(Njump+1)){
Tn = rexp(1) / lambda[Xt[n - 1, r]] # time between jumps, exp(lambda_i)
Xt[n, r] = sample(states, 1, prob = P[Xt[n - 1, r], ]) # new state
Wn[n,r] = Wn[n - 1, r] + Tn # time of nth jump
}
}
# Plot the paths
Npaths = Nruns
plotadj = c(0, -.1, .1)
plot(range(Wn),
range(states)+range(plotadj),
type = 'n',
ylab = "X(t)", xlab = "t",
main = paste(Npaths," paths of a CTMC"))
colors = c("black","orange","skyblue")
for (r in 1:Npaths){
segments(y0 = Xt[-(Njump + 1), r] + plotadj[r],
x0 = Wn[-(Njump + 1), r],
y1 = Xt[-(Njump + 1), r] + plotadj[r],
x1 = Wn[-1, r], col = colors[r], lty = r, lwd = 2)
points(Wn[, r], Xt[,r] + plotadj[r], pch = 16, col = colors[r])
points(Wn[-1, r], Xt[-(Njump + 1), r] + plotadj[r], col = colors[r])
}
M/M/1 Queue: Sample Path
lambda = 0.2
mu = 0.5
n_jumps = 20
X_t = rep(NA, n_jumps + 1)
T_n = rep(NA, n_jumps + 1)
X_t[1] = 0
T_n[1] = 0
for (n in 2:n_jumps){
if (X_t[n - 1] == 0){
T_n[n] = T_n[n - 1] + rexp(1) / lambda
X_t[n] = X_t[n - 1] + 1
} else {
T_n[n] = T_n[n - 1] + rexp(1) / (lambda + mu)
X_t[n] = X_t[n - 1] + sample(c(-1, 1), 1, prob = c(mu, lambda))
}
}
plot(T_n, X_t,
type = "s",
xlab = "t", ylab = "X(t)",
main = "Sample path of M/M/1 queue")
M/M/s Queue: Sample path
lambda = 2.3
mu = 0.5
s = 5
n_jumps = 20
X_t = rep(NA, n_jumps + 1)
W_n = rep(NA, n_jumps + 1)
X_t[1] = 0
W_n[1] = 0
for (n in 2:n_jumps){
W_n[n] = W_n[n - 1] + rexp(1) / (lambda + mu * min(s, X_t[n - 1]))
X_t[n] = X_t[n - 1] + sample(c(-1, 1), 1,
prob = c(mu * min(s, X_t[n - 1]), lambda))
}
plot(W_n, X_t,
type = "s",
xlab = "t", ylab = "X(t)",
main = paste("Sample path of M/M/s queue with s = ", s))