init_fn <- function(num_particles) rnorm(num_particles, 0, 1)
transition_fn <- function(particles) particles + rnorm(length(particles))
log_likelihood_fn <- function(y, particles) {
dnorm(y, mean = particles, sd = 1, log = TRUE)
}
# Define a simple random-walk Metropolis move function
move_fn <- function(particle, y) {
proposal <- particle + rnorm(1, 0, 0.1)
log_p_current <- log_likelihood_fn(y = y, particles = particle)
log_p_proposal <- log_likelihood_fn(y = y, particles = proposal)
if (log(runif(1)) < (log_p_proposal - log_p_current)) {
return(proposal)
} else {
return(particle)
}
}
y <- cumsum(rnorm(50)) # Dummy data
num_particles <- 100
result <- resample_move_filter(
y = y,
num_particles = num_particles,
init_fn = init_fn,
transition_fn = transition_fn,
log_likelihood_fn = log_likelihood_fn,
move_fn = move_fn
)
plot(result$state_est,
type = "l", col = "blue", main = "RMPF State Estimates",
ylim = range(c(result$state_est, y))
)
points(y, col = "red", pch = 20)
# With parameters
init_fn <- function(num_particles) rnorm(num_particles, 0, 1)
transition_fn <- function(particles, mu) {
particles + rnorm(length(particles), mean = mu)
}
log_likelihood_fn <- function(y, particles, sigma) {
dnorm(y, mean = particles, sd = sigma, log = TRUE)
}
move_fn <- function(particle, y, sigma) {
proposal <- particle + rnorm(1, 0, 0.1)
log_p_curr <- log_likelihood_fn(y = y, particles = particle, sigma = sigma)
log_p_prop <- log_likelihood_fn(y = y, particles = proposal, sigma = sigma)
if (log(runif(1)) < (log_p_prop - log_p_curr)) {
return(proposal)
} else {
return(particle)
}
}
y <- cumsum(rnorm(50))
num_particles <- 100
result <- resample_move_filter(
y = y,
num_particles = num_particles,
init_fn = init_fn,
transition_fn = transition_fn,
log_likelihood_fn = log_likelihood_fn,
move_fn = move_fn,
mu = 1,
sigma = 1
)
plot(result$state_est,
type = "l", col = "blue", main = "RMPF with Parameters",
ylim = range(c(result$state_est, y))
)
points(y, col = "red", pch = 20)
# With observation gaps
simulate_ssm <- function(num_steps, mu, sigma) {
x <- numeric(num_steps)
y <- numeric(num_steps)
x[1] <- rnorm(1, mean = 0, sd = sigma)
y[1] <- rnorm(1, mean = x[1], sd = sigma)
for (t in 2:num_steps) {
x[t] <- mu * x[t - 1] + sin(x[t - 1]) + rnorm(1, mean = 0, sd = sigma)
y[t] <- x[t] + rnorm(1, mean = 0, sd = sigma)
}
y
}
data <- simulate_ssm(10, mu = 1, sigma = 1)
obs_times <- c(1, 2, 3, 5, 6, 7, 8, 9, 10) # skip t=4
data_obs <- data[obs_times]
init_fn <- function(num_particles) rnorm(num_particles, 0, 1)
transition_fn <- function(particles, mu) {
particles + rnorm(length(particles), mean = mu)
}
log_likelihood_fn <- function(y, particles, sigma) {
dnorm(y, mean = particles, sd = sigma, log = TRUE)
}
move_fn <- function(particle, y, sigma) {
proposal <- particle + rnorm(1, 0, 0.1)
log_p_cur <- log_likelihood_fn(y = y, particles = particle, sigma = sigma)
log_p_prop <- log_likelihood_fn(y = y, particles = proposal, sigma = sigma)
if (log(runif(1)) < (log_p_prop - log_p_cur)) {
return(proposal)
} else {
return(particle)
}
}
result <- resample_move_filter(
y = data_obs,
num_particles = 100,
init_fn = init_fn,
transition_fn = transition_fn,
log_likelihood_fn = log_likelihood_fn,
move_fn = move_fn,
obs_times = obs_times,
mu = 1,
sigma = 1
)
plot(result$state_est,
type = "l", col = "blue", main = "RMPF with Observation Gaps",
ylim = range(c(result$state_est, data))
)
points(data_obs, col = "red", pch = 20)
Run the code above in your browser using DataLab