I am afraid the CNL model cannot use different alphas across individuals, neither it can use random alphas. We might allow this in future versions of Apollo.
One possible way to work around this restriction would be to jointly estimate multiple CNL models, one for each group of individuals with the same alphas. The key would be excluding observations using the "rows" setting inside "cnl_setting". For example, let's imagine you have two groups of individuals: low and high income individuals. The code below assumes both groups to have the same preferences, except for their alphas.
Code: Select all
# ################################################################# #
#### LOAD LIBRARY AND DEFINE CORE SETTINGS ####
# ################################################################# #
### Initialise
rm(list = ls())
library(apollo)
apollo_initialise()
### Set core controls
apollo_control = list(
modelName ="CNL2",
modelDescr ="CNL model with two sets of alpha parameters",
indivID ="ID"
)
# ################################################################# #
#### LOAD DATA AND APPLY ANY TRANSFORMATIONS ####
# ################################################################# #
data("apollo_modeChoiceData", package='apollo')
database = apollo_modeChoiceData
rm(apollo_modeChoiceData)
# ################################################################# #
#### DEFINE MODEL PARAMETERS ####
# ################################################################# #
### Parameters, e.g.: c(name1=value1, name2=value2, ...)
apollo_beta=c(asc_bus = 0,
asc_air = 0,
asc_rail = 0,
bTT = 0,
bAcc = 0,
bCost = 0,
bWifi = 0,
bFood = 0,
lFPT = 0.95,
lGPT = 0.95,
a1Rail_GPT = 0,
a2Rail_GPT = 0)
### Name of parameters fixed to their starting values, e.g. c("name1")
apollo_fixed = c()
# ################################################################# #
#### GROUP AND VALIDATE INPUTS ####
# ################################################################# #
apollo_inputs = apollo_validateInputs()
# ################################################################# #
#### DEFINE MODEL AND LIKELIHOOD FUNCTION ####
# ################################################################# #
apollo_probabilities=function(apollo_beta, apollo_inputs,
functionality="estimate"){
### Initialise
apollo_attach(apollo_beta, apollo_inputs)
on.exit(apollo_detach(apollo_beta, apollo_inputs))
P = list()
### Utilities are common for low and high income individuals
V = list()
V[['car']] = bTT*time_car + bCost*cost_car
V[['bus']] = asc_bus + bTT*time_bus + bAcc*access_bus + bCost*cost_bus
V[['air']] = asc_air + bTT*time_air + bAcc*access_air + bCost*cost_air + bWifi*(service_air ==2) + bFood*(service_air ==3)
V[['rail']] = asc_rail + bTT*time_rail + bAcc*access_rail + bCost*cost_rail + bWifi*(service_rail==2) + bFood*(service_rail==3)
### Nest scale parameters are common for low and high income individuals
cnlNests = list(fastPT = lFPT,
groundPT = lGPT,
car = 1)
### Nest allocation parameters (alpha) are different for low and high income individuals
a1 = 1 / (1 + exp(-a1Rail_GPT))
a2 = 1 / (1 + exp(-a2Rail_GPT))
# car bus air rail
cnlStructure1 = matrix(c( 0, 0, 1, 1-a1, # fastPT
0, 1, 0, a1, # groundPT
1, 0, 0, 0),# car
nrow=length(cnlNests), ncol=length(V), byrow=TRUE)
# car bus air rail
cnlStructure2 = matrix(c( 0, 0, 1, 1-a2, # fastPT
0, 1, 0, a2, # groundPT
1, 0, 0, 0),# car
nrow=length(cnlNests), ncol=length(V), byrow=TRUE)
### Likelihood for low income individuals
cnl_settings <- list(
alternatives = c(car=1, bus=2, air=3, rail=4),
avail = list(car=av_car, bus=av_bus, air=av_air, rail=av_rail),
choiceVar = choice,
V = V,
cnlNests = cnlNests,
cnlStructure = cnlStructure1,
rows = income<45000
)
P[["lowInc"]] = apollo_cnl(cnl_settings, functionality)
### Likelihood for high income individuals
cnl_settings$cnlStructure = cnlStructure2
cnl_settings$rows = income>=45000
P[["highInc"]] = apollo_cnl(cnl_settings, functionality)
### Comment out as necessary
P = apollo_combineModels(P, apollo_inputs, functionality)
P = apollo_panelProd(P, apollo_inputs, functionality)
P = apollo_prepareProb(P, apollo_inputs, functionality)
return(P)
}
# ################################################################# #
#### MODEL ESTIMATION & OUTPUT ####
# ################################################################# #
model = apollo_estimate(apollo_beta, apollo_fixed,
apollo_probabilities, apollo_inputs,
estimate_settings=list(writeIter=FALSE))
apollo_modelOutput(model)
apollo_saveOutput(model)