Skip to contents

This document provides a detailed mathematical description of the nested logit (NL) model as implemented in src/nestlogit.cpp.

Notation

Symbol Description
i=1,,Ni = 1, \ldots, N Index for individuals (choice situations)
j=1,,Jij = 1, \ldots, J_i Index for inside alternatives available to individual ii
CiC_i Choice set of inside alternatives available in situation ii
jij_i The alternative chosen by individual ii
wiw_i Weight for individual ii
XijX_{ij} Row vector of covariates for individual ii and alternative jj (1×K1 \times K)
β\beta Coefficient vector (K×1K \times 1)
δj\delta_j Alternative-specific constant (ASC) for alternative jj
VijV_{ij} Systematic (deterministic) utility
BkB_k Global set of inside alternatives belonging to nest kk; situation ii contributes BkCiB_k\cap C_i
k(j)k(j) The nest containing alternative jj
λk\lambda_k Inclusive value (dissimilarity) coefficient for nest kk
IkI_k Inclusive value for nest kk
P(jk)P(j \mid k) Probability of choosing jj conditional on choosing nest kk
PkP_k Marginal probability of choosing nest kk
PijP_{ij} Probability that individual ii chooses alternative jj

1. Model Definition

1.1 Utility Specification

The utility that individual ii derives from alternative jj is:

Uij=Vij+εij U_{ij} = V_{ij} + \varepsilon_{ij}

where the systematic utility is:

Vij=Xijβ+δj V_{ij} = X_{ij}\beta + \delta_j

The error term εij\varepsilon_{ij} follows a Generalized Extreme Value (GEV) distribution that induces within-nest correlation.

1.2 Nest Structure

The JJ inside alternatives are partitioned into KK mutually exclusive and exhaustive nests B1,,BKB_1, \ldots, B_K. An outside option (alternative 0) with Vi0=0V_{i0} = 0 may optionally be included, and it is always assigned its own singleton nest with λ0=1\lambda_0 = 1.

1.3 Inclusive Value Coefficients

Each nest kk has a dissimilarity parameter λk>0\lambda_k > 0 that governs within-nest substitution:

  • λk=1\lambda_k = 1 corresponds to independent (MNL-like) alternatives within the nest.
  • 0<λk<10 < \lambda_k < 1 indicates positive within-nest correlation (the typical case).
  • λk>1\lambda_k > 1 is mathematically evaluable in the implemented probability formula but lies outside the standard globally RUM-consistent nested-GEV restriction 0<λk10<\lambda_k\leq1. It should not automatically be interpreted as a valid negative within-nest correlation parameter.

The optimizer in run_nestlogit() currently imposes the lower bound λk>0\lambda_k > 0 but does not impose λk1\lambda_k \leq 1. An estimate above one should therefore be read as a diagnostic about the nesting tree or maintained assumptions, not as evidence of especially strong within-nest substitution.

Singleton nests (nests with exactly one alternative) have λk\lambda_k fixed to 1 and are not estimated. Only non-singleton nests contribute λ\lambda parameters to θ\theta. The low-level parser requires at least one globally non-singleton nest; a specification in which every nest is a singleton is rejected rather than estimated as an MNL through this entry point.

Code reference: src/nestlogit.cpp

1.4 Alternative-Specific Constants (ASCs)

The ASC identification follows the same convention as MNL:

  • Without outside option (include_outside_option = FALSE): The first inside alternative’s ASC is fixed to zero (δ1=0\delta_1 = 0). The parameter vector contains J1J-1 free ASC parameters.
  • With outside option (include_outside_option = TRUE): The outside option serves as the reference with Vi0=0V_{i0} = 0. All JJ inside alternatives have free ASC parameters.

Code reference: src/nestlogit.cpp


2. Log-Likelihood Function

2.1 Probability Decomposition

The nested logit choice probability decomposes as:

Pij=P(jk(j))Pk(j) P_{ij} = P(j \mid k(j)) \cdot P_{k(j)}

The two components are derived from the GEV generating function.

2.2 Inclusive Value

The inclusive value for nest kk is the log-sum of scaled utilities within the nest:

Iik=jBkCiexp(Vijλk) I_{ik} = \sum_{j \in B_k\cap C_i} \exp\!\left(\frac{V_{ij}}{\lambda_k}\right)

logIik=log(jBkCiexp(Vijλk)) \log I_{ik} = \log\!\left(\sum_{j \in B_k\cap C_i} \exp\!\left(\frac{V_{ij}}{\lambda_k}\right)\right)

The rest of the article suppresses the ii subscript and writes IkI_k. Nests with no available alternative in CiC_i have log inclusive value -\infty and contribute zero to the upper-level denominator.

2.3 Conditional Choice Probability

The probability of choosing alternative jj given that nest k(j)k(j) is chosen:

P(jk)=exp(Vij/λk)Ik P(j \mid k) = \frac{\exp(V_{ij}/\lambda_k)}{I_k}

In log form:

logP(jk)=VijλklogIk \log P(j \mid k) = \frac{V_{ij}}{\lambda_k} - \log I_k

2.4 Nest (Marginal) Probability

The probability of choosing nest kk:

Pk=exp(λklogIk)lexp(λllogIl) P_k = \frac{\exp(\lambda_k \log I_k)}{\sum_{l} \exp(\lambda_l \log I_l)}

If an outside option is included, its contribution enters the denominator as exp(λ0logI0)=exp(1log(exp(0/1)))=exp(0)=1\exp(\lambda_0 \log I_0) = \exp(1 \cdot \log(\exp(0/1))) = \exp(0) = 1.

In log form:

logPk=λklogIklog(lexp(λllogIl)) \log P_k = \lambda_k \log I_k - \log\!\left(\sum_l \exp(\lambda_l \log I_l)\right)

2.5 Joint Choice Probability

Taking logs of the joint probability:

logPij=logP(jk(j))+logPk(j) \log P_{ij} = \log P(j \mid k(j)) + \log P_{k(j)}

logPij=Vijλk(j)logIk(j)+λk(j)logIk(j)logDi \log P_{ij} = \frac{V_{ij}}{\lambda_{k(j)}} - \log I_{k(j)} + \lambda_{k(j)} \log I_{k(j)} - \log D_i

where Di=lexp(λllogIl)D_i = \sum_l \exp(\lambda_l \log I_l) (plus 1 if an outside option is present).

Code reference: src/nestlogit.cpp

2.6 Log-Likelihood

The log-likelihood is the weighted sum of log-probabilities of the observed choices:

(θ)=i=1NwilogPiji \ell(\theta) = \sum_{i=1}^{N} w_i \log P_{ij_i}

where θ=(β,λ,δ)\theta = (\beta, \lambda, \delta) and jij_i is the alternative chosen by individual ii.

Code reference: src/nestlogit.cpp

2.7 Log-Sum-Exp Trick for Numerical Stability

Two log-sum-exp stabilizations are applied.

Within-nest inclusive value. To compute logIk\log I_k without overflow, the implementation subtracts the maximum scaled utility in each nest:

logIk=Vmax,k+log(jBkexp(VijλkVmax,k)) \log I_k = V_{\max,k} + \log\!\left(\sum_{j \in B_k} \exp\!\left(\frac{V_{ij}}{\lambda_k} - V_{\max,k}\right)\right)

where Vmax,k=maxjBkVij/λkV_{\max,k} = \max_{j \in B_k} V_{ij}/\lambda_k.

Across-nest denominator. The denominator Di=lexp(λllogIl)D_i = \sum_l \exp(\lambda_l \log I_l) is similarly stabilized by subtracting maxlλllogIl\max_l \lambda_l \log I_l before exponentiation.

Code reference: src/nestlogit.cpp

2.8 Relation to Other Nested-Logit Parameterizations

The probabilities in §§2.3–2.4 are the utility-normalized GEV form used by choicer (McFadden 1978; Train 2009, Ch. 4): utility is scaled by 1/λk1/\lambda_k inside the conditional probability, and the inclusive value is multiplied by λk\lambda_k in the nest probability. Some software uses a normalization in which its reported systematic index enters the within-nest logit unscaled. These conventions can represent different definitions of utility coefficients and error scales; they are not generally numerically identical under a common-coefficient restriction, and their reported β\beta and λ\lambda cannot be compared without deriving the normalization mapping. It is too strong to label every unscaled convention non-RUM; the precise point is which utility, inclusive-value, and scale normalization is being estimated (Koppelman & Wen 1998; Hensher & Greene 2002; Heiss 2002).


3. Gradient Computation

