Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

- **Large-scale urban models**: 100K+ choosers, 1K+ alternatives
- **Sampling-based estimation**: Most alternatives are irrelevant; only a sampled subset is evaluated per chooser
- **Spatial correlation**: Nearby alternatives share unobserved attributes (via `graph=` on any model)
- **Spatial dependence**: Nearby alternatives can affect each other or share unobserved attributes (via `graph=` on any model)
- **Heterogeneous preferences**: Mixed logit for random taste variation
- **Nested structure**: Nested logit for hierarchical choice (e.g., county → tract → block)
- **JAX-native computation**: JIT-compiled kernels, GPU acceleration, automatic differentiation
Expand All @@ -13,8 +13,18 @@ The package is **not** a general-purpose ML library. It is specifically for stru

## Features

LocPick can automate the creation of choice tables for estimation or simulation, using census choice sets, uniform or weighted random sampling of alternatives, generated interaction terms, and cartesian merges. A unique feature is the implementation of [*spatial* choice models](https://linkinghub.elsevier.com/retrieve/pii/S0191261503000055), which assume that nearby alternatives are more similar (closer substitutes).
LocPick can automate the creation of choice tables for estimation or simulation, using census choice sets, uniform or weighted random sampling of alternatives, generated interaction terms, and cartesian merges. A unique feature is the implementation of *spatial* choice models, which take one of two forms.

- The [Bhat et al](https://linkinghub.elsevier.com/retrieve/pii/S0191261503000055) approach is similar to a spatial error model, assuming that nearby alternatives are more similar (closer substitutes).
- The SAR style approach assumes that the structural utility of each alternative $V$ has a simultaneous autoregressive structure, and is estimated with either [PML](http://dx.doi.org/10.1016/j.regsciurbeco.2009.09.004) or [GMM](https://www.sciencedirect.com/science/article/pii/S0166046217300625)

It also provides tools for Monte Carlo simulation of choices given probability distributions from fitted models, with fast algorithms for independent or capacity-constrained choices.

LocPick includes classic and spatially-correlated Multinomial Logit, Nested Logit, Mixed, and Mixed/Nested Logit estimators; its internal data pipeline is designed around pandas inputs, xarray-backed alignment, and NumPy/JAX-ready arrays.
LocPick includes estimators for classic, spatially-correlated, and simultaneous autoregressive:

- Multinomial Logit
- Nested Logit
- Mixed Logit and
- Mixed/Nested

models, and an internal data pipeline designed around pandas inputs, xarray-backed alignment, and NumPy/JAX-ready arrays.
96 changes: 94 additions & 2 deletions docs/source/_static/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ @article{abbe2007NormalizationCorrelation
keywords = {Behavior models,Correlations,Generalized extreme-value,Logit
models,Model estimation,Route choice},
}

@article{al-haideri2026CyclistsCrossing,
title = {Cyclists' Crossing Behaviour at Roundabouts: {{A Generalized
Spatially Correlated Nested Logit}} Model},
Expand Down Expand Up @@ -70,7 +69,6 @@ @article{al-haideri2026CyclistsCrossing
behavioural mechanisms underlying cyclists' crossing decisions.},
langid = {english},
}

@article{anselin1988spatial,
title = {Spatial Econometrics: Methods and Models},
author = {Anselin, Luc},
Expand Down Expand Up @@ -246,6 +244,69 @@ @article{dugundji2013StructureEmergence
networks,Spatial interaction,Transportation demand},
}

@article{krisztin2021BayesianSpatial,
title = {A {{Bayesian}} Spatial Autoregressive Logit Model with an Empirical
Application to {{European}} Regional {{FDI}} Flows},
author = {Krisztin, Tamás and Piribauer, Philipp},
date = {2021-07-01},
journaltitle = {Empirical Economics},
shortjournal = {Empir Econ},
volume = {61},
number = {1},
pages = {231--257},
issn = {1435-8921},
doi = {10.1007/s00181-020-01856-w},
url = {https://doi.org/10.1007/s00181-020-01856-w},
urldate = {2026-06-18},
abstract = {In this paper, we propose a Bayesian estimation approach for a
spatial autoregressive logit specification. Our approach relies on
recent advances in Bayesian computing, making use of Pólya–Gamma
sampling for Bayesian Markov-chain Monte Carlo algorithms. The
proposed specification assumes that the involved log-odds of the
model follow a spatial autoregressive process. Pólya–Gamma sampling
involves a computationally efficient treatment of the spatial
autoregressive logit model, allowing for extensions to the existing
baseline specification in an elegant and straightforward way. In a
Monte Carlo study we demonstrate that our proposed approach
markedly outperforms alternative specifications in terms of
parameter precision. The paper moreover illustrates the performance
of the proposed spatial autoregressive logit specification using
pan-European regional data on foreign direct investments. Our
empirical results highlight the importance of accounting for
spatial dependence when modelling European regional FDI flows.},
langid = {english},
keywords = {Bayesian MCMC estimation,C11,C21,C25,European regions,F23,FDI
flows,R11,R30,Spatial autoregressive logit},
}

@article{krisztin2022SpatialMultinomial,
title = {A Spatial Multinomial Logit Model for Analysing Urban Expansion},
author = {Krisztin, Tamás and Piribauer, Philipp and Wögerer, Michael},
date = {2022-04-03},
journaltitle = {Spatial Economic Analysis},
volume = {17},
number = {2},
pages = {223--244},
publisher = {Routledge},
issn = {1742-1772},
doi = {10.1080/17421772.2021.1933579},
url = {https://doi.org/10.1080/17421772.2021.1933579},
urldate = {2026-06-18},
abstract = {The paper proposes a Bayesian multinomial logit model to analyse
spatial patterns of urban expansion. The specification assumes that
the log-odds of each class follow a spatial autoregressive process.
Using recent advances in Bayesian computing, our model allows for a
computationally efficient treatment of the spatial multinomial
logit model. This allows us to assess spillovers between regions
and across land-use classes. In a series of Monte Carlo studies, we
benchmark our model against other competing specifications. The
paper also showcases the performance of the proposed specification
using European regional data. Our results indicate that spatial
dependence plays a key role in the land-sealing process of cropland
and grassland. Moreover, we uncover land-sealing spillovers across
multiple classes of arable land.},
}

@article{mcfadden1978goodness,
title = {Goodness-of-Fit for the Multinomial Logit Model},
author = {McFadden, Daniel},
Expand Down Expand Up @@ -304,6 +365,37 @@ @article{perez-lopez2022SpatiallyCorrelated
langid = {english},
}

@article{smirnov2010ModelingSpatial,
title = {Modeling Spatial Discrete Choice},
author = {Smirnov, Oleg A.},
date = {2010-09},
journaltitle = {Regional Science and Urban Economics},
volume = {40},
number = {5},
pages = {292--298},
publisher = {Elsevier B.V.},
issn = {01660462},
doi = {10.1016/j.regsciurbeco.2009.09.004},
url = {http://dx.doi.org/10.1016/j.regsciurbeco.2009.09.004},
abstract = {The paper presents a basic spatial discrete choice modeling
framework obtained by applying random utility theory to discrete
choices made by heterogeneous spatially dependent individuals. The
newly developed framework has two main advantages over existing
approaches. First, individual decision-makers are no longer assumed
to be independent and non-interacting but spatially interdependent
in their preferences facilitating the development of applied
discrete choice models using a wide range of spatial data. Second,
pseudo maximum likelihood estimator is developed for this model
that is consistent and computationally feasible for large datasets.
The performance of the pseudo maximum likelihood estimator for the
spatial discrete choice model is illustrated using simulated data.
© 2009 Elsevier B.V.},
isbn = {0166-0462},
keywords = {Discrete choice,Maximum likelihood,Spatial interdependence,Spatial
random utility,urban-modeling},
annotation = {44 citations (Crossref) [2022-08-11]},
}

@book{train2009discrete,
title = {Discrete Choice Methods with Simulation},
author = {Train, Kenneth E.},
Expand Down
13 changes: 2 additions & 11 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,18 @@ Model Specification
Models
------

.. currentmodule:: locpick.models.mnl
.. currentmodule:: locpick.models.choice_model

.. autosummary::
:toctree: generated/

MNL :no-index:
ChoiceModel :no-index:

.. currentmodule:: locpick.models.nested

.. autosummary::
:toctree: generated/

NestedMNL :no-index:
NestSpec :no-index:
NestingTree :no-index:

Expand All @@ -64,16 +63,8 @@ Models
.. autosummary::
:toctree: generated/

MixedMNL :no-index:
ParamDistribution :no-index:

.. currentmodule:: locpick.models.mixed_nested

.. autosummary::
:toctree: generated/

MixedNestedMNL :no-index:

.. currentmodule:: locpick.models.scl

.. autosummary::
Expand Down
1 change: 1 addition & 0 deletions docs/source/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Mixed Logit <user-guide/mixed>
Spatial Mixed Logit <user-guide/spatial_mixed>
Spatial Nested Logit <user-guide/spatial_nested>
Spatial Mixed-Nested Logit <user-guide/spatial_mixed_nested>
SAR-MNL Demo <user-guide/sar_mnl_demo>
Simulated Location Choice Demo <user-guide/livelike_locpick_household_tract_demo>
Spatial Models Demo <user-guide/spatial_models_demo>
Sampling Correction <user-guide/sampling>
Expand Down
4 changes: 2 additions & 2 deletions docs/source/user-guide/choicetable.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The `ChoiceTable` class is the primary data container for location choice modeli
## Quick Start

```python
from locpick import ChoiceTable, MNL
from locpick import ChoiceTable, ChoiceModel

# Create a ChoiceTable from chooser and alternative data
ct = ChoiceTable.from_tables(
Expand All @@ -26,7 +26,7 @@ ct = ChoiceTable.from_tables(
)

# Estimate an MNL model
model = MNL(ct, formula="cost + time - 1")
model = ChoiceModel(ct, formula="cost + time - 1")
result = model.fit()
print(result.summary())
```
Expand Down
8 changes: 4 additions & 4 deletions docs/source/user-guide/inference.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ Compare two nested models:
```python
from locpick import lr_test

restricted = MNL(ct, formula="cost + time").fit()
unrestricted = NestedMNL(ct, formula="cost + time", nests=tree).fit()
restricted = ChoiceModel(ct, formula="cost + time").fit()
unrestricted = ChoiceModel(ct, formula="cost + time", nests=tree).fit()

result = lr_test(restricted, unrestricted)
print(result.summary())
Expand Down Expand Up @@ -75,8 +75,8 @@ restrictive nested or mixed alternative:
```python
from locpick import hausman_test

mnl_fit = MNL(ct, formula="cost + time").fit()
nested_fit = NestedMNL(ct, formula="cost + time", nests=tree).fit()
mnl_fit = ChoiceModel(ct, formula="cost + time").fit()
nested_fit = ChoiceModel(ct, formula="cost + time", nests=tree).fit()

# H0: MNL is consistent (IIA holds). Compare on the common parameters.
result = hausman_test(efficient=mnl_fit, consistent=nested_fit)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"from livelike.config import up_expanded_attributes_household\n",
"from pymedm import PMEDM\n",
"\n",
"from locpick import MNL, ChoiceTable"
"from locpick import ChoiceModel, ChoiceTable"
]
},
{
Expand Down Expand Up @@ -435,7 +435,7 @@
"source": [
"formula_1 = \"median_contract_rent + median_home_value + median_household_income + p_poverty_rate\"\n",
"\n",
"model_1 = MNL(ct, formula=formula_1)\n",
"model_1 = ChoiceModel(ct, formula=formula_1)\n",
"result_1 = model_1.fit()"
]
},
Expand Down Expand Up @@ -474,7 +474,7 @@
"_interaction_terms = [k for k in interactions.keys() if k in ct._ds.data_vars]\n",
"formula_2 = \" + \".join(_base_terms + _interaction_terms)\n",
"\n",
"model_2 = MNL(ct, formula=formula_2)\n",
"model_2 = ChoiceModel(ct, formula=formula_2)\n",
"result_2 = model_2.fit()\n",
"print(result_2.summary())"
]
Expand Down
6 changes: 3 additions & 3 deletions docs/source/user-guide/mixed.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ This user guide is a placeholder. Full content will be added in a future release

## Overview

The `MixedMNL` class estimates mixed logit (random coefficients) models, which generalize MNL by allowing coefficients to follow random distributions.
The `ChoiceModel` class estimates mixed logit (random coefficients) models when the `random_params` parameter is provided. Mixed logit generalizes MNL by allowing coefficients to follow random distributions.

## Quick Start

```python
from locpick import ChoiceTable, MixedMNL
from locpick import ChoiceTable, ChoiceModel
from locpick.models.mixed import ParamDistribution

ct = ChoiceTable.from_tables(choosers, alternatives, chosen_alternatives=choices)
Expand All @@ -20,7 +20,7 @@ random_params = {
"cost": ParamDistribution(distribution="normal", param="cost"),
}

model = MixedMNL(ct, formula="cost + time - 1", random_params=random_params, n_draws=100)
model = ChoiceModel(ct, formula="cost + time - 1", random_params=random_params, n_draws=100)
result = model.fit()
print(result.summary())
```
8 changes: 4 additions & 4 deletions docs/source/user-guide/mnl.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This user guide is a placeholder. Full content will be added in a future release

## Overview

The `MNL` class estimates multinomial logit (MNL) models for location choice. It supports:
The `ChoiceModel` class estimates multinomial logit (MNL) models for location choice. It supports:

- Formula/scoped-term model specification
- JAX-accelerated log-likelihood and gradient computation
Expand All @@ -16,10 +16,10 @@ The `MNL` class estimates multinomial logit (MNL) models for location choice. It
## Quick Start

```python
from locpick import ChoiceTable, MNL
from locpick import ChoiceTable, ChoiceModel

ct = ChoiceTable.from_tables(choosers, alternatives, chosen_alternatives=choices)
model = MNL(ct, formula="cost + time - 1")
model = ChoiceModel(ct, formula="cost + time - 1")
result = model.fit()
print(result.summary())
```
Expand All @@ -29,6 +29,6 @@ print(result.summary())
```python
# JAX is the default and only production backend
# NumPy kernels exist for reference/testing only
model = MNL(ct, formula="cost + time - 1")
model = ChoiceModel(ct, formula="cost + time - 1")
result = model.fit()
```
8 changes: 4 additions & 4 deletions docs/source/user-guide/modelspec.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ locpick uses formula/scoped-term specification for model structure:
Typically models are specified using Wilkinson formulas

```python
from locpick import ChoiceTable, MNL
from locpick import ChoiceTable, ChoiceModel

model = MNL(ct, formula="cost + time - 1")
model = ChoiceModel(ct, formula="cost + time - 1")
```

The `ChoiceTable` handles data construction intelligently. In this example `cost` is fixed
Expand All @@ -42,10 +42,10 @@ ct = ct.add_pairwise_variable("time", time_series)
## Scoped Terms

```python
from locpick import ModelSpec, MNL
from locpick import ModelSpec, ChoiceModel

spec = ModelSpec(formula="cost + time - 1").alternative_specific("time", reference="walk")
model = MNL(ct, spec=spec)
model = ChoiceModel(ct, spec=spec)
```

## Generated Interaction Variables
Expand Down
6 changes: 3 additions & 3 deletions docs/source/user-guide/nested.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ This user guide is a placeholder. Full content will be added in a future release

## Overview

The `NestedMNL` class estimates nested logit models, which generalize MNL by grouping alternatives into nests with correlated error terms.
The `ChoiceModel` class estimates nested logit models when the `nests` parameter is provided. Nested logit generalizes MNL by grouping alternatives into nests with correlated error terms.

## Quick Start

```python
from locpick import ChoiceTable, NestedMNL
from locpick import ChoiceTable, ChoiceModel
from locpick.models.nested import NestSpec, NestingTree

ct = ChoiceTable.from_tables(choosers, alternatives, chosen_alternatives=choices)
Expand All @@ -23,7 +23,7 @@ tree = NestingTree(
]
)

model = NestedMNL(ct, formula="cost + time - 1", nests=tree)
model = ChoiceModel(ct, formula="cost + time - 1", nests=tree)
result = model.fit()
print(result.summary())
```
4 changes: 2 additions & 2 deletions docs/source/user-guide/prediction.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ Prediction and simulation are **model methods**, not `FitResult` methods. After
- `model.predict(result, data)` — Predicted choices

```python
from locpick import ChoiceTable, MNL
from locpick import ChoiceTable, ChoiceModel

ct = ChoiceTable.from_tables(choosers, alternatives, chosen_alternatives=choices)
model = MNL(ct, formula="cost + time - 1")
model = ChoiceModel(ct, formula="cost + time - 1")
result = model.fit()

# Choice probabilities (n_obs × n_alts ndarray)
Expand Down
Loading
Loading