https://github.com/cran/HLSM
Raw File
Tip revision: 281f55f9f8ae3be814d154729507a7fb494e8a92 authored by Tracy Sweet on 06 December 2021, 12:00:02 UTC
version 0.9.0
Tip revision: 281f55f
HLSM_run.R
####Function to run the sampler#####
##SPECIFYING PRIORS######
#########################
##if priors = NULL => uses randomly generated priors
##else: priors is a list of following objects:
##MuBeta:= prior mean for betas & intercepts;
##SigmaBeta:= prior variance for betas & intercept;
##MuAlpha:= prior mean for alpha;
##SigmaAlpha:= prior variance for alpha;
##MuZ; VarZ;
##PriorA; PriorB
##TUNING PARAMETERS#######
##########################
##if tune = NULL => uses auto tuning
##else: tune is a list of following objects:
##tuneAlpha = 0.9
##tuneBeta = array, dim=c(PP,KK)
##tuneInt = vec, len = KK
##tuneZ =  list( vec(len = nn[x]])) length of list = KK
##############################################################
#library(MASS)

HLSMrandomEF = function(Y,
                        edgeCov = NULL,
                        receiverCov = NULL,
                        senderCov = NULL,
                        FullX = NULL,
                        initialVals = NULL,
                        priors = NULL,
                        tune = NULL,
                        tuneIn = TRUE,
                        dd=2,
                        niter)
{

  #X and Y are provided as list.
  if (class(Y) != 'list') {
    if (dim(Y)[2] != 4) {
      stop('Invalid data structure type')
    }
  }

#  if (class(Y) == 'list' &
#      class(Y[[1]]) != 'matrix' &
#      class(Y[[1]]) != 'data.frame') {
#    stop('Invalid data structure type')
#  }

  if (class(Y) == 'list') {
    KK = length(Y)
    if (dim(Y[[1]])[1] == dim(Y[[1]])[2]) {
      nn = sapply(1:length(Y), function(x)
        nrow(Y[[x]]))
      nodenames = lapply(1:length(Y), function(x)
          rownames(Y[[x]]))
      if(sum(sapply(nodenames, is.null))>=1){nodenames=lapply(1:length(Y), function(x) 1:dim(Y[[x]])[1])}
    }

    if (dim(Y[[1]])[1] != dim(Y[[1]])[2] & dim(Y[[1]])[2] == 4) {
      nn = sapply(1:length(Y), function(x)
        length(unique(c(
          Y[[x]]$Receiver, Y[[x]]$Sender
        ))))
      nodenames = lapply(1:length(Y), function(x)
        unique(c(Y[[x]]$Receiver, Y[[x]]$Sender)))
    }
  }

  if (class(Y) != 'list') {
    if (dim(Y)[2] == 4) {
      nid = unique(Y$id)
      KK = length(nid)
      nn = rep(0, KK)
      df.list = list()
      nodenames = list()
      for (k in 1:KK) {
        df.sm = Y[which(Y$id == nid[k],),]
        nn[k] = length(unique(c(df.sm$Receiver, df.sm$Sender)))
        nodenames[[k]] = unique(c(df.sm$Receiver, df.sm$Sender))
        df.list[[k]] = array(0, dim = c(nn[k], nn[k]))
        dimnames(df.list[[k]])[[1]] = dimnames(df.list[[k]])[[2]] = nodenames[[k]]
        for (i in 1:dim(df.sm)[1]) {
          df.list[[k]][paste(df.sm$Sender[i]), paste(df.sm$Receiver[i])] = df.sm$Outcome[i]  #assume undirected graph and missing items are zeros
        }
      }
      Y = df.list
    }
  }


  ##prepare covariates#####
  #########################
  noCOV = FALSE
  if (!is.null(FullX) &
      !is.null(edgeCov) &
      !is.null(receiverCov) &
      !is.null(senderCov))
    (stop('FullX cannot be used when nodal or edge covariates are provided'))

  if (is.null(FullX) &
      is.null(edgeCov) & is.null(receiverCov) & is.null(senderCov)) {
    X = lapply(1:KK, function(x)
      array(0, dim = c(nn[x], nn[x], 1)))
    noCOV = TRUE
  }

  if (is.null(FullX)) {
    if (!is.null(edgeCov) | !is.null(senderCov) | !is.null(receiverCov)) {
      if (!is.null(edgeCov)) {
        if (class(edgeCov) != 'data.frame') {
          stop('edgeCov must be of class data.frame')
        }
        X1 = getEdgeCov(edgeCov, nn, nodenames)
      } else
        (X1 = NULL)
      if(!is.null(senderCov)){
        if(class(senderCov) != 'data.frame'){
          stop('senderCov must be of class data.frame')}
        X2 = getSenderCov(senderCov, nn,nodenames)
      }else(X2 = NULL)


      if(!is.null(receiverCov)){
        if(class(receiverCov) != 'data.frame'){
          stop('receiverCov must be of class data.frame')}
        X3 = getReceiverCov(receiverCov, nn,nodenames)
      }else(X3 = NULL)

      X = lapply(1:KK, function(x){if(!is.null(X1)&!is.null(X2)&!is.null(X3)){
        ncov = dim(X1[[x]])[3]+dim(X2[[x]])[3]+dim(X3[[x]])[3];
        df = array(0, dim = c(nn[x],nn[x],ncov));
        df[,,1:dim(X1[[x]])[3]] = X1[[x]];
        df[,,(dim(X1[[x]])[3]+1):(dim(X1[[x]])[3]+dim(X2[[x]])[3])] = X2[[x]];
        df[,,(dim(X1[[x]])[3]+dim(X2[[x]])[3]+1):(dim(X1[[x]])[3]+dim(X2[[x]])[3]+dim(X3[[x]])[3])] = X3[[x]] };
        if(!is.null(X1)&!is.null(X2) & is.null(X3)){
          ncov = dim(X1[[x]])[3]+dim(X2[[x]])[3];
          df = array(0, dim = c(nn[x],nn[x],ncov));
          df[,,1:dim(X1[[x]])[3]] = X1[[x]];
          df[,,(dim(X1[[x]])[3]+1):(dim(X1[[x]])[3]+dim(X2[[x]])[3])] = X2[[x]]};
        if(!is.null(X1)&!is.null(X3)&is.null(X2)){
          ncov = dim(X1[[x]])[3]+dim(X3[[x]])[3];
          df = array(0, dim = c(nn[x],nn[x],ncov));
          df[,,1:dim(X1[[x]])[3]] = X1[[x]];
          df[,,(dim(X1[[x]])[3]+1):(dim(X1[[x]])[3]+dim(X3[[x]])[3])] = X3[[x]]};
        if(!is.null(X2)&!is.null(X3)&is.null(X1)){
          ncov = dim(X2[[x]])[3]+dim(X3[[x]])[3];
          df = array(0, dim = c(nn[x],nn[x],ncov));
          df[,,1:dim(X2[[x]])[3]] = X2[[x]];
          df[,,(dim(X2[[x]])[3]+1):(dim(X2[[x]])[3]+dim(X3[[x]])[3])] = X3[[x]]};
        if(!is.null(X1)& is.null(X2)& is.null(X3)){
          df = X1[[x]] };
        if(is.null(X1)& !is.null(X2)& is.null(X3)){
          df = X2[[x]] };
        if(is.null(X1)& is.null(X2)& !is.null(X3)){
          df = X3[[x]] };
        return(df) } )
    }
  }
  if (!is.null(FullX))
    X = FullX

  PP = dim(X[[1]])[3]
  XX = unlist(X)
  YY = unlist(Y)
  YY[which(is.na(YY))] = 0
  XX[which(is.na(XX))] = 0

  #Priors

  if (is.null(priors)) {
    MuBeta = rep(0, (PP + 1))
    VarBeta = rep(1, (PP + 1))
    MuZ = c(0, 0)
    VarZ = c(20, 20)
    PriorA = 100
    PriorB = 150
  } else{
    if (class(priors) != 'list')
      (stop("priors must be of class list, if not NULL"))
    MuBeta = priors$MuBeta
    VarBeta = priors$VarBeta
    MuZ = priors$MuZ
    VarZ = priors$VarZ
    PriorA = priors$PriorA
    PriorB = priors$PriorB
  }
  ##starting values
  ##Initialization of the latent positions
  ##first do MDS on the observed network
  ##then center it
  ##Procrustean transformation of latent positions
  C = lapply(1:KK, function(tt) {
    diag(nn[tt]) - (1 / nn[tt]) * array(1, dim = c(nn[tt], nn[tt]))
  })
  Z0 = lapply(1:KK, function(tt) {
    g = graph.adjacency(Y[[tt]])

    ss = shortest.paths(g)

    ss[ss > 4] = 4

    Z0 = cmdscale(ss, k = dd)

    dimnames(Z0)[[1]] = dimnames(YY[[tt]])[[1]]

    return(Z0)
  })
  Z00 = lapply(1:KK, function(tt)
    C[[tt]] %*% Z0[[tt]])


  if (is.null(initialVals)) {
    # 	Z0 = list()
    #         for(i in 1:KK){
    #             ZZ = t(replicate(nn[i],rnorm(dd,0,sqrt(10))))
    #             ZZ[1,]=c(1,0)
    #             ZZ[2,2]=0
    #             if(ZZ[2,1] < ZZ[1,1]){
    #                 ZZ[2,1] = -1*(ZZ[2,1]-ZZ[1,1])+1}
    #             ZZ[3,2] = abs(ZZ[3,2])
    #             Z0[[i]] = ZZ
    #         }
    Z0 = unlist(Z00)
    beta0 = replicate(KK, rnorm(PP, 0, 1))
    intercept0  = rnorm(KK, 0, 1)

    print("Starting Values Set")
  } else{
    if (class(initialVals) != 'list')
      (stop("initialVals must be of class list, if not NULL"))
    Z0 = initialVals$ZZ
    beta0 = initialVals$beta
    intercept0 = initialVals$intercept
}


  ###tuning parameters#####
  if (is.null(tune)) {
    a.number = 5
    tuneBeta = array(1, dim = c(PP, KK))
    tuneInt = rep(0.2, KK)
    tuneZ =  lapply(1:KK, function(x)
      rep(1.2, nn[x]))
  } else{
    if (class(tune) != 'list')
      (stop("tune must be of class list, if not NULL"))
    a.number = 1
    tuneBeta = tune$tuneBeta
    tuneInt = tune$tuneInt
    tuneZ = tune$tuneZ
  }

  ###Tuning the Sampler####
  do.again = 1
  tuneX = 1
  if (tuneIn == TRUE) {
    while (do.again == 1) {
      print('Tuning the Sampler')
      for (counter in 1:a.number) {
        rslt = MCMCfunction(
          nn = nn,
          PP = PP,
          KK = KK,
          dd = dd,
          XX = XX,
          YY = YY,
          ZZ = Z0,
          beta = beta0 ,
          intercept = intercept0,
          MuBeta = MuBeta,
          SigmaBeta = VarBeta,
          MuZ = MuZ,
          VarZ = VarZ,
          tuneBetaAll = tuneBeta,
          tuneInt = tuneInt,
          tuneZAll = unlist(tuneZ),
          niter = 200,
          PriorA = PriorA,
          PriorB = PriorB
        )

        tuneZ = lapply(1:KK, function(x)
          adjust.my.tune(tuneZ[[x]], rslt$acc$Z[[x]], 2))
        tuneBeta = array(sapply(1:KK, function(x)
          adjust.my.tune(tuneBeta[, x], rslt$acc$beta[, x], 1)), dim = c(PP, KK))
        tuneInt = sapply(1:KK, function(x)
          adjust.my.tune(tuneInt[x], rslt$acc$intercept[x], 1))
        print(paste('TuneDone = ', tuneX))
        tuneX = tuneX + 1
      }
      extreme = lapply(1:KK, function(x)
        which.suck(rslt$acc$Z[[x]], 2))
      do.again = max(sapply(extreme, length)) > 5

    }
    print("Tuning is finished")
  }
  rslt = MCMCfunction(
    nn = nn,
    PP = PP,
    KK = KK,
    dd = dd,
    XX = XX,
    YY = YY,
    ZZ = Z0,
    beta = beta0 ,
    intercept = intercept0,
    MuBeta = MuBeta,
    SigmaBeta = VarBeta,
    MuZ = MuZ,
    VarZ = VarZ,
    tuneBetaAll = tuneBeta,
    tuneInt = tuneInt,
    tuneZAll = unlist(tuneZ),
    niter = niter,
    PriorA = PriorA,
    PriorB = PriorB
  )
  
  ##Procrutes transformation on the final draws of the latent positions
  ##
  Ztransformed = lapply(1:niter, function(ii) {
    lapply(1:KK,
           function(tt) {
             z = rslt$draws$ZZ[[ii]][[tt]]
             
             z = C[[tt]] %*% z
             
             pr = t(Z00[[tt]]) %*% z
             
             ssZ = svd(pr)
             tx = ssZ$v %*% t(ssZ$u)
             zfinal = z %*% tx
             return(zfinal)
           })
  })
  rslt$draws$ZZ = Ztransformed
  
  rslt$call = match.call()
  if (noCOV == TRUE) {
    rslt$tune = list(tuneZ = tuneZ, tuneInt = tuneInt)
    rslt$draws$Beta = NA
  }

 
  if (noCOV == FALSE) {
    rslt$tune = list(tuneBeta = tuneBeta,
                     tuneZ = tuneZ,
                     tuneInt = tuneInt)
  }

  
  class(rslt) = 'HLSM'
  rslt
}
back to top