3.1 Gradient with Respect to ViaV_{ia} (Utility Scores)

To derive the gradients with respect to β\beta and δ\delta, we first compute the derivative of the log-probability of the chosen alternative with respect to the systematic utility ViaV_{ia} of each alternative aa.

Let kik_i denote the chosen nest (i.e., k(ji)k(j_i)). The log-probability of the chosen alternative is:

logPiji=logP(jiki)+logPki \log P_{ij_i} = \log P(j_i \mid k_i) + \log P_{k_i}

Derivative of the conditional term. Since logP(jk)=Vij/λklogIk\log P(j \mid k) = V_{ij}/\lambda_k - \log I_k and logIkVia=1λk𝟏aBkP(ak)\frac{\partial \log I_k}{\partial V_{ia}} = \frac{1}{\lambda_k} \mathbf{1}_{a \in B_k} P(a \mid k):

logP(jiki)Via=1λki(𝟏a=ji𝟏aBkiP(aki)) \frac{\partial \log P(j_i \mid k_i)}{\partial V_{ia}} = \frac{1}{\lambda_{k_i}}\left(\mathbf{1}_{a = j_i} - \mathbf{1}_{a \in B_{k_i}} P(a \mid k_i)\right)

Derivative of the nest term. Using logDiVia=Pk(a)P(ak(a))=Pia\frac{\partial \log D_i}{\partial V_{ia}} = P_{k(a)} P(a \mid k(a)) = P_{ia}:

logPkiVia=𝟏aBkiP(aki)Pia \frac{\partial \log P_{k_i}}{\partial V_{ia}} = \mathbf{1}_{a \in B_{k_i}} P(a \mid k_i) - P_{ia}

Combined. Adding both terms:

logPijiVia=𝟏a=jiλki+(11λki)𝟏aBkiP(aki)Pia \frac{\partial \log P_{ij_i}}{\partial V_{ia}} = \frac{\mathbf{1}_{a = j_i}}{\lambda_{k_i}} + \left(1 - \frac{1}{\lambda_{k_i}}\right)\mathbf{1}_{a \in B_{k_i}} P(a \mid k_i) - P_{ia}

This is implemented as the vector grad_vec of length JiJ_i:

grad_vec[a]=Pia+(11λki)𝟏aBkiP(aki)+1λki𝟏a=ji \text{grad\_vec}[a] = -P_{ia} + \left(1 - \frac{1}{\lambda_{k_i}}\right) \mathbf{1}_{a \in B_{k_i}} P(a \mid k_i) + \frac{1}{\lambda_{k_i}} \mathbf{1}_{a = j_i}

Code reference: src/nestlogit.cpp

3.2 Gradient with Respect to β\beta

Since Vijβ=XijT\frac{\partial V_{ij}}{\partial \beta} = X_{ij}^T, the contribution from individual ii is:

iβ=wij=1Jigrad_vec[j]XijT=wiXiTgrad_vec \frac{\partial \ell_i}{\partial \beta} = w_i \sum_{j=1}^{J_i} \text{grad\_vec}[j] \cdot X_{ij}^T = w_i \, X_i^T \, \text{grad\_vec}

The full gradient is accumulated as a single BLAS matrix-vector product, identically to MNL.

Code reference: src/nestlogit.cpp

3.3 Gradient with Respect to δ\delta

Since Vijδa=𝟏j=a\frac{\partial V_{ij}}{\partial \delta_a} = \mathbf{1}_{j = a}, the gradient entries are the corresponding elements of grad_vec, scattered to the appropriate positions in θ\theta:

iδa=wigrad_vec[a] \frac{\partial \ell_i}{\partial \delta_a} = w_i \cdot \text{grad\_vec}[a]

The same free-ASC convention as MNL applies (first inside alternative’s ASC excluded when no outside option).

Code reference: src/nestlogit.cpp

3.4 Gradient with Respect to λk\lambda_k

Define the within-nest probability-weighted mean utility:

Vk=jBkP(jk)Vij \bar{V}_k = \sum_{j \in B_k} P(j \mid k) \cdot V_{ij}

For the chosen nest (k=kik = k_i). The log-probability decomposes as:

logPiji=VijiλkilogIkilogP(jiki)+λkilogIkilogDilogPki \log P_{ij_i} = \underbrace{\frac{V_{ij_i}}{\lambda_{k_i}} - \log I_{k_i}}_{\log P(j_i \mid k_i)} + \underbrace{\lambda_{k_i} \log I_{k_i} - \log D_i}_{\log P_{k_i}}

Using logIkλk=Vk/λk2\frac{\partial \log I_k}{\partial \lambda_k} = -\bar{V}_k / \lambda_k^2:

logP(jiki)λki=VkiVijiλki2 \frac{\partial \log P(j_i \mid k_i)}{\partial \lambda_{k_i}} = \frac{\bar{V}_{k_i} - V_{ij_i}}{\lambda_{k_i}^2}

logPkiλki=(1Pki)(logIkiVkiλki) \frac{\partial \log P_{k_i}}{\partial \lambda_{k_i}} = (1 - P_{k_i})\!\left(\log I_{k_i} - \frac{\bar{V}_{k_i}}{\lambda_{k_i}}\right)

Combining:

iλki=wi[(1Pki)(logIkiVkiλki)+VkiVijiλki2] \frac{\partial \ell_i}{\partial \lambda_{k_i}} = w_i \left[(1 - P_{k_i})\!\left(\log I_{k_i} - \frac{\bar{V}_{k_i}}{\lambda_{k_i}}\right) + \frac{\bar{V}_{k_i} - V_{ij_i}}{\lambda_{k_i}^2}\right]

For a non-chosen nest (kkik \neq k_i). The conditional probability P(jiki)P(j_i \mid k_i) is independent of λk\lambda_k, so only the nest probability contributes:

logPkiλk=Pk(logIkVkλk) \frac{\partial \log P_{k_i}}{\partial \lambda_k} = -P_k \!\left(\log I_k - \frac{\bar{V}_k}{\lambda_k}\right)

iλk=wiPk(logIkVkλk) \frac{\partial \ell_i}{\partial \lambda_k} = -w_i \, P_k \!\left(\log I_k - \frac{\bar{V}_k}{\lambda_k}\right)

The common factor logIkVk/λk\log I_k - \bar{V}_k / \lambda_k is labeled term_in_brackets in the code.

Code reference: src/nestlogit.cpp


4. Hessian Computation

This section documents the Hessian of the negated log-likelihood. The function nl_loglik_hessian_parallel returns H(θ)=2(θ)H(\theta) = -\nabla^2 \ell(\theta), the same quantity that invert_hessian() expects (positive semi-definite at the MLE). The sign convention matches the numeric oracle nl_loglik_numeric_hessian (which differences the negated gradient), so both functions are interchangeable as inputs to invert_hessian().

Two implementations are available:

  • nl_loglik_hessian_paralleldefault (se_method = "hessian"): single-pass analytical Hessian derived below. Validated against the numeric oracle at a maximum absolute difference of 2.6×108\approx 2.6 \times 10^{-8} across the package’s test fixtures, well below the 10610^{-6} tolerance those tests enforce. At extreme λk<0.1\lambda_k < 0.1, the oracle’s own finite-difference accuracy degrades; the analytical Hessian remains finite and symmetric throughout.
  • nl_loglik_numeric_hessian — retained oracle (se_method = "numeric"): central finite differences on the analytical gradient with step ϵi=106max(|θi|,1)\epsilon_i = 10^{-6} \cdot \max(|\theta_i|, 1). Use for diagnostic comparison or whenever a direct verification of the analytical path is required.

4.1 Notation and Scope

All notation follows §§0–3. Subscripts ii (individual), j/a/bj/a/b (alternative local indices within ii’s choice set, 0-based), and kk/ll (nest indices, 0-based) are used throughout. Additional symbols specific to this section:

