Skip to content
Closed
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
103 changes: 92 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,47 @@ on:
branches: [ main ]
workflow_dispatch:

env:
# Temporary until Sharrow publishes its Python 3.14 AST compatibility fixes.
SHARROW_REVISION: 56a41c760d020537dc551afa946ebf2f83d1c85a

jobs:
test-dev-install:
name: developer install
runs-on: ubuntu-latest
defaults:
run:
shell: bash -l {0}
working-directory: larch
steps:
- name: checkout
uses: actions/checkout@v4
with:
path: larch
- name: checkout compatible Sharrow
uses: actions/checkout@v4
with:
repository: outerl/sharrow
ref: ${{ env.SHARROW_REVISION }}
path: sharrow
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version-file: "larch/.python-version"
- name: setup graphviz
uses: ts-graphviz/setup-graphviz@v2
- name: run developer install script
run: bash envs/uv-dev.sh -d .
- name: install developer dependencies
run: uv sync --locked --all-extras
- name: generate example modules
run: uv run --no-sync python tools/rip_examples.py
- name: review environment
run: uv pip list
- name: run tests
run: uv run pytest
run: uv run --no-sync pytest

build-wheel:
name: 🛞 build wheel
Expand All @@ -37,49 +60,107 @@ jobs:
with:
fetch-depth: 0
fetch-tags: true
submodules: recursive
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true
- name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version-file: "pyproject.toml"
python-version: "3.14"
- name: build wheel
run: uv build
run: |
python tools/rip_examples.py
uv build --no-sources
- name: Upload wheel artifact
uses: actions/upload-artifact@v4
with:
name: wheels
path: dist

