Page 1 of 1

CNL models with individual alphas

Posted: 04 Dec 2020, 07:47
by mastermoses
Hi,

I am currently estimating CNL models for mode choice based on SP-RP data. The SP data was mainly conducted among users of a ride pooling service. Depending on their ride pooling usage (one time user vs. regular user), the alphas vary heavily. So, I wondered if there is a possibility to use individual alphas or at least sociodemographic influences on the alphas when estimating CNL models with Apollo (or even in general)? First tries were of course not successful, since sociodemographic influences are treated as vectors, whereas the alphas have to be single values.

Thanks
Michael

Re: CNL models with individual alphas

Posted: 05 Dec 2020, 17:25
by dpalma
Hi Michael,

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)

Re: CNL models with individual alphas

Posted: 11 Dec 2020, 11:03
by mastermoses
Hi David,

thanks for your suggestion, it worked perfectly for my case! I am looking forward to see those features in future version of Apollo.

Best,
Michael

Re: CNL models with individual alphas

Posted: 16 Jun 2026, 10:16
by NadineKW
Hello,

as I continued working with Michael's results I reactivate his posting from a long time ago.

As described the work-around with individual parameters worked well, however I was wondering, how I could confirm the significance of those parameters, as the allocation-alphas are not estimated directly but only calculated through αk​=exp(α0k​)​/∑j​exp(α0j​) and only the a0's are estimated. As far as I understood the t-values from the regular output cannot be considered in that case.

Do you have any recommendation how to confirm that? I was asked for it in a review.

Thanks a lot :)

Re: CNL models with individual alphas

Posted: 19 Jun 2026, 07:41
by stephanehess
Hi - you can use apollo_deltaMethod for that, just write down the expression for the difference in the alphas