################################################################### #
# Script for Replication of: Consumers' Preference and Willingness to Pay
#                           For Biofortified Garri
# Description: The script to estimate full attendance mixed logit model for
## nutrition treatment
## Author: Akinwehinmi Titilayo
#################################################################### #

# ################################################################# #
#### LOAD LIBRARY AND DEFINE CORE SETTINGS                       ####
# ################################################################# #

### Clear memory
#rm(list = ls())

### Load Apollo library
check.packages <- function(pkg){
  new.pkg <- pkg[!(pkg %in% installed.packages()[, "Package"])]
  if (length(new.pkg))
    install.packages(new.pkg, dependencies = TRUE)
  sapply(pkg, require, character.only = TRUE)
}
packages <- c("apollo", "lmtest", "dplyr", "tidyr", "tibble", "skimr", "gtsummary", "segmented", "ggplot2", "tidyverse",
              "hrbrthemes", "viridis")
check.packages(packages)


### Initialise code
apollo_initialise()

### Set core controls
apollo_control = list(
  modelName       = "Nutrition_Full_Attendance_Model",
  modelDescr      = "Full Attendance Mixed logit model for Nutrition Treatment",
  indivID         = "id",  
  mixing          = TRUE, 
  nCores          = 7,
  analyticGrad    = TRUE, # Needs to be set explicitly for models with inter-intra draws (requires extra RAM).
  outputDirectory = "output"
)


# ################################################################# #
#### LOAD DATA AND APPLY ANY TRANSFORMATIONS                     ####
# ################################################################# #

### Loading data from package
### if data is to be loaded from a file (e.g. called data.csv), 
### the code would be: database = read.csv("data.csv",header=TRUE)

#apollo_database = read.csv("data_biofortification.csv",header=TRUE)
apollo_database = read.csv("data_biofortification.csv")

#Subset database for Nutrition Group
database <- subset(apollo_database, consumer==2)


# ################################################################# #
#### DEFINE MODEL PARAMETERS                                     ####
# ################################################################# #

### Vector of parameters, including any that are kept fixed in estimation
apollo_beta = c(
  
  b_price                 = 0,   #sigma_price_inter          = 0,
  asc3                    = 0,   sigma_asc3_inter           = 0,
  va                      = 0,   sigma_va_inter             = 0,
  iron25                  = 0,   sigma_iron25_inter         = 0,
  iron50                  = 0,   sigma_iron50_inter         = 0,
  lowstarch               = 0,   sigma_lowstarch_inter      = 0,
  gm                      = 0,   sigma_gm_inter             = 0,
  ge                      = 0,   sigma_ge_inter             = 0,
  
  
  # # Correlation in preferences within the control group
  sigma_va_iron25          = 0,        sigma_va_iron50      = 0,    sigma_va_lowstarch    = 0,
  sigma_va_gm              = 0,        sigma_va_ge          = 0,    sigma_iron25_iron50   = 0,
  sigma_iron25_lowstarch   = 0,        sigma_iron25_gm      = 0,    sigma_iron25_ge       = 0,
  sigma_iron50_lowstarch   = 0,        sigma_iron50_gm      = 0,    sigma_iron50_ge       = 0,
  sigma_lowstarch_gm       = 0,        sigma_lowstarch_ge   = 0,    sigma_gm_ge           = 0
  
  
)

### Vector with names (in quotes) of parameters to be kept fixed at their starting value in apollo_beta, use apollo_beta_fixed = c() if none
apollo_fixed = c()

### Overwrite beta starting values
#apollo_readBeta(apollo_beta, apollo_fixed, "Biofortification_July_WTP_Corr_ST_1", overwriteFixed = FALSE)
# ################################################################# #
#### DEFINE RANDOM COMPONENTS                                    ####
# ################################################################# #

