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
7 changes: 4 additions & 3 deletions .github/ISSUE_TEMPLATE/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ missing, unclear, or inconsistent with the actual code/data? -->
- [ ] Add/update docstrings in `path/to/module.py`
- [ ] Write or refine a documentation page in `docs/`
- [ ] Update code examples in `examples/` to reflect current API behavior
- [ ] Update provenance notes in `benchmark/reference/README.md` or
- [ ] Update provenance notes in `benchmark/README.md` or
`docs/validation.md`

### References & Context
<!-- Link to relevant code, the original LuccME scripts in
benchmark/reference/, papers, or related issues, if applicable. -->
<!-- Link to relevant code, the original LuccME scripts (kept in
LambdaGeo/terrame-docker, benchmark/references/), papers, or related
issues, if applicable. -->
30 changes: 29 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,35 @@

All notable changes to `disslucc` are documented here.

## [0.3.0] -- unreleased
## [0.4.0] -- 2026-09-23

Reference results now come from
[LambdaGeo/terrame-docker](https://github.com/LambdaGeo/terrame-docker) v0.1.0,
and both allocations are validated year by year, iteration counts included.

### Added
- `benchmark/goldens/`: year-by-year TerraME reference results (every cell,
every year, `<lu>_out` and `<lu>_pot`, iteration counts) for `lab01`,
`lab01_md1643`, `lab15` and `lab15_md10`, copied from terrame-docker v0.1.0
(which has all 21 LuccME labs), and `tests/test_goldens_per_year.py`, which
checks iterations and every class year by year.
- `AllocationClueLike(cell_correction=True)`: `False` skips
`_correct_cell_change` and reproduces TerraME, whose `correctCellChange`
never runs (a `regionregionAloc` typo). The default is unchanged.
- `iterations_per_step` on `AllocationClueLike` and `AllocationDClueSLike`.

### Changed
- `docs/validation.md`: the Lab1 MAE (0.0036) is explained by the cell
correction TerraME skips, not by the `maxDifference` tolerance; new
"Year by year" section. The numbers themselves are unchanged.

### Removed
- `benchmark/reference/*.lua` and `benchmark/data/*.zip`, now kept in
terrame-docker (`benchmark/references/`). Tests and examples read the last
year of `benchmark/goldens/lab01_md1643` and `lab15_md10`, which hold the
same values.

## [0.3.0] -- 2026-09-22

First version meant to be independently citable and reproducible
without `disslucc-continuous` or `disslucc-discrete` cloned alongside
Expand Down
4 changes: 2 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ authors:
given-names: "Sérgio"
orcid: "https://orcid.org/0000-0002-0232-4549"
affiliation: "Universidade Federal do Maranhão (UFMA)"
version: 0.3.0
date-released: "2026-09-22"
version: 0.4.0
date-released: "2026-09-23"
license: MIT
repository-code: "https://github.com/LambdaGeo/disslucc"
keywords:
Expand Down
33 changes: 21 additions & 12 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ src/disslucc/
validation/ # continuous/discrete; potential + allocation are not
executors/ # ModelExecutor (base.py, continuous.py, discrete.py)
data/input/ # vendored real input data (shapefiles + demand CSVs)
benchmark/data/ # vendored TerraME *reference outputs* (expected results)
benchmark/reference/ # vendored original LuccME .lua *scripts* (provenance) + README.md
benchmark/goldens/ # TerraME reference results, year by year (copy from LambdaGeo/terrame-docker)
examples/ # runnable scripts: synthetic, real data, via Executor
tests/ # pytest -- validation (exact numbers) + discriminance (does the
# benchmark actually constrain the implementation?)
Expand All @@ -56,14 +55,18 @@ scripts, then three more `examples/*.py` files found later) -- grep for
`/home/`, `/tmp/` before assuming a script is portable.