Symbol Description
kik_i 0-based index of the chosen nest (1-1 when outside option is chosen)
cac_a 0-based local index of the chosen inside alternative
Vk\bar{V}_k jBkP(jk)Vij\sum_{j \in B_k} P(j \mid k) \cdot V_{ij}P(k)P(\cdot \mid k)-weighted mean utility in nest kk
TkT_k logIkVk/λk\log I_k - \bar{V}_k / \lambda_k — the “bracket term” from §3.4
Ṽk2\widetilde{V}^2_k jBkP(jk)Vij2\sum_{j \in B_k} P(j \mid k) \cdot V_{ij}^2 — conditional second moment
VarVk\mathrm{VarV}_k Ṽk2Vk2\widetilde{V}^2_k - \bar{V}_k^2P(k)P(\cdot\mid k)-weighted variance of VV in nest kk
𝐦k\mathbf{m}_k jBkPij𝐱ij\sum_{j \in B_k} P_{ij} \cdot \mathbf{x}_{ij}PijP_{ij}-weighted mean of XX in nest kk (KK-vector)
𝐜k\mathbf{c}_k jBkP(jk)𝐱ij\sum_{j \in B_k} P(j \mid k) \cdot \mathbf{x}_{ij}P(k)P(\cdot\mid k)-weighted mean of XX in nest kk (KK-vector)
𝐒k(2)\mathbf{S}^{(2)}_k jBkPij𝐱ij𝐱ijT\sum_{j \in B_k} P_{ij} \cdot \mathbf{x}_{ij} \mathbf{x}_{ij}^TPijP_{ij}-weighted second moment of XX (K×KK \times K)
𝐐k\mathbf{Q}_k jBkP(jk)𝐱ij𝐱ijT\sum_{j \in B_k} P(j \mid k) \cdot \mathbf{x}_{ij} \mathbf{x}_{ij}^TP(k)P(\cdot\mid k)-weighted second moment of XX (K×KK \times K)
𝐱i\bar{\mathbf{x}}_i jPij𝐱ij\sum_j P_{ij} \cdot \mathbf{x}_{ij}PijP_{ij}-weighted global mean of XX for individual ii (KK-vector)

The negated per-individual log-likelihood contribution is fi=wilogPi,caf_i = -w_i \log P_{i,c_a}. The full Hessian is the sum H=i=1NH(i)H = \sum_{i=1}^N H^{(i)} where H(i)=wi2logPi,caH^{(i)} = -w_i \nabla^2 \log P_{i,c_a}.


4.2 V-Space Hessian QiQ_i

Because Vij=𝐱ijβ+δjV_{ij} = \mathbf{x}_{ij} \beta + \delta_j is linear in β\beta and δ\delta, the second derivatives with respect to these parameters factor through the mi×mim_i \times m_i V-space Hessian. Define:

Qi[a,b]=2logPi,caViaVib Q_i[a, b] = -\frac{\partial^2 \log P_{i,c_a}}{\partial V_{ia} \, \partial V_{ib}}

Starting from the gradient formula (§3.1):

g[a]=logPi,caVia=Pia+(11λki)𝟏aBkiP(aki)+𝟏a=caλki g[a] = \frac{\partial \log P_{i,c_a}}{\partial V_{ia}} = -P_{ia} + \left(1 - \frac{1}{\lambda_{k_i}}\right) \mathbf{1}_{a \in B_{k_i}} P(a \mid k_i) + \frac{\mathbf{1}_{a = c_a}}{\lambda_{k_i}}

differentiating with respect to VibV_{ib} yields:

g[a]Vib=PiaVib+(11λki)𝟏aBkiP(aki)Vib \frac{\partial g[a]}{\partial V_{ib}} = -\frac{\partial P_{ia}}{\partial V_{ib}} + \left(1 - \frac{1}{\lambda_{k_i}}\right) \mathbf{1}_{a \in B_{k_i}} \frac{\partial P(a \mid k_i)}{\partial V_{ib}}

Partial derivative of PiaP_{ia} with respect to VibV_{ib}. Write ka=k(a)k_a = k(a), kb=k(b)k_b = k(b). Expanding Pia=P(aka)PkaP_{ia} = P(a \mid k_a) \cdot P_{k_a} via the product rule and using Pka/Vib=Pka[𝟏kb=kaP(bka)Pib]\partial P_{k_a}/\partial V_{ib} = P_{k_a}[\mathbf{1}_{k_b=k_a} P(b\mid k_a) - P_{ib}]:

PiaVib=Pia{𝟏ka=kb[𝟏a=bλka+P(bka)(11λka)]Pib} \frac{\partial P_{ia}}{\partial V_{ib}} = P_{ia} \left\{ \mathbf{1}_{k_a = k_b}\left[ \frac{\mathbf{1}_{a=b}}{\lambda_{k_a}} + P(b \mid k_a)\left(1-\frac{1}{\lambda_{k_a}}\right) \right] - P_{ib} \right\}

Partial derivative of P(aki)P(a \mid k_i) with respect to VibV_{ib}. Non-zero only when aBkia \in B_{k_i}:

P(aki)Vib=1λki𝟏kb=kiP(bki)(𝟏a=bP(aki)) \frac{\partial P(a \mid k_i)}{\partial V_{ib}} = \frac{1}{\lambda_{k_i}} \mathbf{1}_{k_b = k_i} P(b \mid k_i) \left(\mathbf{1}_{a=b} - P(a \mid k_i)\right)

Combined V-space Hessian (correct formula). Negating and combining:

Qi[a,b]=Pia{𝟏ka=kb[𝟏a=bλka+P(bka)(11λka)]Pib}𝟏ka=ki𝟏kb=ki11/λkiλkiP(aki)(𝟏a=bP(bki))Ca,b: chosen-nest correction \boxed{ Q_i[a, b] = P_{ia} \left\{ \mathbf{1}_{k_a = k_b}\left[ \frac{\mathbf{1}_{a=b}}{\lambda_{k_a}} +P(b \mid k_a)\left(1-\frac{1}{\lambda_{k_a}}\right) \right] - P_{ib} \right\} - \underbrace{\mathbf{1}_{k_a = k_i} \mathbf{1}_{k_b = k_i} \cdot \frac{1 - 1/\lambda_{k_i}}{\lambda_{k_i}} \cdot P(a \mid k_i)\bigl(\mathbf{1}_{a=b} - P(b \mid k_i)\bigr)}_{C_{a,b}: \text{ chosen-nest correction}} }

The chosen-nest correction Ca,bC_{a,b} is nonzero only when both aa and bb are in the chosen nest kik_i (and ki0k_i \geq 0). It arises from the (11/λki)(1 - 1/\lambda_{k_i}) factor in g[a]g[a] coupling the conditional probability gradient back to VibV_{ib}.

Structural notes and MNL limit:

  • For kakbk_a \neq k_b: Qi[a,b]=PiaPibQ_i[a,b] = -P_{ia} P_{ib} (cross-nest entries are the negative product of marginal probabilities, the familiar multinomial covariance term).
  • MNL limit (λk=1\lambda_k = 1 for all kk): Qi[a,b]=Pia(𝟏a=bPib)Q_i[a,b] = P_{ia}(\mathbf{1}_{a=b} - P_{ib}), the standard multinomial Hessian of logPca-\log P_{c_a}. Own diagonal =Pia(1Pia)= P_{ia}(1-P_{ia}); off-diagonal =PiaPib= -P_{ia}P_{ib}. The chosen-nest correction vanishes because 11/λki=01 - 1/\lambda_{k_i} = 0.
  • When the outside option is chosen (ki=1k_i = -1) or when λki=1\lambda_{k_i} = 1 (singleton chosen nest), Ca,b=0C_{a,b} = 0 for all pairs.

Implementation note: The implementation materializes QiQ_i as an explicit mi×mim_i \times m_i matrix, which is efficient for typical choice set sizes (J20J \leq 20). The outer-product decomposition used for the beta-beta block (§4.3) avoids forming this matrix explicitly for the K×KK \times K accumulation.

Code reference: src/nestlogit.cpp


4.3 Beta-Beta Block

Since Vij/βr=xij,r\partial V_{ij}/\partial \beta_r = x_{ij,r}:

Hβr,βs(i)=wiabxia,rQi[a,b]xib,s=wi𝐗iT𝐐i𝐗i H^{(i)}_{\beta_r, \beta_s} = w_i \sum_{a} \sum_{b} x_{ia,r} \cdot Q_i[a,b] \cdot x_{ib,s} = w_i \, \mathbf{X}_i^T \mathbf{Q}_i \mathbf{X}_i

The matrix product is decomposed into three terms that can be accumulated in a single nest-level pass, exploiting the outer-product structure of QiQ_i:

Term A — universal outer product (subtracted): wi𝐱i𝐱iT -w_i \, \bar{\mathbf{x}}_i \, \bar{\mathbf{x}}_i^T

This arises from the PiaPib-P_{ia} P_{ib} term universal to all pairs: a,bxia,rPiaPibxib,s=xi,rxi,s\sum_{a,b} x_{ia,r} P_{ia} P_{ib} x_{ib,s} = \bar{x}_{i,r} \bar{x}_{i,s}.