### Set parameters for generating draws
apollo_draws = list(
  interDrawsType = "sobol",
  interNDraws    = 500,
  interUnifDraws = c("draws_price_inter", "draws_price_inter_a", "draws_price_inter_b"),
  interNormDraws = c(
    
    
    "draws_asc3_inter", "draws_va_inter", "draws_iron25_inter",
    "draws_iron50_inter", "draws_lowstarch_inter", 
    "draws_gm_inter", "draws_ge_inter",
    
    #draws for correlation 
    "draws_va_iron25" ,        "draws_va_iron50" ,    "draws_va_lowstarch"  ,
    "draws_va_gm"     ,        "draws_va_ge"     ,    "draws_iron25_iron50" ,
    "draws_iron25_lowstarch" , "draws_iron25_gm" ,    "draws_iron25_ge"     ,
    "draws_iron50_lowstarch" , "draws_iron50_gm" ,    "draws_iron50_ge"     ,
    "draws_lowstarch_gm" ,     "draws_lowstarch_ge" , "draws_gm_ge"        
    )
)

### Create random parameters
apollo_randCoeff = function(apollo_beta, apollo_inputs){
  randcoeff = list()
  
  #Triangular 
  #randcoeff[["b_price"]] =    (price + price*(draws_price_inter_a+draws_price_inter_b)/2)
  
  #randcoeff[["b_price"]] =    -exp(price + sigma_price_inter*draws_price_inter)
  
  randcoeff[["b_asc3"]] =    (asc3 + sigma_asc3_inter*draws_asc3_inter)
  
  randcoeff[["b_va"]] =    (va + sigma_va_inter*draws_va_inter)
  
  randcoeff[["b_iron25"]] =   (iron25 + sigma_iron25_inter*draws_iron25_inter +
                                 sigma_va_iron25*draws_va_iron25)
  
  randcoeff[["b_iron50"]] = (iron50 + sigma_iron50_inter*draws_iron50_inter +
                               sigma_va_iron50*draws_va_iron50 
                             + sigma_iron25_iron50*draws_iron25_iron50) 
  
  randcoeff[["b_lowstarch"]] = (lowstarch + sigma_lowstarch_inter*draws_lowstarch_inter + 
                                  sigma_va_lowstarch*draws_va_lowstarch + sigma_iron25_lowstarch*draws_iron25_lowstarch +
                                  sigma_iron50_lowstarch*draws_iron50_lowstarch)
  
  randcoeff[["b_gm"]] =  (gm + sigma_gm_inter*draws_gm_inter + sigma_va_gm*draws_va_gm +
                            sigma_iron25_gm*draws_iron25_gm + sigma_iron50_gm*draws_iron50_gm + 
                            sigma_lowstarch_gm*draws_lowstarch_gm)
  
  randcoeff[["b_ge"]] = (ge + sigma_ge_inter*draws_ge_inter + 
                           sigma_va_ge*draws_va_ge + sigma_iron25_ge*draws_iron25_ge + sigma_iron50_ge*draws_iron50_ge +
                           sigma_lowstarch_ge*draws_lowstarch_ge + sigma_gm_ge*draws_gm_ge)
  
  return(randcoeff)
}

# ################################################################# #
#### GROUP AND VALIDATE INPUTS                                   ####
# ################################################################# #

apollo_inputs = apollo_validateInputs()

# ################################################################# #
#### DEFINE MODEL AND LIKELIHOOD FUNCTION                        ####
# ################################################################# #