**Data provenance is not "whatever GitHub script has a matching name."**
`terrame/luccme`'s public `tests/functional/lab01.lua` and `lab15.lua`
share calibrated coefficients and demand trajectories with the scripts
that actually generated this repo's reference data, but declare
different `maxDifference` values (5000 and 300, vs. the 1643 and 10
actually used) and did **not** generate `benchmark/data/`'s zips. The
real generating scripts are vendored, unmodified, at
`benchmark/reference/` -- **read `benchmark/reference/README.md` before
citing or changing any `max_difference`/`maxDifference` value.**
The reference results live in `benchmark/goldens/`, a copy of the goldens
generated in [LambdaGeo/terrame-docker](https://github.com/LambdaGeo/terrame-docker)
v0.1.0, which keeps the generating scripts, the original TerraME outputs, the
generator and goldens for all 21 LuccME labs. This repository keeps only the
goldens its tests use (`lab01`, `lab15`: the LuccME package's labs;
`lab01_md1643`, `lab15_md10`); add one together with the component and test
that need it, never ahead of time. `lab01_md1643` and `lab15_md10` are the scenarios behind `docs/validation.md`
(same coefficients and demand as `lab01`/`lab15`, but `maxDifference` 1643
and 10 instead of 5000 and 300). **Read terrame-docker's
`benchmark/references/README.md` before citing or changing any
`max_difference`/`maxDifference` value.** Never edit a golden by hand --
regenerate it there and copy it (see `benchmark/README.md`).
A empirical validation number that stops matching (e.g. MAE jumping from
0.0036 to above 0.01) is stronger evidence of a wrong parameter than a
GitHub script that merely looks similar.
Expand All @@ -78,10 +81,15 @@ PR/commit and say so explicitly -- don't let it drift silently.
```bash
python -m venv venv && source venv/bin/activate
pip install -e ".[examples,dev]"
pytest tests/ -v # expect: 14 passed, 2 xfailed
pytest tests/ -v # expect: 19 passed, 2 xfailed
mypy src/disslucc # expect: clean
```

`AllocationClueLike(cell_correction=True)` (the default) deliberately differs
from TerraME: LuccME's `correctCellChange` never runs (a `regionregionAloc`
typo). Tests that compare against the continuous goldens use
`cell_correction=False`; don't "fix" the default to make them pass.

The 2 `xfail`s in `tests/test_benchmark_discriminance_lab15.py` are
intentional and documented (the Lab15 scenario is near-non-discriminative
by design -- a trivial static ranking reproduces the same output). Don't
Expand All @@ -90,7 +98,8 @@ dynamic-covariate scenario (see `docs/decisions.md`).

Before changing a `max_difference`/convergence value, a demand table, or
a regression coefficient anywhere in `src/`, `tests/_lab*_helpers.py`, or
`examples/`: check `benchmark/reference/` first. If the change isn't
`examples/`: check the golden's `manifest.json` and the scripts in
terrame-docker's `benchmark/references/` first. If the change isn't
traceable to those `.lua` files, it's very likely wrong even if it looks
locally reasonable.

Expand Down
28 changes: 15 additions & 13 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,19 +112,21 @@ number change unexpectedly, treat it as a regression until proven otherwise.
Two things make this package different from a typical model port, and both
have their own conventions:

- **Vendored input/reference data** (`data/input/`, `benchmark/data/`) is
real data from `disslucc-continuous`/`disslucc-discrete`, not synthetic.
Don't regenerate or "clean up" these files without understanding
`docs/validation.md` first -- the numbers they produce are cited in
`dissmodel`'s JOSS paper.
- **Provenance scripts** (`benchmark/reference/*.lua`) are the actual
original LuccME "Model Configurator" scripts that generated the reference
data, kept unmodified. If you're unsure whether a script on
`terrame/luccme`'s GitHub is "the" source for a scenario here, check
`benchmark/reference/README.md` first -- coefficients/demand matching is
not sufficient evidence, since TerraME's own public test suite contains
look-alike scenarios with different convergence parameters that did not
generate this repository's data.
- **Vendored input data** (`data/input/`) is real data from
`disslucc-continuous`/`disslucc-discrete`, not synthetic. Don't regenerate
or "clean up" these files without understanding `docs/validation.md` first
-- the numbers they produce are cited in `dissmodel`'s JOSS paper.
- **Reference results** (`benchmark/goldens/`) are a copy of the goldens this
repository's tests use, generated in [LambdaGeo/terrame-docker](https://github.com/LambdaGeo/terrame-docker)
v0.1.0 (which has goldens for all 21 LuccME labs; copy one here only with
the component and test that use it),
which also keeps the original LuccME "Model Configurator" scripts, the
original TerraME outputs and the generator. Never edit a golden by hand:
regenerate it there and copy the folder (see `benchmark/README.md`). If
you're unsure which script is "the" source for a scenario, check
terrame-docker's `benchmark/references/README.md` -- coefficients/demand
matching is not sufficient evidence, since TerraME's own public test suite
contains look-alike scenarios with different convergence parameters.