Term B — per-nest within-nest correction (added), summed over all nests kk: +wik[(11λk)𝐦k𝐜kT+1λk𝐒k(2)] +w_i \sum_{k} \left[ \left(1 - \frac{1}{\lambda_k}\right) \mathbf{m}_k \mathbf{c}_k^T + \frac{1}{\lambda_k} \mathbf{S}^{(2)}_k \right]

For singleton nests (λk=1\lambda_k = 1): (11/λk)=0(1 - 1/\lambda_k) = 0, so the contribution reduces to 𝐒k(2)\mathbf{S}^{(2)}_k.

Term C — chosen-nest correction (subtracted), only when ki0k_i \geq 0: wi11/λkiλki(𝐐ki𝐜ki𝐜kiT) -w_i \cdot \frac{1 - 1/\lambda_{k_i}}{\lambda_{k_i}} \left( \mathbf{Q}_{k_i} - \mathbf{c}_{k_i} \mathbf{c}_{k_i}^T \right)

Here 𝐐ki𝐜ki𝐜kiT\mathbf{Q}_{k_i} - \mathbf{c}_{k_i}\mathbf{c}_{k_i}^T is the P(ki)P(\cdot\mid k_i)-weighted covariance of XX within the chosen nest.

Full beta-beta block (Hessian of the negated log-likelihood; positive semi-definite at the MLE): Hββ(i)=wi[𝐱i𝐱iT+k((11λk)𝐦k𝐜kT+1λk𝐒k(2))𝟏ki011/λkiλki(𝐐ki𝐜ki𝐜kiT)] H^{(i)}_{\beta\beta} = w_i \left[ -\bar{\mathbf{x}}_i \bar{\mathbf{x}}_i^T + \sum_k \!\left(\!\left(1-\frac{1}{\lambda_k}\right)\mathbf{m}_k \mathbf{c}_k^T + \frac{1}{\lambda_k}\mathbf{S}^{(2)}_k\right) - \mathbf{1}_{k_i \geq 0} \cdot \frac{1-1/\lambda_{k_i}}{\lambda_{k_i}} \!\left(\mathbf{Q}_{k_i} - \mathbf{c}_{k_i}\mathbf{c}_{k_i}^T\right) \right]

MNL limit check. At λk=1\lambda_k = 1 for all kk: Term B =k𝐒k(2)=𝐗iTdiag(Pi)𝐗i= \sum_k \mathbf{S}^{(2)}_k = \mathbf{X}_i^T \mathrm{diag}(P_i) \mathbf{X}_i; Term C vanishes; the formula yields the standard MNL expression wi(𝐗iTdiag(Pi)𝐗i𝐱i𝐱iT)w_i(\mathbf{X}_i^T \mathrm{diag}(P_i) \mathbf{X}_i - \bar{\mathbf{x}}_i \bar{\mathbf{x}}_i^T).

Code reference: src/nestlogit.cpp


4.4 Beta-Delta and Delta-Delta Blocks

Since Vij/δa=𝟏j=a\partial V_{ij}/\partial \delta_a = \mathbf{1}_{j=a}, these blocks are direct projections of QiQ_i onto free-ASC alternatives.

Delta-delta block (for free-ASC alternatives aa' and bb'): Hδa,δb(i)=wiQi[a,b] H^{(i)}_{\delta_{a'}, \delta_{b'}} = w_i \cdot Q_i[a', b']

Beta-delta block (for covariate index rr and free-ASC alternative bb'): Hβr,δb(i)=wiaxia,rQi[a,b]=wi(𝐗iT𝐐i[:,b])r H^{(i)}_{\beta_r, \delta_{b'}} = w_i \sum_{a} x_{ia,r} \cdot Q_i[a, b'] = w_i \, \bigl(\mathbf{X}_i^T \mathbf{Q}_i[:, b']\bigr)_r

Both blocks reuse the same QiQ_i matrix computed in §4.2. No additional auxiliary quantities are required.

ASC normalization. Without an outside option, the first inside alternative’s ASC is fixed to zero: free-ASC alternatives satisfy alt_idx0[a] > 0, mapped to theta positions delta_start_idx + alt_idx0[a] - 1.

Code reference: src/nestlogit.cpp


4.5 Lambda-V Cross Derivative

The lambda parameters enter nonlinearly through both logIk\log I_k and the nest probabilities, so cross-derivatives between λk\lambda_k and β/δ\beta/\delta must be computed via the chain rule. Define:

db(k)=gλkVib,gλk=logPi,caλk d^{(k)}_b = \frac{\partial g_{\lambda_k}}{\partial V_{ib}}, \qquad g_{\lambda_k} = \frac{\partial \log P_{i,c_a}}{\partial \lambda_k}

Key intermediates (derived from §3.4):

TkVib=𝟏k(b)=kP(bk)VibVkλk2,PkVib=Pk[𝟏k(b)=kP(bk)Pib] \frac{\partial T_k}{\partial V_{ib}} = -\mathbf{1}_{k(b)=k} P(b \mid k) \frac{V_{ib} - \bar{V}_k}{\lambda_k^2}, \qquad \frac{\partial P_k}{\partial V_{ib}} = P_k \bigl[\mathbf{1}_{k(b)=k} P(b \mid k) - P_{ib}\bigr]

For non-chosen nests (kkik \neq k_i), using gλk=PkTkg_{\lambda_k} = -P_k T_k: db(k)=PkTkPib+𝟏k(b)=kPkP(bk)[VibVkλk2Tk] d^{(k)}_b = P_k T_k P_{ib} + \mathbf{1}_{k(b)=k} P_k P(b \mid k) \left[\frac{V_{ib} - \bar{V}_k}{\lambda_k^2} - T_k\right]

The first term is a universal “shift” proportional to PibP_{ib}; the second is the within-nest correction active only for bBkb \in B_k.

For the chosen nest (k=kik = k_i, only when ki0k_i \geq 0), using gλki=(1Pki)Tki+(VkiVca)/λki2g_{\lambda_{k_i}} = (1-P_{k_i})T_{k_i} + (\bar{V}_{k_i} - V_{c_a})/\lambda_{k_i}^2: db(ki)=PkiTkiPib𝟏b=caλki2+𝟏k(b)=kiP(bki)[PkiTki+VibVkiλki2(Pki1+1λki)+1λki2] d^{(k_i)}_b = P_{k_i} T_{k_i} P_{ib} - \frac{\mathbf{1}_{b = c_a}}{\lambda_{k_i}^2} + \mathbf{1}_{k(b)=k_i} P(b \mid k_i) \left[ -P_{k_i} T_{k_i} + \frac{V_{ib} - \bar{V}_{k_i}}{\lambda_{k_i}^2} \left(P_{k_i} - 1 + \frac{1}{\lambda_{k_i}}\right) + \frac{1}{\lambda_{k_i}^2} \right]

The extra 1/λki2-1/\lambda_{k_i}^2 term for b=cab = c_a arises from differentiating the (VkiVca)/λki2(\bar{V}_{k_i} - V_{c_a})/\lambda_{k_i}^2 component of the chosen-nest gradient.


4.6 Lambda-Beta and Lambda-Delta Blocks

Using Vib/βr=xib,r\partial V_{ib}/\partial \beta_r = x_{ib,r} and Vib/δb=𝟏b=b\partial V_{ib}/\partial \delta_{b'} = \mathbf{1}_{b=b'}:

Hλk,βr(i)=wibdb(k)xib,r=wi(𝐗iT𝐝(k))r H^{(i)}_{\lambda_k, \beta_r} = -w_i \sum_{b} d^{(k)}_b \cdot x_{ib,r} = -w_i \, \bigl(\mathbf{X}_i^T \mathbf{d}^{(k)}\bigr)_r