apollo_probabilities=function(apollo_beta, apollo_inputs, functionality="estimate"){
  
  ### Function initialisation: do not change the following three commands
  ### Attach inputs and detach after function exit
  apollo_attach(apollo_beta, apollo_inputs)
  on.exit(apollo_detach(apollo_beta, apollo_inputs))
  
  ### Create list of probabilities P
  P = list()
  
  ### List of utilities: these must use the same names as in mnl_settings, order is irrelevant
  V = list()
  V[["alt1"]] =  (b_price*Price1 + b_va*VAB1 + b_iron25*IRA1 + b_iron50*IRB1 + 
                    b_lowstarch*LowStarch1 + b_gm*GM1 + b_ge*GE1 )
  
  V[["alt2"]] = (b_price*Price2 + b_va*VAB2 + b_iron25*IRA2 + b_iron50*IRB2 + 
                   b_lowstarch*LowStarch2 + b_gm*GM2 + b_ge*GE2)
  
  V[["alt3"]] =  (b_price*Price3 + b_asc3*asc33)
  
  ### Define settings for MNL model component
  mnl_settings = list(
    alternatives  = c(alt1=1, alt2=2, alt3=3),
    avail         = list(alt1=1, alt2=1, alt3=1),
    choiceVar     = Choice,
    utilities     = V
  )
  
  ### Compute probabilities using MNL model
  P[["model"]] = apollo_mnl(mnl_settings, functionality)
  
  ### Average across intra-individual draws
  # P = apollo_avgIntraDraws(P, apollo_inputs, functionality)
  
  ### Take product across observation for same individual
  P = apollo_panelProd(P, apollo_inputs, functionality)
  
  ### Average across inter-individual draws
  P = apollo_avgInterDraws(P, apollo_inputs, functionality)
  
  ### Prepare and return outputs of function
  P = apollo_prepareProb(P, apollo_inputs, functionality)
  return(P)
}

# ################################################################# #
#### MODEL ESTIMATION                                            ####
# ################################################################# #

### optionally load pre-estimated model from memory
#model = apollo_loadModel("Biofortification_WTP_Stated_ANA_November_14_All_1A")
# apollo_addCovariance(model, apollo_inputs)
### Optional speedTest
# speedTest_settings=list(
#     nDrawsTry = c(100, 200, 500, 1000),
#     nCoresTry = 8,
#    nRep      = 10)
#  apollo_speedTest(apollo_beta, apollo_fixed, apollo_probabilities, apollo_inputs, speedTest_settings)

### Optional starting values search
# search_settings = list(
#   nCanditates = 10
# )
# apollo_beta=apollo_searchStart(apollo_beta, apollo_fixed,apollo_probabilities, apollo_inputs, search_settings)



model = apollo_estimate(apollo_beta, apollo_fixed,apollo_probabilities, apollo_inputs, estimate_settings=list(maxIterations=400))


# ################################################################# #
#### MODEL OUTPUTS                                               ####
# ################################################################# #

# ----------------------------------------------------------------- #
#---- FORMATTED OUTPUT (TO SCREEN)                               ----
# ----------------------------------------------------------------- #


apollo_modelOutput(model)

# ----------------------------------------------------------------- #
#---- FORMATTED OUTPUT (TO FILE, using model name)               ----
# ----------------------------------------------------------------- #


apollo_saveOutput(model)



# ################################################################# #
##### POST-PROCESSING                                            ####
# ################################################################# #

###Compute WTP from the Preference space estimates

deltaMethod_settings=list(expression=c(wtp_va="va/(-b_price)", wtp_iron25="iron25/(-b_price)", wtp_iron50="iron50/(-b_price)", wtp_lowstarch="lowstarch/(-b_price)", wtp_gm="gm/(-b_price)", wtp_ge="ge/(-b_price)",
                                       wtp_sd_va="sigma_va_inter/(-b_price)", wtp_sd_iron25="sigma_iron25_inter/(-b_price)", wtp_sd_iron50="sigma_iron50_inter/(-b_price)", 
                                       wtp_sd_lowstarch="sigma_lowstarch_inter/(-b_price)", wtp_sd_gm="sigma_gm_inter/(-b_price)", wtp_sd_ge="sigma_ge_inter/(-b_price)"))
wtp_nutrition <- apollo_deltaMethod(model, deltaMethod_settings)
write.csv(wtp_nutrition, "wtp_nutrition.csv")