build-sharrow-wheel:
name: 🛞 build compatible Sharrow wheel
runs-on: ubuntu-latest
steps:
- name: checkout compatible Sharrow
uses: actions/checkout@v4
with:
repository: outerl/sharrow
ref: ${{ env.SHARROW_REVISION }}
- name: Install uv
uses: astral-sh/setup-uv@v3
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.14"
- name: build dependency wheel
env:
SETUPTOOLS_SCM_PRETEND_VERSION_FOR_SHARROW: 2.16.2+py314.56a41c7
run: uv build --wheel --no-sources
- name: Upload dependency wheel
uses: actions/upload-artifact@v4
with:
name: sharrow-py314-wheel
path: dist/*.whl

test-wheel:
name: 🧪 test wheel
needs: build-wheel
needs: [build-wheel, build-sharrow-wheel]
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ '3.10', '3.11', '3.12', '3.13' ]
python-version: [ '3.11', '3.12', '3.13', '3.14' ]
fail-fast: false
defaults:
run:
shell: bash -l {0}
steps:
- name: checkout tests
uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
- name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: setup graphviz
uses: ts-graphviz/setup-graphviz@v2
- name: Download wheel artifact
uses: actions/download-artifact@v4
with:
name: wheels
path: dist
- name: Download compatible Sharrow wheel
if: matrix.python-version == '3.14'
uses: actions/download-artifact@v4
with:
name: sharrow-py314-wheel
path: dependencies
- name: Install wheel
run: |
uv venv
uv pip install dist/*.whl
uv venv --python "${{ matrix.python-version }}"
wheels=(dist/*.whl)
dependency_wheels=()
if [[ "${{ matrix.python-version }}" == "3.14" ]]; then
dependency_wheels=(dependencies/*.whl)
fi
uv pip install --only-binary :all: "${wheels[0]}[test]" "${dependency_wheels[@]}"
uv pip check
- name: Verify installed wheel
run: |
.venv/bin/python - <<'PY'
from pathlib import Path
import sys
import larch
from sharrow.aster import expression_for_numba

assert Path(larch.__file__).is_relative_to(Path(sys.prefix))
assert larch.examples.ex, "Generated examples are missing from the wheel"
expression_for_numba(
"skims['DIST']", spacename="skims", dim_slots=(0,), spacevars={"DIST"}
)
print(larch.versions())
PY
- name: Run tests
run: |
uv run python -c "import larch; print(larch.versions())"
.venv/bin/python -m pytest tests -o addopts=''
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.11"
- name: Build wheel
run: |
python tools/rip_examples.py
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.11"
- name: Build wheel
run: |
python tools/rip_examples.py
Expand Down
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.13
3.14
60 changes: 4 additions & 56 deletions docs/examples/exampville/204_exville_dest_only.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -980,7 +980,7 @@
" ).sort_index(),\n",
" rtol=1e-2,\n",
")\n",
"assert m.pstderr == approx(\n",
"assert mg.pstderr == approx(\n",
" np.array([0.145749, 0.052355, 0.0, 0.0, 0.009012, 0.003812]),\n",
" rel=1e-3,\n",
")"
Expand Down Expand Up @@ -1012,61 +1012,9 @@
"outputs": [],
"source": [
"# TEST\n",
"assert mg.bhhh() == approx(\n",
" np.array(\n",
" [\n",
" [\n",
" 4.92276067e01,\n",
" 0.00000000e00,\n",
" 0.00000000e00,\n",
" 0.00000000e00,\n",
" 1.82962749e02,\n",
" 2.35657294e02,\n",
" ],\n",
" [\n",
" 0.00000000e00,\n",
" 3.66140769e02,\n",
" 0.00000000e00,\n",
" 0.00000000e00,\n",
" -2.02327809e02,\n",
" 5.64802080e02,\n",
" ],\n",
" [\n",
" 0.00000000e00,\n",
" 0.00000000e00,\n",
" 0.00000000e00,\n",
" 0.00000000e00,\n",
" 0.00000000e00,\n",
" 0.00000000e00,\n",
" ],\n",
" [\n",
" 0.00000000e00,\n",
" 0.00000000e00,\n",
" 0.00000000e00,\n",
" 0.00000000e00,\n",
" 0.00000000e00,\n",
" 0.00000000e00,\n",
" ],\n",
" [\n",
" 1.82962749e02,\n",
" -2.02327809e02,\n",
" 0.00000000e00,\n",
" 0.00000000e00,\n",
" 1.45027493e04,\n",
" 1.20949516e04,\n",
" ],\n",
" [\n",
" 2.35657294e02,\n",
" 5.64802080e02,\n",
" 0.00000000e00,\n",
" 0.00000000e00,\n",
" 1.20949516e04,\n",
" 8.59976140e04,\n",
" ],\n",
" ]\n",
" ),\n",
" rel=1e-2,\n",
")"
"# Aggregation preserves alternative-level scores. Evaluate both models at\n",
"# the same coefficients so optimizer stopping tolerances do not affect parity.\n",
"assert mg.bhhh() == approx(m.bhhh(mg.pvals), rel=1e-8, abs=1e-8)"
]
}
],
Expand Down
28 changes: 14 additions & 14 deletions docs/examples/mtc/007_ovtt_by_distance.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@
"metadata": {},
"outputs": [],
"source": [
"result = m.maximize_loglike(stderr=True)\n",
"result = m.maximize_loglike(stderr=True, options={\"maxiter\": 1000, \"ftol\": 1e-13})\n",
"m.calculate_parameter_covariance()\n",
"m.loglike()"
]
Expand Down Expand Up @@ -312,19 +312,19 @@
"from pytest import approx\n",
"\n",
"expected_x = {\n",
" \"ASC_BIKE\": -2.675340279013382,\n",
" \"ASC_SR2\": -2.1871708718901455,\n",
" \"ASC_SR3P\": -3.5170483581773535,\n",
" \"ASC_TRAN\": -0.039611848334672385,\n",
" \"ASC_WALK\": -1.0206078711851112,\n",
" \"hhinc#2,3\": -0.001383608162986253,\n",
" \"hhinc#4\": -0.007257729971526785,\n",
" \"hhinc#5\": -0.01196363695212793,\n",
" \"hhinc#6\": -0.008182417861122782,\n",
" \"motorized_ovtbydist\": -0.18145744778558676,\n",
" \"motorized_time\": -0.04156509908994426,\n",
" \"nonmotorized_time\": -0.04755705411055601,\n",
" \"totcost\": -0.004114472584806616,\n",
" \"ASC_BIKE\": -2.6867134884041124,\n",
" \"ASC_SR2\": -2.188408263476616,\n",
" \"ASC_SR3P\": -3.5180530612046663,\n",
" \"ASC_TRAN\": -0.042203403709053865,\n",
" \"ASC_WALK\": -1.0228699972401316,\n",
" \"hhinc#2,3\": -0.0013767552257365773,\n",
" \"hhinc#4\": -0.007247420724207541,\n",
" \"hhinc#5\": -0.011858861031538045,\n",
" \"hhinc#6\": -0.008237733460896757,\n",
" \"motorized_ovtbydist\": -0.18121891400931894,\n",
" \"motorized_time\": -0.04154068238646636,\n",
" \"nonmotorized_time\": -0.04746566631597504,\n",
" \"totcost\": -0.0041167524654853885,\n",
"}\n",
"for k in expected_x:\n",
" assert revealed_x[k] == approx(expected_x[k], 2e-2), (\n",
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/mtc/009_ttr_4.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@
"metadata": {},
"outputs": [],
"source": [
"result = m.maximize_loglike(stderr=True)\n",
"result = m.maximize_loglike(stderr=True, options={\"maxiter\": 1000, \"ftol\": 1e-13})\n",
"m.calculate_parameter_covariance()\n",
"m.loglike()"
]
Expand Down
54 changes: 27 additions & 27 deletions docs/examples/mtc/017A_market_seg.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@
"metadata": {},
"outputs": [],
"source": [
"result = m.maximize_loglike(stderr=True, options={\"maxiter\": 1000, \"ftol\": 1e-10})\n",
"result = m.maximize_loglike(stderr=True, options={\"maxiter\": 1000, \"ftol\": 1e-13})\n",
"m.calculate_parameter_covariance()\n",
"m.loglike()"
]
Expand Down Expand Up @@ -380,32 +380,32 @@
"from pytest import approx\n",
"\n",
"expected_x = {\n",
" \"ASC_Bike\": 0.9742143708899291,\n",
" \"ASC_SR2\": 0.5953670936985695,\n",
" \"ASC_SR3+\": -0.7824827134037493,\n",
" \"ASC_Transit\": 2.2585074587816134,\n",
" \"ASC_Walk\": 2.9039591287055986,\n",
" \"costbyincome\": -0.02264018916095553,\n",
" \"hhinc#4\": -0.006444094209484317,\n",
" \"hhinc#5\": -0.011725009048022181,\n",
" \"hhinc#6\": -0.01198956540981421,\n",
" \"motorized_ovtbydist\": -0.11308926104452616,\n",
" \"motorized_time\": -0.021067655041764506,\n",
" \"nonmotorized_time\": -0.04394234551517281,\n",
" \"vehbywrk_Bike\": -2.644433522672152,\n",
" \"vehbywrk_SR\": -3.0157086560458417,\n",
" \"vehbywrk_Transit\": -3.9631693279363467,\n",
" \"vehbywrk_Walk\": -3.3398299003269862,\n",
" \"wkcbd_Bike\": 0.371887416799123,\n",
" \"wkcbd_SR2\": 0.37071617423118847,\n",
" \"wkcbd_SR3+\": 0.22893265840284804,\n",
" \"wkcbd_Transit\": 1.1056371095671524,\n",
" \"wkcbd_Walk\": 0.030612758978009455,\n",
" \"wkempden_Bike\": 0.001542900697956932,\n",
" \"wkempden_SR2\": 0.00204432338331191,\n",
" \"wkempden_SR3+\": 0.0035300285386588638,\n",
" \"wkempden_Transit\": 0.00316015805069698,\n",
" \"wkempden_Walk\": 0.0037858816800672803,\n",
" \"ASC_Bike\": 0.9768656487673031,\n",
" \"ASC_SR2\": 0.5928602674741049,\n",
" \"ASC_SR3+\": -0.7852130283746404,\n",
" \"ASC_Transit\": 2.2579601121574915,\n",
" \"ASC_Walk\": 2.9068933591665163,\n",
" \"costbyincome\": -0.022668384302186657,\n",
" \"hhinc#4\": -0.006445844794354888,\n",
" \"hhinc#5\": -0.011662175656345601,\n",
" \"hhinc#6\": -0.01200189697215675,\n",
" \"motorized_ovtbydist\": -0.11312496962190924,\n",
" \"motorized_time\": -0.021071030481812515,\n",
" \"nonmotorized_time\": -0.04400616719163487,\n",
" \"vehbywrk_Bike\": -2.6637415199527004,\n",
" \"vehbywrk_SR\": -3.014536760048916,\n",
" \"vehbywrk_Transit\": -3.9632962228600492,\n",
" \"vehbywrk_Walk\": -3.341935874346473,\n",
" \"wkcbd_Bike\": 0.39513498215985876,\n",
" \"wkcbd_SR2\": 0.3724423420159654,\n",
" \"wkcbd_SR3+\": 0.22943430769880338,\n",
" \"wkcbd_Transit\": 1.1064347514617832,\n",
" \"wkcbd_Walk\": 0.029732296011644076,\n",
" \"wkempden_Bike\": 0.0015075846525952844,\n",
" \"wkempden_SR2\": 0.0020444554589942516,\n",
" \"wkempden_SR3+\": 0.0035323129337276214,\n",
" \"wkempden_Transit\": 0.0031600744478203252,\n",
" \"wkempden_Walk\": 0.0037891491261088186,\n",
"}\n",
"for k in expected_x:\n",
" assert revealed_x[k] == approx(expected_x[k], 2e-2), (\n",
Expand Down
Loading
Loading