Hλk,δb(i)=widb(k) H^{(i)}_{\lambda_k, \delta_{b'}} = -w_i \, d^{(k)}_{b'}

Both are filled symmetrically. Singleton nests (theta index =1= -1) contribute no rows or columns to these blocks.

Code reference: src/nestlogit.cpp


4.7 Lambda-Lambda Block

Differentiating gλkg_{\lambda_k} with respect to λl\lambda_l, using: Tkλk=VarVkλk30,Pkλk=Pk(1Pk)Tk,Pkλl=PkPlTl(lk),Tkλl=0(lk) \frac{\partial T_k}{\partial \lambda_k} = \frac{\mathrm{VarV}_k}{\lambda_k^3} \geq 0, \qquad \frac{\partial P_k}{\partial \lambda_k} = P_k (1 - P_k) T_k, \qquad \frac{\partial P_k}{\partial \lambda_l} = -P_k P_l T_l \;(l \neq k), \qquad \frac{\partial T_k}{\partial \lambda_l} = 0 \;(l \neq k)

Off-diagonal klk \neq l (any combination of chosen/non-chosen nests): Hλk,λl(i)=wiPkPlTkTl H^{(i)}_{\lambda_k, \lambda_l} = -w_i \, P_k P_l T_k T_l

This formula holds uniformly regardless of whether kk or ll equals kik_i. It can be negative (whenever TkT_k and TlT_l share the same sign), reflecting correlation between nest-level inclusive values.

Diagonal kkik \neq k_i (non-chosen nest): Hλk,λk(i)=wi[Pk(1Pk)Tk2+PkVarVkλk3] H^{(i)}_{\lambda_k, \lambda_k} = w_i \left[ P_k (1 - P_k) T_k^2 + \frac{P_k \, \mathrm{VarV}_k}{\lambda_k^3} \right]

The first term is a Fisher-information-type squared-gradient term; the second is positive and captures curvature from TkT_k’s dependence on λk\lambda_k through the within-nest utility variance.

Diagonal k=kik = k_i (chosen nest, only when ki0k_i \geq 0): Hλki,λki(i)=wi[Pki(1Pki)Tki2(1Pki)VarVkiλki3+VarVkiλki4+2(VkiVca)λki3] H^{(i)}_{\lambda_{k_i}, \lambda_{k_i}} = w_i \left[ P_{k_i}(1 - P_{k_i}) T_{k_i}^2 - \frac{(1 - P_{k_i}) \mathrm{VarV}_{k_i}}{\lambda_{k_i}^3} + \frac{\mathrm{VarV}_{k_i}}{\lambda_{k_i}^4} + \frac{2(\bar{V}_{k_i} - V_{c_a})}{\lambda_{k_i}^3} \right]

The chosen-nest diagonal differs from the non-chosen formula because the (VkiVca)/λki2(\bar{V}_{k_i} - V_{c_a})/\lambda_{k_i}^2 term in gλkig_{\lambda_{k_i}} contributes VarVki/λki42(VkiVca)/λki3-\mathrm{VarV}_{k_i}/\lambda_{k_i}^4 - 2(\bar{V}_{k_i} - V_{c_a})/\lambda_{k_i}^3 when differentiated. Since the chosen alternative tends to have above-average utility within its nest (VcaVkiV_{c_a} \geq \bar{V}_{k_i} in expectation), the last term is typically negative, making the chosen-nest diagonal somewhat smaller than the non-chosen counterpart.

When the outside option is chosen (ki=1k_i = -1), all lambda diagonals use the non-chosen formula.

Code reference: src/nestlogit.cpp


4.8 Single-Pass Implementation and Auxiliary Accumulations

All six blocks are accumulated in a single parallel pass over individuals. The per-nest auxiliary quantities below are accumulated in an inner loop over alternatives at O(mi)O(m_i) cost before any block is computed.

Per-nest scalars (zero-initialized per individual, indexed by nest kk):

Quantity Formula Blocks that use it
Vk\bar{V}_k jBkP(jk)Vj\sum_{j \in B_k} P(j\mid k) V_j TkT_k, lambda-lambda, lambda-V cross
Ṽk2\widetilde{V}^2_k jBkP(jk)Vj2\sum_{j \in B_k} P(j\mid k) V_j^2 VarVk\mathrm{VarV}_k for lambda-lambda diagonal
TkT_k logIkVk/λk\log I_k - \bar{V}_k/\lambda_k lambda-lambda (all entries), lambda-V cross
VarVk\mathrm{VarV}_k Ṽk2Vk2\widetilde{V}^2_k - \bar{V}_k^2 lambda-lambda diagonal

Per-nest K-vectors:

Quantity Formula Blocks that use it
𝐦k\mathbf{m}_k jBkPij𝐱j\sum_{j \in B_k} P_{ij} \mathbf{x}_j beta-beta Term B
𝐜k\mathbf{c}_k jBkP(jk)𝐱j\sum_{j \in B_k} P(j\mid k) \mathbf{x}_j beta-beta Terms B and C

Per-nest K×KK \times K matrices:

Quantity Formula Blocks that use it
𝐒k(2)\mathbf{S}^{(2)}_k jBkPij𝐱j𝐱jT\sum_{j \in B_k} P_{ij} \mathbf{x}_j \mathbf{x}_j^T beta-beta Term B
𝐐k\mathbf{Q}_k jBkP(jk)𝐱j𝐱jT\sum_{j \in B_k} P(j\mid k) \mathbf{x}_j \mathbf{x}_j^T beta-beta Term C (chosen nest kik_i only)

Global per-individual: 𝐱i=jPij𝐱j=k𝐦k\bar{\mathbf{x}}_i = \sum_j P_{ij} \mathbf{x}_j = \sum_k \mathbf{m}_k (beta-beta Term A).

OpenMP structure. The outer loop over individuals is parallelized with dynamic scheduling. Each thread maintains a thread-local P×PP \times P accumulator local_H, merged into global_H via #pragma omp critical after the individual loop. The nest-to-theta-index map is copied thread-privately to avoid false sharing.

Symmetrization and sanitization. After the parallel loop: H(H+HT)/2H \leftarrow (H + H^T)/2 enforces exact symmetry; any remaining non-finite entries are zeroed.

Singleton-nest handling. Singleton nests (λk=1\lambda_k = 1, theta index =1= -1) contribute nothing to the lambda-lambda, lambda-beta, or lambda-delta blocks. Their beta-beta contribution via Term B simplifies to 𝐒k(2)\mathbf{S}^{(2)}_k (since 11/λk=01 - 1/\lambda_k = 0).

Per-individual weights. Every contribution is multiplied by wiw_i (WESML weight; equals 1 for unweighted data).

Code reference: src/nestlogit.cpp


5. Implementation Details

5.1 Parameter Vector Structure

The full parameter vector θ\theta is organized as:

Block Indices Length Description
β\beta [0,K)[0, K) KK Coefficients for design matrix XX
λ\lambda [K,K+Kλ)[K, K + K_\lambda) KλK_\lambda Non-singleton nest dissimilarity parameters
δ\delta [K+Kλ,K+Kλ+Jasc)[K + K_\lambda, K + K_\lambda + J_{\text{asc}}) 00, J1J-1, or JJ Free alternative-specific constants

where KλK_\lambda is the number of non-singleton nests and Jasc=0J_{\text{asc}}=0 when use_asc = FALSE, J1J-1 without an outside option, or JJ with an outside option.

Code reference: src/nestlogit.cpp

5.2 Singleton Nest Handling

At startup, the implementation identifies which nests are singletons (contain exactly one alternative). These nests: - Have their λ\lambda fixed to 1 (no contribution to the upper-level logit denominator beyond their single utility term). - Are excluded from the estimated parameter vector. - Are tracked via nest_k_to_theta_idx, an integer vector of length KK where entry kk holds the corresponding index in θ\theta for non-singleton nests and 1-1 for singletons.

This ensures that the NL model degenerates gracefully to MNL on a per-nest basis when nests are singletons.

Code reference: src/nestlogit.cpp

5.3 Data Organization

  • Design matrix XX: Stacked matrix of dimension (iMi)×K(\sum_i M_i) \times K, where MiM_i is the number of inside alternatives for individual ii.
  • alt_idx: 1-based indices mapping rows of XX to global alternative IDs.
  • nest_idx: 1-based nest assignment of length JJ (number of unique inside alternatives), not length Mi\sum M_i. Accessed via nest_idx.elem(alt_idx0_i) to handle varying choice sets.
  • choice_idx: 1-based local row position of the chosen inside alternative within each situation’s block; 0 for the outside option.
  • Prefix sums SS: Used for efficient slicing into the stacked data: Si=j<iMjS_i = \sum_{j < i} M_j.

Code reference: src/nestlogit.cpp

5.4 Base Utility Pre-computation

Prior to the parallel loop, all systematic utilities Vij=Xijβ+δjV_{ij} = X_{ij}\beta + \delta_j are computed in a single pass:

base_util = X * beta                 // single BLAS dgemm
if use_asc: base_util += delta[alt_idx0]

This avoids redundant matrix-vector products inside the per-individual loop.

Code reference: src/nestlogit.cpp

5.5 OpenMP Parallelization

The implementation parallelizes over individuals using OpenMP: - Each thread maintains local accumulators for log-likelihood and gradient. - nest_k_to_theta_idx is copied thread-privately to avoid false sharing. - Thread results are combined using #pragma omp critical sections. - Dynamic scheduling balances load across individuals with varying choice set sizes.

Code reference: src/nestlogit.cpp

5.6 Negated Objectives

The likelihood/gradient kernel returns: - (θ)-\ell(\theta) (negated log-likelihood) - (θ)-\nabla\ell(\theta) (negated gradient)

for compatibility with minimization routines (e.g., nloptr) that minimize a loss function rather than maximize a likelihood. The analytical and numeric Hessian kernels return 2-\nabla^2\ell; the BHHH kernel instead returns the positive-semidefinite OPG information approximation iwisisiT\sum_iw_is_is_i^T.

5.7 Finite-Value Guards

The likelihood kernel replaces a non-finite chosen log probability by 1010-10^{10}. If the final negated objective is non-finite it returns 101010^{10} and a zero gradient; isolated non-finite gradient entries are zeroed. The analytical Hessian skips a situation whose chosen log probability is non-finite, symmetrizes the aggregate, and replaces any remaining non-finite entries by zero. These rules are optimizer failure guards, not part of the regular finite-parameter nested-logit criterion; encountering them calls for rescaling or revising the specification.

Code reference: src/nestlogit.cpp


6. Post-Estimation Quantities

6.1 Choice Probabilities (predict)

The joint probability is the decomposition from §2.1:

Pij=P(jk(j))Pk(j) P_{ij} = P(j \mid k(j)) \cdot P_{k(j)}

with P(jk)P(j \mid k) and PkP_k given in §§2.3–2.4. nl_predict returns individual-level probabilities PijP_{ij} and systematic utilities VijV_{ij} for every observation row. nl_predict_shares aggregates over individuals to obtain weighted market shares:

ŝj=i=1NwiPiji=1Nwi \hat{s}_j = \frac{\sum_{i=1}^{N} w_i \, P_{ij}}{\sum_{i=1}^{N} w_i}

Code reference: src/nestlogit.cpp


6.2 Elasticities

6.2.1 Semi-elasticity with respect to utility

Let r=k(j)r = k(j) be the nest of the responding alternative jj and s=k(a)s = k(a) be the nest of the perturbed alternative aa. From §3.1, the derivative of logPij\log P_{ij} with respect to the systematic utility of any alternative aa is:

logPijVia=𝟏a=jλr+(11λr)𝟏s=rP(ar)Pia \frac{\partial \log P_{ij}}{\partial V_{ia}} = \frac{\mathbf{1}_{a=j}}{\lambda_r} + \left(1 - \frac{1}{\lambda_r}\right)\mathbf{1}_{s=r} \, P(a \mid r) - P_{ia}

This is the general expression; the gradient formula in §3.1 applies it only to the chosen alternative, whereas here we evaluate it for all pairs (j,a)(j, a) to construct the full elasticity matrix.

6.2.2 Elasticity of PijP_{ij} with respect to covariate kk of alternative aa

Since Via/xia,k=βk\partial V_{ia} / \partial x_{ia,k} = \beta_k:

Eij,iak=Pijxia,kxia,kPij=βkxia,klogPijVia E_{ij,ia}^{k} = \frac{\partial P_{ij}}{\partial x_{ia,k}} \cdot \frac{x_{ia,k}}{P_{ij}} = \beta_k \, x_{ia,k} \cdot \frac{\partial \log P_{ij}}{\partial V_{ia}}

Substituting the three cases:

Case Condition Semi-elasticity logPij/Via\partial \log P_{ij}/\partial V_{ia}
Own a=ja = j 1λr+(11λr)P(jr)Pij\dfrac{1}{\lambda_r} + \left(1 - \dfrac{1}{\lambda_r}\right) P(j \mid r) - P_{ij}
Cross, same nest s=r,ajs = r,\; a \neq j (11λr)P(ar)Pia\left(1 - \dfrac{1}{\lambda_r}\right) P(a \mid r) - P_{ia}
Cross, different nest srs \neq r Pia-P_{ia}

Reduction to MNL. When λk=1\lambda_k = 1 for all nests the within-nest term (11/λr)(1 - 1/\lambda_r) vanishes and the conditional probability drops out, giving logPij/Via=𝟏a=jPia\partial \log P_{ij}/\partial V_{ia} = \mathbf{1}_{a=j} - P_{ia}, which is exactly the MNL semi-elasticity (§3.1 of the MNL document).

Outside option. When an outside option is present it occupies its own singleton nest with λ0=1\lambda_0 = 1 and xi0,k=0x_{i0,k} = 0. Its row (responding = outside option) has semi-elasticity Pia-P_{ia} for every inside alternative aa (different nest, §3.1); its column (perturbed = outside option) is identically zero because βk0=0\beta_k \cdot 0 = 0.

The implementation accumulates wiEij,iakw_i \cdot E_{ij,ia}^k across individuals and divides by iwi\sum_i w_i to produce a weighted average of individual probability elasticities. This is not generally the elasticity of an aggregate share under a common market-level perturbation when attributes vary across situations. Rows index responding alternatives and columns perturbed alternatives.

Code reference: src/nestlogit.cpp


6.3 Diversion Ratios

6.3.1 Definition

The utility-based diversion ratio from losing alternative jj to receiving alternative kk is:

DR(jk)=Qk/VijQj/Vij DR(j \to k) = -\frac{\partial Q_k / \partial V_{ij}}{\partial Q_j / \partial V_{ij}}

where Qm=iwiPimQ_m = \sum_i w_i P_{im} is aggregate demand and the perturbation is through the systematic utility of the losing alternative jj.

6.3.2 Partial derivatives of demand

Using Pim/Vij=Pim(logPim/Vij)\partial P_{im}/\partial V_{ij} = P_{im} \cdot (\partial \log P_{im}/\partial V_{ij}) and the semi-elasticity from §6.2.1, the three cases with r=k(j)r = k(j):

PimVij={Pij[1λr+(11λr)P(jr)Pij]m=jPim[(11λr)P(jr)Pij]k(m)=r,mjPimPijk(m)r \frac{\partial P_{im}}{\partial V_{ij}} = \begin{cases} P_{ij}\!\left[\dfrac{1}{\lambda_r} + \left(1 - \dfrac{1}{\lambda_r}\right) P(j \mid r) - P_{ij}\right] & m = j \\[6pt] P_{im}\!\left[\left(1 - \dfrac{1}{\lambda_r}\right) P(j \mid r) - P_{ij}\right] & k(m) = r,\; m \neq j \\[6pt] -P_{im} \, P_{ij} & k(m) \neq r \end{cases}

6.3.3 Utility Perturbation and Covariate Interpretation

The implemented matrix is defined with respect to a common additive perturbation of VijV_{ij}. If a fixed-coefficient attribute of alternative jj receives the same additive change dxdx in every situation, dVij=βrdxdV_{ij}=\beta_r dx, so the common scalar cancels:

DR(jk)=βrdxiwi(Pik/Vij)βrdxiwi(Pij/Vij)=iwi(Pik/Vij)iwi(Pij/Vij) DR(j \to k) = -\frac{\beta_r dx\sum_i w_i \,(\partial P_{ik}/\partial V_{ij})} {\beta_r dx\sum_i w_i \,(\partial P_{ij}/\partial V_{ij})} = -\frac{\sum_i w_i \,(\partial P_{ik}/\partial V_{ij})} {\sum_i w_i \,(\partial P_{ij}/\partial V_{ij})}

It is in this additive-shift sense that NL diversion is independent of the chosen fixed covariate. For a proportional perturbation dxi=xij,rdlogxdx_i=x_{ij,r}d\log x, the values xij,rx_{ij,r} remain inside both population sums and generally do not cancel. The kernel does not compute that attribute-specific proportional diversion. In MXL even a common additive perturbation of a random-coefficient attribute carries draw-specific βirs\beta_{ir}^s, so the coefficient cannot be factored out.

6.3.4 Population aggregation and column-sum property

Define:

num(k,j)=i=1Nwi(PikVij),den(j)=i=1NwiPijVij \text{num}(k, j) = \sum_{i=1}^{N} w_i \left(-\frac{\partial P_{ik}}{\partial V_{ij}}\right), \qquad \text{den}(j) = \sum_{i=1}^{N} w_i \frac{\partial P_{ij}}{\partial V_{ij}}

so that DR(jk)=num(k,j)/den(j)DR(j \to k) = \text{num}(k,j) \,/\, \text{den}(j) for kjk \neq j.

Columns sum to 1. The fundamental identity mPim/Vij=0\sum_{m} \partial P_{im}/\partial V_{ij} = 0 (probabilities sum to 1 for every individual and every perturbation direction, including the outside option when present) gives:

kjPikVij=PijVijkjnum(k,j)=den(j)kjDR(jk)=1 \sum_{k \neq j} \frac{\partial P_{ik}}{\partial V_{ij}} = -\frac{\partial P_{ij}}{\partial V_{ij}} \implies \sum_{k \neq j} \text{num}(k, j) = \text{den}(j) \implies \sum_{k \neq j} DR(j \to k) = 1

When an outside option is present it acts as both a source (it can lose demand) and a destination (it can receive diverted demand), so it appears in both the row index kk and the column index jj of the Jtotal×JtotalJ_{\text{total}} \times J_{\text{total}} diversion matrix, and the column sums still equal 1 over all alternatives including the outside option. Because its systematic utility is fixed at zero in estimation, the outside-as-source column is a derivative with respect to a hypothetical perturbation of that normalized utility, not an available outside-option covariate.

6.3.5 Reduction to MNL at λ=1\lambda = 1

When all λk=1\lambda_k = 1 the cross-same-nest case collapses to the cross-different-nest case (Pim/Vij=PimPij\partial P_{im}/\partial V_{ij} = -P_{im} P_{ij} for mjm \neq j) and the own case gives Pij/Vij=Pij(1Pij)\partial P_{ij}/\partial V_{ij} = P_{ij}(1 - P_{ij}). Substituting:

DR(jk)|λ=1=iwiPijPikiwiPij(1Pij) DR(j \to k)\big|_{\lambda=1} = \frac{\sum_i w_i \, P_{ij} \, P_{ik}}{\sum_i w_i \, P_{ij} (1 - P_{ij})}

which is the MNL diversion ratio (§6.3 of the MNL document).

Code reference: src/nestlogit.cpp


6.4 BLP Share Inversion

6.4.1 Problem statement

Given observed market shares sj*s_j^*, find the ASC vector δ\delta such that the NL model reproduces those shares:

ŝj(δ)=sj*j \hat{s}_j(\delta) = s_j^* \quad \forall j

6.4.2 Damped contraction mapping

Under the usual feasibility, connected-substitutes, and normalization conditions, the BLP fixed-point iteration is

δ(t+1)=δ(t)+κ(logs*logŝ(δ(t))) \delta^{(t+1)} = \delta^{(t)} + \kappa \bigl(\log s^* - \log \hat{s}(\delta^{(t)})\bigr)

with κ=1\kappa=1 giving the undamped update. Existence, uniqueness, and global convergence are properties of the share mapping and target—not an unconditional guarantee for every numerical input. Predicted shares ŝ(δ(t))\hat{s}(\delta^{(t)}) are computed via the NL formula:

ŝj(δ(t))=i=1NwiPij(δ(t))i=1Nwi \hat{s}_j(\delta^{(t)}) = \frac{\sum_{i=1}^{N} w_i \, P_{ij}(\delta^{(t)})}{\sum_{i=1}^{N} w_i}

where Pij(δ(t))=P(jk(j))Pk(j)P_{ij}(\delta^{(t)}) = P(j \mid k(j)) \cdot P_{k(j)} is evaluated at the current δ(t)\delta^{(t)} with β\beta and λ\lambda held fixed.

6.4.3 Damping for nested models

For strongly nested data (small λk\lambda_k) the plain update can overshoot numerically. Choosing 0<κ<10<\kappa<1 may stabilize iteration. A possible empirical starting heuristic is

κminkλk \kappa \approx \min_k \lambda_k

but this is not a theorem or an automatic rule in the package. The kernel accepts the numeric damping value as supplied and does not constrain it to (0,1](0,1]; the analyst must inspect convergence and resulting share residuals.

6.4.4 Baseline re-normalization

Without an outside option, delta is a full length-JJ vector and is centered initially and on return by subtracting its first inside entry, so the returned baseline is zero. With an outside option, supplied and returned delta contain the JJ inside ASCs only. The kernel works internally with a prepended outside entry, pins that entry at zero after each update, and returns the inside subvector without subtracting the first inside ASC.

All target shares must be strictly positive and have length JJ (no outside) or J+1J+1 (outside first). The kernel does not check that they sum to one. Convergence uses the largest absolute change in the full working vector; reaching max_iter prints a warning and returns the last iterate without a separate convergence flag.

Note on the lambda argument. nl_blp_contraction expects a full length-nnestsn_{\text{nests}} vector where singleton nests have their entry set to 1. This differs from the estimated parameter block λ\lambda in θ\theta, which contains only non-singleton entries. The caller is responsible for expanding the estimated lambdas into the full vector before invoking the contraction.

Code reference: src/nestlogit.cpp

6.5 Willingness to Pay

Utility is linear in covariates, so willingness to pay is the same marginal rate of substitution as in the MNL model: for attribute kk and price coefficient α=βp\alpha = \beta_p,

WTPk=βkα,SÊ=gTV̂(k,p)g,g=(1/αβk/α2) \mathrm{WTP}_k = -\frac{\beta_k}{\alpha}, \qquad \widehat{\mathrm{SE}} = \sqrt{\nabla g^T \, \hat{V}_{(k,p)} \, \nabla g}, \quad \nabla g = \begin{pmatrix} -1/\alpha \\ \beta_k/\alpha^2 \end{pmatrix}

with V̂(k,p)\hat{V}_{(k,p)} the 2×22 \times 2 block of the coefficient covariance. The nest parameters λ\lambda rescale within-nest substitution but do not enter the ratio of marginal utilities, so they affect WTP only through the estimated covariance of (βk,α)(\beta_k, \alpha). ASCs may also be used as the numerator (δj/α-\delta_j/\alpha). See §8 of the MNL document for the full derivation and caveats.

Code reference: R/wtp.R

6.6 Consumer Surplus and the Nested Logsum

For the nested logit, expected maximum utility is the two-level logsum below plus the scenario-invariant extreme-value location constant (omitted by logsum(), as in MNL):

logsumi=logDi=log(lexp(λllogIl)[+1]),logIl=logjBlCiexp(Vijλl) \mathrm{logsum}_i = \log D_i = \log\left( \sum_{l} \exp\big(\lambda_l \log I_l\big) \; [+\, 1] \right), \qquad \log I_l = \log \sum_{j \in B_l \cap C_i} \exp\!\left(\frac{V_{ij}}{\lambda_l}\right)

where the +1=exp(0)+1 = \exp(0) term appears when an outside option is present and singleton nests have λl=1\lambda_l = 1 (§5.2). Both levels are computed with the max-subtraction trick (§2.7).

Two useful identities:

  • Reduction to MNL. With all λl=1\lambda_l = 1, λllogIl=logjBlexp(Vij)\lambda_l \log I_l = \log \sum_{j \in B_l} \exp(V_{ij}) and the nested logsum collapses to the MNL logsum logjexp(Vij)\log \sum_j \exp(V_{ij}).
  • Outside-option link. Since Pi0=1/DiP_{i0} = 1 / D_i (§2.5), the logsum equals logPi0-\log P_{i0} — a direct consistency check against the probability kernel.

Expected consumer surplus follows Train (2009, Ch. 3) exactly as in the MNL case:

𝔼[CSi]=logsumiα \mathbb{E}[CS_i] = \frac{\mathrm{logsum}_i}{-\alpha}

with the same caveats: no income effects, and CS levels inherit the ASC normalization, so only differences across scenarios (counterfactual newdata vs. baseline) are meaningful. The implementation reports point estimates for NL (the delta-method SE of the mean CS is currently provided for MNL only; Krinsky–Robb resampling of the coefficients is the practical interval method here). The routine does not enforce α<0\alpha<0; interpreting α-\alpha as positive marginal utility of income requires the analyst to verify the estimated sign.

Code reference: R/surplus.R

6.7 Goodness of Fit

The measures are model-agnostic and identical to §10 of the MNL document, computed from the NL log-likelihood and predicted probabilities:

  • McFadden pseudo R²: R2=1(θ̂)/0R^2 = 1 - \ell(\hat\theta)/\ell_0 and Radj2=1((θ̂)K)/0R^2_{\text{adj}} = 1 - (\ell(\hat\theta) - K)/\ell_0, with KK counting all estimated parameters including the λ\lambda block.
  • Equal-shares null (default, exact for unbalanced sets and weights): 0=iwilog(Mi+𝟏outside)\ell_0 = -\sum_i w_i \log(M_i + \mathbf{1}_{\text{outside}}).
  • Market-shares null (constants-only closed form): 0=cjNjlog(sj)\ell_0 = c\sum_j N_j \log(s_j), where cc is the common weight; requires identical choice-set composition across individuals and uniform weights. The constants-only model is itself an MNL—at β=0\beta = 0 and free ASCs the nest structure is not identified from constant shares—so the same closed form applies.
  • Hit rate: weighted share of choice situations whose observed choice has the highest predicted NL probability; with an outside option the outside good competes with Pi0=1jPijP_{i0} = 1 - \sum_j P_{ij}.

Code reference: R/gof.R


7. Choice-Based Sampling and WESML Weighting

7.1 Endogenous Stratified (Choice-Based) Sampling

Under random (exogenous) sampling each choice situation is drawn independently of its outcome. Under choice-based (endogenous stratified) sampling the strata are defined by the chosen alternative jij_i and situations are drawn with stratum-specific frequencies — for example, deliberately oversampling individuals who chose a rare alternative. Let Q(j)Q(j) be the population share of alternative jj and H(j)H(j) the sample share of choosers of jj.

Unlike the MNL special case (a full set of ASCs leaves the slopes consistent), the nested logit has no such free pass: the dissimilarity parameters λl\lambda_l enter the within- and between-nest probabilities nonlinearly, so choice-based sampling generally biases the slopes β\beta, the constants δ\delta, and the λ\lambda block. Weighting is therefore required for consistent estimation of the population parameters.

7.2 The WESML Weighted Log-Likelihood

Manski and Lerman (1977) restore consistency by weighting each situation’s contribution by the ratio of population to sample share of its chosen alternative,

wi=Q(ji)H(ji),W(θ)=i=1NwilogPiji(θ). w_i = \frac{Q(j_i)}{H(j_i)}, \qquad \ell^{W}(\theta) = \sum_{i=1}^{N} w_i \log P_{i j_i}(\theta).

The maximizer θ̂\hat\theta is invariant to multiplying every wiw_i by a common positive constant, so the weights may be normalized to mean 1 without changing the estimates.

7.3 Robust (Sandwich) Variance: the w2w^2 Meat

WESML is a weighted M-estimator solving iwisi(θ̂)=0\sum_i w_i\, s_i(\hat\theta) = 0, where si=logPiji/θs_i = \partial \log P_{i j_i}/\partial\theta is the full per-situation score over the β\beta, λ\lambda and δ\delta blocks ($$3) and HiH_i its Hessian ($$4). Its robust (Huber–White) asymptotic variance is the sandwich

V=A1BA1,A=iwi(Hi),B=iwi2sisi. V = A^{-1} B A^{-1}, \qquad A = \sum_{i} w_i\,(-H_i), \qquad B = \sum_{i} w_i^{2}\, s_i s_i^{\top}.

The weight enters the bread AA linearly, but the meat BB carries the weight squared: the contribution of situation ii to the estimating equation is wisiw_i s_i, so its variance involves (wisi)(wisi)=wi2sisi(w_i s_i)(w_i s_i)^{\top} = w_i^{2}\, s_i s_i^{\top}. The score sis_i is assembled exactly as in the gradient kernel ($$3.3–3.4): the β\beta and δ\delta blocks from grad_vec, and the λl\lambda_l blocks from the per-nest expression (𝟏{l=li}Pil)[logIilλl1jBlPij|lVij]+𝟏{l=li}λl2(jBlPij|lVijViji)(\,\mathbf{1}\{l = l_i\} - P_{il}\,)\big[\log I_{il} - \lambda_l^{-1}\!\sum_{j\in B_l} P_{ij|l} V_{ij}\big] + \mathbf{1}\{l=l_i\}\,\lambda_l^{-2}\big(\sum_{j\in B_l} P_{ij|l}V_{ij} - V_{ij_i}\big), with singleton nests (λl1\lambda_l \equiv 1) contributing no score.

As in the MNL/MXL cases, both naive variances are wrong under weighting: the inverse-Hessian A1A^{-1} assumes the information-matrix equality A=BA = B (which fails once the wiw_i are non-degenerate), and ordinary BHHH/OPG (iwisisi)1\big(\sum_i w_i\, s_i s_i^{\top}\big)^{-1} uses the weight to the first power, not the second. The sandwich is invariant to the weight scale: AcAA \to cA, Bc2BB \to c^2 B, hence VA1BA1V \to A^{-1} B A^{-1}.

7.4 Scope: Robust vs. Design-Based Variance

The estimator implemented here is the robust weighted-M-estimator (Huber–White) variance, with uncentered meat B=iwi2sisiB = \sum_i w_i^{2}\, s_i s_i^{\top} — the asymptotic variance under variable-probability sampling. The smaller stratum-centered (design-based) variance for a fixed-quota design is out of scope; see Manski & McFadden (1981) and Cosslett (1981).

7.5 Implementation and Cluster-Robust Extension

The common post-estimation path obtains the N×pN\times p matrix SS of weight-free scores from nl_scores_parallel (singleton lambda rows are absent because those parameters are not in θ\theta), then forms

A=𝚗𝚕_𝚕𝚘𝚐𝚕𝚒𝚔_𝚑𝚎𝚜𝚜𝚒𝚊𝚗_𝚙𝚊𝚛𝚊𝚕𝚕𝚎𝚕(θ̂;w),B=(diag(w)S)T(diag(w)S). A=\texttt{nl\_loglik\_hessian\_parallel}(\widehat\theta;w), \qquad B=(\operatorname{diag}(w)S)^T(\operatorname{diag}(w)S).

For a fit whose selected method is the numeric NL Hessian, the post-hoc bread uses the numeric oracle instead. The eager fit-time robust path is algebraically identical and may obtain BB by calling the BHHH accumulator with weights = w^2. For cluster labels g(i)g(i), se_method = "cluster" uses

Bcluster=g(i:g(i)=gwisi)(i:g(i)=gwisi)T, B_{\mathrm{cluster}}=\sum_g \left(\sum_{i:g(i)=g}w_is_i\right) \left(\sum_{i:g(i)=g}w_is_i\right)^T,

with no finite-cluster correction. These matrices are combined as V=A1BA1V=A^{-1}BA^{-1}. User-facing entry points: wesml_weights() computes the Manski–Lerman weights from the population shares QQ, while sample_by_choice() draws a choice-based sample and attaches those weights; run_nestlogit(..., se_method = "sandwich") estimates with the robust variance; wesml_vcov() returns it post hoc. Passing run_nestlogit(..., weights_col = ) collapses a row-level weight column to one weight per choice situation (validated constant within id), and a provenance guard prevents a WESML-labeled sample from being silently fit unweighted.

Code reference: nl_scores_parallel() / nl_bhhh_parallel() in src/nestlogit.cpp; compute_sandwich_vcov(), .score_meat(), and .assemble_score_vcov() in R/classes.R; wesml_weights() / sample_by_choice() in R/sampling.R.


References

  • McFadden, D. (1978). Modelling the choice of residential location. In A. Karlqvist et al. (Eds.), Spatial Interaction Theory and Planning Models (pp. 75-96). North-Holland.
  • Ben-Akiva, M., & Lerman, S. R. (1985). Discrete Choice Analysis: Theory and Application to Travel Demand. MIT Press.
  • Koppelman, F. S., & Wen, C.-H. (1998). Alternative nested logit models: structure, properties and estimation. Transportation Research Part B, 32(5), 289-298.
  • Hensher, D. A., & Greene, W. H. (2002). Specification and estimation of the nested logit model: alternative normalisations. Transportation Research Part B, 36(1), 1-17.
  • Heiss, F. (2002). Structural choice analysis with nested logit models. The Stata Journal, 2(3), 227-252.
  • Berry, S., Levinsohn, J., & Pakes, A. (1995). Automobile prices in market equilibrium. Econometrica, 63(4), 841–890.
  • Train, K. E. (2009). Discrete Choice Methods with Simulation (2nd ed.). Cambridge University Press. Chapter 4.
  • Manski, C. F., & Lerman, S. R. (1977). The estimation of choice probabilities from choice based samples. Econometrica, 45(8), 1977–1988.
  • Manski, C. F., & McFadden, D. (1981). Alternative estimators and sample designs for discrete choice analysis. In C. F. Manski & D. McFadden (Eds.), Structural Analysis of Discrete Data with Econometric Applications (pp. 2–50). MIT Press.
  • Cosslett, S. R. (1981). Maximum likelihood estimator for choice-based samples. Econometrica, 49(5), 1289–1316.