TABLE OF CONTENTS
MetropolisHastings/mh.bdm [ Functions ]
NAME
mh.bdm --- RJMCMC for Birth-death-move steps
FUNCTION
This function handles the reversible-jump MCMC steps for adding, removing, or moving knots in the adaptive knot selection procedure. It can work with either the hazard or frailty curve.
SYNOPSIS
2896 mh.bdm <- function(which, hazard, frailty, regression)
INPUTS
which string, can be either "hazard" or "frailty" hazard RCurve for hazard frailty RCurve for frailty regression RRegression structure
OUTPUTS
curve updated RCurve for either hazard or frailty
SOURCE
2899 { 2900 # get all the needed components 2901 if(which == "hazard") curve <- hazard 2902 if(which == "frailty") curve <- frailty 2903 if(!curve$hasspline) return(curve); 2904 knots <- curve$spline.knots 2905 ord <- curve$spline.ord 2906 params <- curve$spline.par 2907 nknots <- curve$spline.nknots 2908 candknots <- curve$spline.candknots 2909 ncandknots <- curve$spline.ncandknots 2910 occ <- attr(candknots, "occupied") 2911 occind <- which(occ == 1) 2912 # evaluate the prior probability of k knots, k+1 knots, and k-1 knots 2913 pk <- nknotsPrior(nknots, curve) 2914 pkp1 <- if(nknots < curve$spline.maxoccknots) nknotsPrior(nknots + 1, curve) else 0 2915 pkm1 <- if(nknots > 1) nknotsPrior(nknots - 1, curve) else 0 2916 # compute probability of birth, death and move steps 2917 pb <- curve$spline.bdmconst * min(1, pkp1 / pk) # P(birth) 2918 pd <- curve$spline.bdmconst * min(1, pkm1 / pk) # P(death) 2919 pm <- max(0, 1 - pb - pd) # P(move) 2920 u <- runif(1) 2921 if(curve$name == "hazard") 2922 baselik <- mklik.spline.haz(curve$spline.par, hazard, frailty, regression) 2923 if(curve$name == "frailty") 2924 baselik <- mklik.spline.frail(curve$spline.par, hazard, frailty, regression) 2925 if(u < pd){ 2926 # Death step 2927 j <- sample(1:nknots, 1) + ord # index of dying knot 2928 x <- knots[j] 2929 #cat("Remove knot ", j, " at ", knots[j], "(occ", occ[occind[j - ord]], ")\n") 2930 knots2 <- knots 2931 params2 <- params 2932 knots2 <- knots2[ - j] # remove the knot 2933 # update parameters symetrically to birth step 2934 params2 <- params2[ - (j - 1)] 2935 if(ord > 2) for(j2 in (j - ord + 1):(j - 2)){ 2936 r2 <- (x - knots2[j2]) / (knots2[j2 + ord - 1] - knots2[j2]) 2937 inner <- 1 / r2 *exp(params2[j2]) - (1 - r2) / r2 * exp(params2[j2 - 1]) 2938 if(inner > 0) params2[j2] <- log(inner) else params2[j2] <- curve$spline.min 2939 } 2940 attr(knots2, "boundary") <- attr(knots, "boundary") 2941 attr(knots2, "order") <- attr(knots, "order") 2942 attr(knots2, "index") <- 1:(nknots - 1) - ord 2943 # create a temporary curve that is identical to the original, except for 2944 # the spline.knots and spline.params components 2945 temp <- curve 2946 temp$spline.knots <- knots2 2947 temp$spline.nknots <- nknots - 1 2948 occ2 <- occ; occ2[occind[j - ord]] <- 0 2949 attr(temp$spline.candknots, "occupied") <- occ2 2950 # Compute the spline basis of the temp curve 2951 temp <- makesplinebasis(temp) 2952 # Jacobian of the transformation 2953 J <- exp(params2[j - 1]) / (exp(params[j - 1]) - exp(params[j - 2])) 2954 if(ord > 2) for(j2 in (j - ord + 2):(j - 2)) { 2955 r2 <- (x - knots2[j2]) / (knots2[j2 + ord - 1] - knots2[j2]) 2956 J <- J * exp(params2[j2]) / (r2 * exp(params[j2])) 2957 } 2958 # candidate likelihood 2959 if(curve$name == "hazard") { 2960 temp <- updatespline(temp, params2) 2961 candlik <- mklik.spline.haz(temp$spline.par, temp, frailty, regression) 2962 } 2963 if(curve$name == "frailty"){ 2964 # for the frailty, adjust the mean to make sure it is 1 2965 newmean <- exp(params2)%*%temp$spline.basisexp - 2966 exp(params2[j - 2]) * temp$spline.basisexp[j - 2] 2967 newinner <- -newmean / temp$spline.basisexp[j - 2] 2968 if(newinner < 0){ 2969 candlik<- -Inf 2970 }else{ 2971 params2[j - 2] <- log(newinner) 2972 temp <- updatespline(temp, params2) 2973 candlik <- mklik.spline.frail(temp$spline.par, hazard, temp, regression) 2974 } 2975 } 2976 # compute acceptance ratio, and accept-reject 2977 ratio <- sqrt(2 * pi * curve$spline.priorvar) * abs(J) 2978 acc <- acceptreject(baselik, candlik, ratio) 2979 #cat("Lik: ", baselik, candlik, J, ratio, acc, "\n") 2980 if(any(knots2[(ord + 1):(length(knots2) - ord)] != candknots[occ2 == 1])) browser() 2981 if(acc) return(temp) else return(curve) 2982 } 2983 2984 if(u > pd & u < pd + pb){ 2985 # Birth of a knot 2986 params <- curve$spline.par 2987 # choose an unoccupied candidate knot location at random 2988 birthind <- occind[1] 2989 while(occ[birthind] > 0) birthind <- floor(runif(1, 1, ncandknots + 1)) + ord 2990 # get the position and interval of candidate knot 2991 x <- candknots[birthind] 2992 i <- findInterval(x, knots) 2993 #cat("Birth at ", x, " after knot ", i, "\n"); 2994 # Compute new knots and parameters 2995 knots2 <- c(knots[1:i], x, knots[(i + 1):length(knots)]) 2996 attr(knots2, "boundary") <- attr(knots, "boundary") 2997 attr(knots2, "order") <- attr(knots, "order") 2998 attr(knots2, "index") <- 1:(nknots + 1) - ord 2999 params2 <- c(params[1:(i - ord + 1)], 0, params[(i - ord + 2):length(params)]) 3000 # Even though it is possible to add a knot non-destructively, we need to generate 3001 # another random number to maintain dimension matching and detailed balance 3002 for(i2 in (i - ord + 2):i){ 3003 r2 <- (x - knots[i2]) / (knots[i2 + ord - 1] - knots[i2]) 3004 if(i2 == i) r2 <- runif(1) 3005 params2[i2] <- log(r2 * exp(params[i2]) + (1 - r2) * exp(params[i2 - 1])) 3006 } 3007 # Create a temp curve with new knots and params 3008 temp <- curve 3009 temp$spline.knots <- knots2 3010 temp$spline.nknots <- nknots + 1 3011 occ2 <- occ; occ2[birthind] <- 1 3012 attr(temp$spline.candknots, "occupied") <- occ2 3013 temp <- makesplinebasis(temp) 3014 # Jacobian of the transformation 3015 J <- (exp(params[i]) - exp(params[i - 1])) / exp(params2[i]) 3016 if(ord > 2) for(i2 in (i - ord + 2):(i - 1)) { 3017 r2 <- (x - knots[i2]) / (knots[i2 + ord - 1] - knots[i2]) 3018 J <- J * r2 * exp(params[i2]) / exp(params2[i2]) 3019 } 3020 if(curve$name == "hazard") { 3021 temp <- updatespline(temp, params2) 3022 candlik <- mklik.spline.haz(temp$spline.par, temp, frailty, regression) 3023 } 3024 if(curve$name == "frailty"){ 3025 # adjust frailty mean 3026 newmean <- exp(params2)%*%temp$spline.basisexp - exp(params2[i]) * 3027 temp$spline.basisexp[i] 3028 newinner <- -newmean / temp$spline.basisexp[i] 3029 if(newinner < 0){ 3030 candlik<- -Inf 3031 }else{ 3032 params2[i] <- log(newinner) 3033 temp <- updatespline(temp, params2) 3034 candlik <- mklik.spline.frail(temp$spline.par, hazard, temp, regression) 3035 } 3036 } 3037 # acceptance ratio 3038 ratio <- 1 / sqrt(2 * pi * curve$spline.priorvar) * abs(J) 3039 acc <- acceptreject(baselik, candlik, ratio) 3040 #cat("Lik: ", baselik, candlik, J, ratio, acc, "\n") 3041 if(any(knots2[(ord + 1):(length(knots2) - ord)] != candknots[occ2 == 1])) browser() 3042 if(acc) return(temp) else return(curve) 3043 3044 } 3045 3046 if(u > pd + pb) { 3047 # Move a knot 3048 # choose a random knot to move 3049 moveind <- floor(runif(1, 1, nknots + 1)) 3050 # compute the range of candidate knot indices to which the knot can be moved 3051 leftknotind <- if(moveind == 1) ord + 1 else occind[moveind - 1] + 1 3052 rightknotind <- if(moveind == nknots) ncandknots + ord else occind[moveind + 1] - 1 3053 newknotind <- floor(runif(1, leftknotind, rightknotind + 1)) 3054 oldknotind <- occind[moveind] 3055 #cat("Moveind: ", moveind, "\n"); 3056 #cat("Old / New: ", candknots[oldknotind], candknots[newknotind], "\n"); 3057 if(newknotind == oldknotind) return(curve) 3058 # create new knots and parameters 3059 knots2 <- knots 3060 params2 <- params 3061 knots2[moveind + ord] <- candknots[newknotind] 3062 # update occupied knot indices 3063 occ2 <- occ 3064 occ2[newknotind] <- 1 3065 occ2[occind[moveind]] <- 0 3066 if(sum(occ == 1) < nknots) browser() 3067 if(any(diff(knots2) < 0)) browser() 3068 if(any(knots2[(ord + 1):(length(knots2) - ord)] != candknots[occ2 == 1])) browser() 3069 temp <- curve 3070 temp$spline.knots <- knots2 3071 attr(temp$spline.candknots, "occupied") <- occ2 3072 # update the spline basis 3073 temp <- makesplinebasis(temp) 3074 if(curve$name == "hazard") { 3075 candlik <- mklik.spline.haz(params2, temp, frailty, regression) 3076 } 3077 if(curve$name == "frailty"){ 3078 # adjust frailty mean 3079 newmean <- exp(params2)%*%temp$spline.basisexp - exp(params2[moveind + ord]) * 3080 temp$spline.basisexp[moveind + ord] 3081 newinner <- -newmean / temp$spline.basisexp[moveind + ord] 3082 if(newinner < 0){ 3083 candlik<- -Inf 3084 }else{ 3085 params2[moveind + ord] <- log(newinner) 3086 temp <- updatespline(temp, params2) 3087 candlik <- mklik.spline.frail(params2, hazard, temp, regression) 3088 } 3089 } 3090 acc <- acceptreject(baselik, candlik, 1) 3091 #cat("Lik: ", baselik, candlik, acc, "\n") 3092 if(acc) return(temp) else return(curve) 3093 } 3094 3095 }