If your change affects a Lab1 or Lab15 validation number, update
`docs/validation.md` in the same PR and say so explicitly in the PR
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ the original TerraME reference on real data for both: Lab1
(continuous) within the official 0.01 MAE tolerance, Lab15 (discrete)
at exact, 100% cell-by-cell agreement — see
[`docs/validation.md`](docs/validation.md) for both results and what
each one does and doesn't prove.
each one does and doesn't prove. Both are also checked year by year,
iteration counts included, against the goldens of
[LambdaGeo/terrame-docker](https://github.com/LambdaGeo/terrame-docker)
(`benchmark/goldens/`), which cover the 21 labs of the LuccME package; this
repository keeps the ones its tests use.

## Migration status: becoming the single successor repository

Expand Down Expand Up @@ -147,8 +151,7 @@ disslucc/
├── examples/ # ready-made scripts, synthetic, real data, and via Executor
├── data/input/ # vendored Lab1 + Lab15 input shapefiles and demand CSVs
├── benchmark/
│ ├── data/ # vendored TerraME reference outputs (Lab1, Lab15)
│ └── reference/ # vendored original LuccME .lua scripts (provenance)
│ └── goldens/ # TerraME reference results, year by year (from LambdaGeo/terrame-docker)
├── tests/ # pytest suite -- validation + discriminance, run by CI
└── docs/
```
52 changes: 52 additions & 0 deletions benchmark/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Goldens do TerraME/LuccME

`goldens/` é uma cópia dos goldens gerados em
[LambdaGeo/terrame-docker](https://github.com/LambdaGeo/terrame-docker)
**v0.1.0** (`benchmark/goldens/`), com TerraME 2.0.1 + LuccME `6244dd4`. É contra eles que o
disslucc é validado, algoritmo por algoritmo.

Scripts, saídas originais do TerraME e o gerador ficam **só** no terrame-docker; aqui
fica só o resultado, para os testes rodarem sem Docker.

## O que há em `goldens/<nome>/`

| Arquivo | Conteúdo |
|---|---|
| `<nome>.csv.gz` | estado de cada célula ao fim de cada ano: `year,id,col,row`, `<classe>_out` e `<classe>_pot`, 12 casas decimais |
| `terrame.log` | saída do TerraME (demanda, área alocada, iterações por ano) |
| `manifest.json` | script de origem e SHA-256, versões, anos, colunas, iterações por ano (`iterations_per_year`) e a verificação cruzada |

`col`/`row` alinham com `data/input/csAC.zip` (`col`, `row`) e `cs_moju.zip` (`col`, `lin`).

## Quais são

Só os goldens que os testes deste repositório usam. Os outros (os 21 labs do pacote
LuccME) ficam no terrame-docker e entram aqui quando o componente correspondente for
implementado, junto com o teste que os usa.

| Golden | Componentes | Usado em |
|---|---|---|
| `lab01` | PreComputedValues + CLinearRegression + CClueLike (`maxDifference` 5000) | `test_goldens_per_year.py` |
| `lab01_md1643` | idem, `maxDifference` 1643: itera 8–26 vezes por ano | `test_goldens_per_year.py`, `test_validation_lab1.py`, discriminância |
| `lab15` | PreComputedValues + DLogisticRegression + DClueSLike (`maxDifference` 300) | `test_goldens_per_year.py` |
| `lab15_md10` | idem, `maxDifference` 10: itera 56–67 vezes por ano | `test_goldens_per_year.py`, `test_validation_lab15.py`, discriminância |

O último ano de `lab01_md1643` e de `lab15_md10` é a antiga referência deste repositório
(`benchmark/data/*.zip`).

## Antes de usar como prova

- Nos labs do pacote a alocação aceita a primeira passada em todos os anos; só as
variantes `_md` testam o laço de convergência.
- Nos labs com `CClueLike`, o TerraME nunca executa `correctCellChange` (typo
`regionregionAloc`). O disslucc executa por padrão; compare com
`cell_correction=False`. Ver `docs/validation.md`.
- Compare com tolerância (1e-9 no arquivo; os testes usam MAE < 1e-6), nunca pelo
SHA-256: de uma geração para outra, algumas células mudam na 12ª casa decimal.

## Adicionar ou atualizar

Copie a pasta do golden de `benchmark/goldens/<nome>/` do terrame-docker, na mesma versão
(`v0.1.0`), para `benchmark/goldens/<nome>/` aqui, no mesmo commit do teste que passa a
usá-lo. Nunca edite um golden à mão; para regenerar, use `benchmark/generate.sh <nome>`
no terrame-docker.
Binary file removed benchmark/data/LUCCME_Lab1_2014.zip
Binary file not shown.
Binary file removed benchmark/data/Lab15_2004.zip
Binary file not shown.
Binary file added benchmark/goldens/lab01/lab01.csv.gz
Binary file not shown.
53 changes: 53 additions & 0 deletions benchmark/goldens/lab01/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"lab": "lab01",
"source": {
"script": "luccme/tests/functional/lab01.lua",
"sha256": "d8e16d718c3654b0d7f89d743413f3ee781d6fb05574231fb843af895c238dfa"
},
"engine": {
"image": "terrame-luccme",
"terrame": "2.0.1",
"terralib": "5.5.1",
"luccme_commit": "6244dd461f94259efb6e1d2170d32fc7e28c033c"
},
"generator": {
"script": "benchmark/harness.lua",
"sha256": "be7c575428c574da799f7f745da7766a05f6b878df08b12bcd0bab882e346581"
},
"status": "ok",
"years": [
2008,
2014
],
"n_cells": 6574,
"columns": [
"f_out",
"d_out",
"outros_out",
"f_pot",
"d_pot",
"outros_pot"
],
"file": {
"name": "lab01.csv.gz",
"rows": 46018,
"sha256": "c773f4b295c8c980898b320a460d29fedd1118260d1e7eacd7c7fc8cd51e59ed"
},
"crosscheck_vs_original_output": {
"tolerance": 1e-09,
"max_abs_diff": {
"Lab01_2014.dbf:d_out": 5.000028169277471e-13
},
"note": "último ano do CSV comparado com os .dbf da pasta de saída: a saída do próprio script e, nas referências, a saída original do TerraME"
},
"iterations_per_year": {
"2008": 0,
"2009": 0,
"2010": 0,
"2011": 0,
"2012": 0,
"2013": 0,
"2014": 0
},
"iterations_note": "contínuo: 'Number of iterations' do LuccME; discreto: maior n de 'Iteration -> n' (0 = aceito na 1ª passada)"
}
90 changes: 90 additions & 0 deletions benchmark/goldens/lab01/terrame.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@

Verifying Model parameters
Verifying Demand parameters
Verifying Potential parameters
Verifying Allocation parameters

Executing Demand component
Executing Potential component
Executing Allocation component

Year: 2008 Step: 0
f Area: 137878 Difference: 0
d Area: 19982 Difference: 0
outros Area: 6489 Difference: 0

Demand allocated correctly in 2008. Number of iterations: 0 Maximum error: 2.7950358344242e-05
[harness] lab01: Lab01, anos 2008..2014, colunas f_out,d_out,outros_out,f_pot,d_pot,outros_pot

Executing Demand component
Executing Potential component
Executing Allocation component

Year: 2009 Step: 0
f Area: 136483 Difference: -1139
d Area: 20953 Difference: 714
outros Area: 6489 Difference: 0

Demand allocated correctly in 2009. Number of iterations: 0 Maximum error: 1138.4125251856

Executing Demand component
Executing Potential component
Executing Allocation component

Year: 2010 Step: 0
f Area: 135609 Difference: -1757
d Area: 21826 Difference: 1331
outros Area: 6489 Difference: 0

Demand allocated correctly in 2010. Number of iterations: 0 Maximum error: 1756.4683416836

Executing Demand component
Executing Potential component
Executing Allocation component

Year: 2011 Step: 0
f Area: 134822 Difference: -2288
d Area: 22612 Difference: 1862
outros Area: 6489 Difference: 0

Demand allocated correctly in 2011. Number of iterations: 0 Maximum error: 2287.3741648977

Executing Demand component
Executing Potential component
Executing Allocation component

Year: 2012 Step: 0
f Area: 134114 Difference: -2711
d Area: 23320 Difference: 2284
outros Area: 6489 Difference: 0

Demand allocated correctly in 2012. Number of iterations: 0 Maximum error: 2710.5152184257

Executing Demand component
Executing Potential component
Executing Allocation component

Year: 2013 Step: 0
f Area: 133475 Difference: -3064
d Area: 23956 Difference: 2635
outros Area: 6489 Difference: 0

Demand allocated correctly in 2013. Number of iterations: 0 Maximum error: 3063.7042134609

Executing Demand component
Executing Potential component
Executing Allocation component

Year: 2014 Step: 0
f Area: 132899 Difference: -3354
d Area: 24530 Difference: 2922
outros Area: 6489 Difference: 0

Demand allocated correctly in 2014. Number of iterations: 0 Maximum error: 3353.6276049931

Saving Lab01_2014.
Elapsed time: 00:00:04 hh:mm:ss

End of Simulation
[harness] lab01: 5 arquivos da saída original em /work/out/lab01
[harness] lab01: CSV gravado em /work/out/lab01
Binary file not shown.
Loading
Loading