## ---- include = FALSE--------------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, eval = FALSE, comment = "#>" ) set.seed(100) # to make it reproducible options(rmarkdown.html_vignette.check_title = FALSE) ## ----setup-------------------------------------------------------------------- # library(ppdiag) # library(rstan) # library(cmdstanr) # library(tidyverse) # library(bayesplot) ## ----mmpp-stan-code----------------------------------------------------------- # mmpp_stan_code <- " # data{ # int num_events; //maximum of number of events for each pair each window => max(unlist(lapply(return_df$event.times,length)))) # vector[num_events+1] time_matrix; // include termination time in the last entry # } # parameters{ # real lambda0; //baseline rate for each pair # real c; //baseline rate for each pair # real w1; //CTMC transition rate # real w2; //CTMC transition rate # } # transformed parameters{ # real q1; # real q2; # q1 = (lambda0).*w1; # q2 = (lambda0).*w2; # } # model{ # real integ; // Placeholder variable for calculating integrals # row_vector[2] forward[num_events]; // Forward variables from forward-backward algorithm # row_vector[2] forward_termination; # row_vector[2] probs_1[num_events+1]; // Probability vector for transition to state 1 (active state) # row_vector[2] probs_2[num_events+1]; // Probability vector for transition to state 2 (inactive state) # vector[num_events+1] interevent; # # //priors # c ~ lognormal(0,1); # w1 ~ beta(0.5,0.5); # w2 ~ beta(0.5,0.5); # # lambda0 ~ gamma(1, 1); # interevent = time_matrix; # // ---- prepare for forward algorithm # // --- log probability of Markov transition logP_ij(t) # for(n in 1:(num_events + 1)){ # probs_1[n][1] = log(q2/(q1+q2)+q1/(q1+q2)*exp(-(q1+q2)*interevent[n])); //1->1 # probs_2[n][2] = log(q1/(q1+q2)+q2/(q1+q2)*exp(-(q1+q2)*interevent[n])); //2->2 # probs_1[n][2] = log1m_exp(probs_2[n][2]); //2->1 # probs_2[n][1] = log1m_exp(probs_1[n][1]); //1->2 # } # //consider n = 1 # integ = interevent[1]*lambda0; # forward[1][1] = log_sum_exp(probs_1[1]) + log(lambda0*(1+c)) - integ*(1+c); # forward[1][2] = log_sum_exp(probs_2[1]) + log(lambda0) - integ; # # if(num_events>1){ # for(n in 2:num_events){ # integ = interevent[n]*lambda0; # forward[n][1] = log_sum_exp(forward[n-1] + probs_1[n]) + log(lambda0*(1+c))- integ*(1+c); # forward[n][2] = log_sum_exp(forward[n-1] + probs_2[n]) + log(lambda0) - integ; # } # } # # integ = interevent[num_events]*lambda0; # forward_termination[1] = log_sum_exp(forward[num_events] + probs_1[num_events]) - integ*(1+c); # forward_termination[2] = log_sum_exp(forward[num_events] + probs_2[num_events]) - integ; # # target += log_sum_exp(forward_termination); # } # " # ## ----mmhp-stan-code----------------------------------------------------------- # mmhp_stan_code <- " # data{ # int num_events; //number of events # vector[num_events+1] time_matrix; // include termination time as last entry # } # parameters{ # real lambda0; //baseline rate for each pair # real w_lambda; # real w_q1; //CTMC transition rate # real w_q2; // # real alpha; # real beta_delta; # real delta_1; // P(initial state = 1) # } # transformed parameters{ # real lambda1; # real q1; # real q2; # row_vector[2] log_delta; # real beta; # lambda1 = (lambda0).*(1+w_lambda); # q2 = (lambda0).*w_q2; # q1 = (lambda0).*w_q1; # log_delta[1] = log(delta_1); # log_delta[2] = log(1-delta_1); # beta = alpha*(1+beta_delta); # } # model{ # real integ; // Placeholder variable for calculating integrals # row_vector[2] forward[num_events]; // Forward variables from forward-backward algorithm # row_vector[2] forward_termination; // Forward variables at termination time # row_vector[2] probs_1[num_events+1]; // Probability vector for transition to state 1 (active state) # row_vector[2] probs_2[num_events+1]; // Probability vector for transition to state 2 (inactive state) # row_vector[2] int_1[num_events+1]; // Integration of lambda when state transit to 1 (active state) # row_vector[2] int_2[num_events+1]; // Integration of lambda when state transit to 2 (inactive state) # real R[num_events+1]; // record variable for Hawkes process # vector[num_events+1] interevent; # real K0; # real K1; # real K2; # real K3; # real K4; # real K5; # //priors # w_lambda ~ gamma(1,1); # alpha ~ gamma(1,1);//lognormal(0,1); # beta_delta ~ lognormal(0,2);//normal(0,10); # //delta_1 ~ beta(2,2); # w_q1 ~ beta(2,2); # w_q2 ~ beta(2,2); # # # lambda0 ~ gamma(1,1); # interevent = time_matrix; # if(num_events==0){ // there is no event occured in this period # //--- prepare for forward calculation # probs_1[1][1] = log(q2/(q1+q2)+q1/(q1+q2)*exp(-(q1+q2)*interevent[1])); //1->1 # probs_2[1][2] = log(q1/(q1+q2)+q2/(q1+q2)*exp(-(q1+q2)*interevent[1])); //2->2 # probs_1[1][2] = log1m_exp(probs_2[1][2]); //2->1 # probs_2[1][1] = log1m_exp(probs_1[1][1]); //1->2 # R[1] = 0; # K0 = exp(-(q1+q2)*interevent[1]); # K1 = (1-exp(-(q1+q2)*interevent[1]))/(q1+q2); # K2 = (1-exp(-(q1+q2)*interevent[1]))/(q1+q2); # int_1[1][1] = ((q2^2*lambda1+q2*q1*lambda0)*interevent[1] + # (q1^2*lambda1+q2*q1*lambda0)*K0*interevent[1] + # (lambda1-lambda0)*q2*q1*K1 + (lambda1-lambda0)*q2*q1*K2)/(q1+q2)^2/exp(probs_1[1][1]); //1->1 # int_1[1][2] = ((q2^2*lambda1+lambda0*q1*q2)*interevent[1] - # (lambda1*q1*q2+lambda0*q2^2)*K0*interevent[1] + # (lambda0-lambda1)*q2^2*K1 + (lambda1-lambda0)*q1*q2*K2)/(q1+q2)^2/exp(probs_1[1][2]); //2->1 # int_2[1][1] = ((q1*q2*lambda1+q1^2*lambda0)*interevent[1] - # (q1^2*lambda1+q1*q2*lambda0)*K0*interevent[1] + # (lambda1-lambda0)*q1^2*K1 + q1*q2*(lambda0-lambda1)*K2)/(q1+q2)^2/exp(probs_2[1][1]); //1->2 # int_2[1][2] = ((q1*q2*lambda1+lambda0*q1^2)*interevent[1] + # (q1*q2*lambda1+lambda0*q2^2)*K0*interevent[1] + # (lambda0-lambda1)*q1*q2*K1 + (lambda0-lambda1)*q1*q2*K2)/(q1+q2)^2/exp(probs_2[1][2]); //2->2 # # forward_termination[1] = log_sum_exp(log_delta + probs_1[1] - int_1[1]); # forward_termination[2] = log_sum_exp(log_delta + probs_2[1] - int_2[1]); # target += log_sum_exp(forward_termination); # //target += -lambda0*interevent[1]*delta_1-lambda1*interevent[1]*(1-delta_1); # }else{ // there is event occured # // ---- prepare for forward algorithm # // --- log probability of Markov transition logP_ij(t) # for(n in 1:(num_events + 1)){ //changed this # probs_1[n][1] = log(q2/(q1+q2)+q1/(q1+q2)*exp(-(q1+q2)*interevent[n])); //1->1 # probs_2[n][2] = log(q1/(q1+q2)+q2/(q1+q2)*exp(-(q1+q2)*interevent[n])); //2->2 # probs_1[n][2] = log1m_exp(probs_2[n][2]); //2->1 # probs_2[n][1] = log1m_exp(probs_1[n][1]); //1->2 # } # # // --- R for Hawkes # R[1] = 0; # for(n in 2:(num_events + 1)){ // and this # R[n] = exp(-beta*interevent[n])*(R[n-1]+1); # } # # // Integration of lambda # for(n in 1:(num_events)){ //and this # K0 = exp(-(q1+q2)*interevent[n]); # K1 = (1-exp(-(q1+q2)*interevent[n]))/(q1+q2); # K2 = (1-exp(-(q1+q2)*interevent[n]))/(q1+q2); # K3 = R[n]*(exp(beta*interevent[n])-1)/beta; # K4 = R[n]*(1-exp(-(beta+q1+q2)*interevent[n]))*exp(beta*interevent[n])/(beta+q1+q2); # K5 = R[n]*(1-exp(-(q1+q2-beta)*interevent[n]))/(q1+q2-beta); # int_1[n][1] = ((q2^2*lambda1+q2*q1*lambda0)*interevent[n] + # (q1^2*lambda1+q2*q1*lambda0)*K0*interevent[n] + # (lambda1-lambda0)*q2*q1*K1 + (lambda1-lambda0)*q2*q1*K2 + # alpha*K3*(q2^2+q1^2*K0) + # alpha*q1*q2*K4 + alpha*q1*q2*K5)/(q1+q2)^2/exp(probs_1[n][1]); //1->1 # int_1[n][2] = ((q2^2*lambda1+lambda0*q1*q2)*interevent[n] - # (lambda1*q1*q2+lambda0*q2^2)*K0*interevent[n] + # (lambda0-lambda1)*q2^2*K1 + (lambda1-lambda0)*q1*q2*K2 + # alpha*q2*K3*(q2-q1*K0) - # alpha*q2^2*K4 + alpha*q1*q2*K5)/(q1+q2)^2/exp(probs_1[n][2]); //2->1 # int_2[n][1] = ((q1*q2*lambda1+q1^2*lambda0)*interevent[n] - # (q1^2*lambda1+q1*q2*lambda0)*K0*interevent[n] + # (lambda1-lambda0)*q1^2*K1 + q1*q2*(lambda0-lambda1)*K2 + # alpha*q1*K3*(q2-q1*K0) + # alpha*q1^2*K4 - alpha*q2*q1*K5)/(q1+q2)^2/exp(probs_2[n][1]); //1->2 # int_2[n][2] = ((q1*q2*lambda1+lambda0*q1^2)*interevent[n] + # (q1*q2*lambda1+lambda0*q2^2)*K0*interevent[n] + # (lambda0-lambda1)*q1*q2*K1 + (lambda0-lambda1)*q1*q2*K2 + # alpha*q1*q2*K3*(1+K0) - # alpha*q1*q2*K4 - alpha*q1*q2*K5)/(q1+q2)^2/exp(probs_2[n][2]); //2->2 # } # # //consider n = 1 # forward[1][1] = log(lambda1) + log_sum_exp(probs_1[1]-int_1[1]+log_delta); # forward[1][2] = log(lambda0) + log_sum_exp(probs_2[1]-int_2[1]+log_delta); # # if(num_events>1){ # for(n in 2:num_events){ # forward[n][1] = log_sum_exp(forward[n-1] + probs_1[n] - int_1[n]) + log(lambda1+alpha*R[n]); # forward[n][2] = log_sum_exp(forward[n-1] + probs_2[n] - int_2[n]) + log(lambda0); # } # } # # forward_termination[1] = log_sum_exp(forward[num_events] + probs_1[num_events] - int_1[num_events]); # forward_termination[2] = log_sum_exp(forward[num_events] + probs_2[num_events] - int_2[num_events]); # // lots of places with max_Nm and Nm got rid of the +1 # target += log_sum_exp(forward_termination); # } # } # " # ## ----sim-mmpp----------------------------------------------------------------- # Q <- matrix(c(-0.4, 0.4, 0.2, -0.2), ncol = 2, byrow = TRUE) # mmpp_obj <- pp_mmpp(Q = Q, lambda0 = 1, c = 1.5, delta = c(1/3, 2/3)) # # sim_mmpp <- pp_simulate(mmpp_obj, n = 50) ## ----rstan-mmpp--------------------------------------------------------------- # mmpp_data <- list(num_events = length(sim_mmpp$events) - 1, # # as first event is start time (0) # time_matrix = diff(c(sim_mmpp$events, sim_mmpp$end)) # #interevent arrival time # ) # # mmpp_rstan <- stan(model_code = mmpp_stan_code, # data = mmpp_data, # chains = 2) # mmpp_sim <- rstan::extract(mmpp_rstan) ## ----mmpp-plot---------------------------------------------------------------- # bayesplot::mcmc_hist(as.matrix(mmpp_rstan), pars = c("lambda0", "c")) ## ----mmpp-post---------------------------------------------------------------- # mmpp_post <- lapply(mmpp_sim, mean) ## ----sim-mmhp----------------------------------------------------------------- # Q <- matrix(c(-0.4, 0.4, 0.2, -0.2), ncol = 2, byrow = TRUE) # mmhp_obj <- pp_mmhp(Q = Q, lambda0 = 0.5, lambda1 = 1.5, # alpha = 0.5, beta = 0.75, delta = c(1/3, 2/3)) # # sim_mmhp <- pp_simulate(mmhp_obj, n = 50) # # # mmhp_data <- list(num_events = length(sim_mmhp$events) - 1, # # as first event is start time (0) # time_matrix = diff(c(sim_mmhp$events, sim_mmhp$end)) # #interevent arrival time # ) ## ----rstan-mmhp--------------------------------------------------------------- # mmhp_rstan <- stan(model_code = mmhp_stan_code, # data = mmhp_data, # chains = 2) # mmhp_sim <- rstan::extract(mmhp_rstan) # mmhp_post <- lapply(mmhp_sim, mean) ## ----plot-draws-mmhp---------------------------------------------------------- # bayesplot::mcmc_hist(as.matrix(mmhp_rstan), # pars = c("lambda0", "lambda1", "alpha", "beta")) ## ----mmpp-fit, eval=FALSE----------------------------------------------------- # mmpp_file <- write_stan_file(mmpp_stan_code) # mmpp_stan <- cmdstan_model(stan_file = mmpp_file) # # fit_mmpp <- mmpp_stan$sample(data = mmpp_data, # seed = 123, # chains = 4, # parallel_chains = 4, # refresh = 500) ## ----compile-mmhp, eval=FALSE------------------------------------------------- # mmhp_file <- write_stan_file(mmhp_stan_code) # mmhp_stan <- cmdstan_model(stan_file = mmhp_file) # # fit_mmhp <- mmhp_stan$sample(data = mmhp_data, # seed = 123, # chains = 4, # parallel_chains = 4, # refresh = 500) ## ----mmpp-ppdiag, fig.width=8------------------------------------------------- # mmpp_fit_obj <- pp_mmpp(lambda0 = mmpp_post$lambda0, # c = mmpp_post$c, # Q = matrix( c(-mmpp_post$q1, # mmpp_post$q1, # mmpp_post$q2, # -mmpp_post$q2), # nrow = 2, ncol = 2, byrow = T) ) # # # pp_diag(mmpp_fit_obj, events = sim_mmpp$events) # ## ----mmhp-ppdiag, fig.width=8------------------------------------------------- # mmhp_fit_obj <- pp_mmhp(lambda0 = mmhp_post$lambda0, # lambda1 = mmhp_post$lambda1, # alpha = mmhp_post$alpha, # beta = mmhp_post$beta, # Q = matrix( c(-mmhp_post$q1, # mmhp_post$q1, # mmhp_post$q2, # -mmhp_post$q2), # nrow = 2, ncol = 2, byrow = T) ) # # pp_diag(mmhp_fit_obj, events = sim_mmhp$events) #