library ("metRology")
## 
## Attaching package: 'metRology'
## The following objects are masked from 'package:base':
## 
##     cbind, rbind

1 Using Midpoint Rule to Compute Marginal Likelihood of t distribution

## the function for computing log likelihood of normal data
log_lik <- function(x,mu,w,df=Inf)
{   sum(dt.scaled(x,df,mu,exp(w),log=TRUE))
}

## the function for computing log prior
log_prior <- function(mu,w, mu_0,sigma_mu,w_0,sigma_w)
{   dnorm(mu,mu_0,sigma_mu,log=TRUE) + dnorm(w,w_0,sigma_w,log=TRUE)
}

## the function for computing the unormalized log posterior 
## given transformed mu and w 
log_post_tran <- function(x, mu_t, w_t, mu_0,sigma_mu,w_0,sigma_w, df=Inf)
{
    #log likelihood
    log_lik(x,logi(mu_t), logi(w_t),df) +
    #log prior 
    log_prior(logi(mu_t), logi(w_t), mu_0,sigma_mu,w_0,sigma_w) + 
    #log derivative of transformation
    log_der_logi(mu_t) + log_der_logi(w_t)
}

## the logistic function for transforming (0,1) value to (-inf,+inf)
logi <- function(x)
{  log(x) - log(1-x)
}

## the log derivative of logistic function 
log_der_logi <- function(x)
{  -log(x) - log(1-x)
}

## the generic function for approximating 1-D integral with midpoint rule
## the logarithms of the function values are passed in
## the log of the integral result is returned

## log_f  --- a function computing the logarithm of the integrant function
## range  --- the range of integral varaible, a vector of two elements
## n      --- the number of points at which the integrant is evaluated
## ...    --- other parameters needed by log_f
log_int_mid <- function(log_f, range, n,...)
{   if(range[1] >= range[2]) 
        stop("Wrong ranges")
    h <- (range[2]-range[1]) / n
    v_log_f <- sapply(range[1] + (1:n - 0.5) * h, log_f,...)
    log_sum_exp(v_log_f) + log(h)       
}

## a function computing the sum of numbers represented with logarithm
## lx     --- a vector of numbers, which are the log of another vector x.
## the log of sum of x is returned
log_sum_exp <- function(lx)
{   mlx <- max(lx)
    mlx + log(sum(exp(lx-mlx)))
}

## a function computing the normalization constant
log_marlik_mid <- function(x,mu_0,sigma_mu,w_0,sigma_w, n, df=Inf)
{
    ## function computing the normalization constant of with mu_t fixed
    log_int_gaussian_mu <- function(mu_t)
    {   log_int_mid(log_f=log_post_tran,range=c(0,1),n=n,
                    x=x,mu_t=mu_t,mu_0=mu_0,sigma_mu=sigma_mu,
                    w_0=w_0,sigma_w=sigma_w, df=df)
    }
    
    log_int_mid(log_f=log_int_gaussian_mu,range=c(0,1), n=n)
}

## we use Monte Carlo method to debug the above function
log_marlik_mc <- function(x,mu_0,sigma_mu,w_0,sigma_w,iters_mc, df=Inf)
{
    ## draw samples from the priors
    mus <- rnorm(iters_mc,mu_0,sigma_mu)
    ws <- rnorm(iters_mc,w_0,sigma_w)
    one_log_lik <- function(i)
    {  log_lik(x,mus[i],ws[i], df)
    }
    v_log_lik <- sapply(1:iters_mc,one_log_lik)
    log_sum_exp(v_log_lik) - log(iters_mc)
}

2 Test with simulated datasets

2.1 Checking the accuracy of numerical quadrature

## [1] -171.4239
## [1] -171.4012

Another test

## [1] -219.7842
## [1] -219.8334
## n =  10 , Estimated Log Marginal Likelihood = -221.0623 
## n =  20 , Estimated Log Marginal Likelihood = -219.781 
## n =  30 , Estimated Log Marginal Likelihood = -219.8175 
## n =  40 , Estimated Log Marginal Likelihood = -219.783 
## n =  50 , Estimated Log Marginal Likelihood = -219.7842 
## n =  60 , Estimated Log Marginal Likelihood = -219.7842 
## n =  70 , Estimated Log Marginal Likelihood = -219.7842 
## n =  80 , Estimated Log Marginal Likelihood = -219.7842 
## n =  90 , Estimated Log Marginal Likelihood = -219.7842

2.2 Comparing log marginal likelihoods of different models

2.2.3 A Case when numerical quadrature fails

## [1] -535.1336
## [1] -369.4429

What has gone wrong? The inverse-logistic transformation maps most points between (0,1) to the region around 0.5. But the likelihood function has its mode around 50!