Repository navigation
Decision log
In one sentence: every methodological decision that shaped the pharmacy model — what, when, by whom, why, and what number it moved — so you can tell a deliberate choice from an accident and know which results are comparable with which.
Where this sits: this page is the history behind the whole pipeline (GeoDMS → Arrow → Julia LP → λ-sweep → rounding → scenarios → deck). The neighbouring pages explain each stage as it is today; this one explains how it got there. Rejected ideas: Alternatives not pursued; branches and data: Branches data and environment.
Five eras tell the story; the table at the end lists every decision with its evidence: a commit on the ServiceAccess branch (dates are commit dates), a GitHub issue (#n) or a document in doc/ ("todo #n" and "todo A1" are items of doc/todo.md, the July recalculation checklist). Where no reason is written anywhere I say "not recorded"; where I infer one, I say so. "Moved" is the number the change shifted, when a source records one.
People, as the sources name them: Lewis and Bernhard Nöbauer (BN) (CFE/EDS, as the review doc labels BN) set the scenario framing; Ana Moreno Monroy (CFE/EDS) and Martijn Brons (DG REGIO) reviewed the methodology draft; Chris Jacobs-Crisioni (JRC) owns the data and the network configuration; Maarten Hilferink the Julia optimisation and the deck, Lola Dekhuijzen the school-era solvers, Jip Claassens the road network and OD matrix (all Object Vision).
Caveat, as of 15 September 2026: the branch on GitHub ends at e25416b (10 Sep). Issues #52, #53 and #44 cite later commits (216ac77, and in #52 four smaller ones) that exist only on Maarten's machine; #54 describes the same unpushed state. Everything attributed to them comes from the issue text (Branches data and environment).
The repository began in August 2023 as Jip's road-network model: a cleaned TomTom network per country, its largest strongly-connected component kept (Glossary) — a rule that later turned out to discard islands (Era 4). The optimisation half arrived in February 2026 for primary schools; two of its decisions still shape the pharmacy model.
The choice set. Maarten limited each client to its 5 nearest facilities (eaf133c); issue #22 gives the reason: searching from pupil locations to five schools has a stop criterion, the reverse direction has none — a compute choice, not a behavioural one. Today this is a radius: every candidate cell within the road time to a client's 5th-nearest existing pharmacy (71–86 candidates on average, 4267fe0), capped at Jip's 120-minute OD cutoff (535f796, no recorded rationale), which later became BIG, the price of an unserved client, by inheritance. Both sit in cfg/main/ModelParameters.dms (around lines 14–16). Because the radius is fixed by today's pharmacies it can bind at S2 (Era 5). Configuration: GeoDMS OD matrix and choice set; where it binds: Scope rules and data gaps.
The facility cost is linear. Chris fitted a power-law cost per pupil to 2023 school data (issue #38); the meeting judged it "may close schools too aggressively", and his three-piece linearisation fails because the model multiplies cost per pupil by load. Maarten's closing line — "We have continued with linear facility location costs: C_j := y_j·(c₀ + c_x·x_j)", a fixed cost c₀ per open school plus c_x per pupil served (x_j is the school's load here, not the later assignment variable) — is why the pharmacy model has a fixed price per location. Under the λ-sweep the per-client part drops out because (nearly) every resident is served in every solution (The facility location model explained).
The school objective — hard coverage plus a penalty proportional to under-enrolment (41f55bb) — was not carried over. No commit says why; the plain reason is that nobody has a minimum viable pharmacy size (inference). It survives in lp_run.jl → run_scenario and on Service allocation procedure.
On 24 May Maarten added the pharmacy analyses, LOGISTIC at midpoint 30 / scale 15, the placeholders FACILITY_MIN_COSTS = 100000 and FACILITY_CLIENT_COSTS = 3333 (the rounded school numbers, never calibrated), and the first sweep. Why pharmacies replaced schools is not in the repository; doc/topics.md names only the mail thread of 13 May. The all-country pharmacy point files arrived on 12 June (0b36dcb, "shared by Taina Pacheco" — the commit does not say OECD); whether the data drove the switch is inference. The thread fixed the question the model still answers — S1, S2, S3 (issue #43, closed in July: "now implemented as S1 and S2, but with lambda_sweep"): a price λ per open location (in code the multiplier w, λ = w × €100 000) traces the frontier of best (locations, travel) pairs, on which S1 and S2 are read against ★, today's network (The lambda sweep and the Pareto frontier, Scenarios S1 S2 S3).
Three decisions in the first fortnight made the sweep usable, each answering a measurement:
-
Bracket S1 on the LP's fractional count
sum_y(9ee7ac6): bracketing needs a quantity that moves one way as λ rises, and the rounded count did not — under interior-point (IPM) solves many tiny y-fractions were counted as open, so it jumped from 2 296 to 3 894 between w = 0.01 and 0.1 on the Netherlands (Scenarios S1 S2 S3). -
Warm-started dual simplex, sequentially (
011cafb): each re-solve takes seconds where a fresh interior-point solve of the old Netherlands sweep took roughly 700–4 000 s; "sequential is the point". A cold IPM solve still beats a cold simplex solve (a9ef6cc); the warm start is what wins (The lambda sweep and the Pareto frontier). -
Multistart rounding with coverage-honest scoring (
e1c426b): once a stranded client was charged instead of dropped, top-p rounding was seen to abandon "hundreds-to-thousands of rural" cells; the multistart is provably no worse than its seeds (From LP fractions to real pharmacies).
June's detour was the cap ladder, Lewis's and BN's four-rung recipe: closures decided by minimum and maximum catchments (residents per pharmacy) in variants A–C, a price per location (the λ-sweep) only as fallback D. Maarten built the cap engine in a day, ran it on the Netherlands and de-emphasised it the next morning (6dc70f5, "per feedback" — whose is not recorded): catchments spread so widely that no defensible cap exists. Formally dropped on 4 September; rungs and NL numbers on Alternatives not pursued.
By late June the pilots had exposed comparability defects; the 24-June thread plus Chris's methodology draft (28 June) fixed the inputs, and doc/todo.md is the checklist.
-
Candidates = cells ≥ 50 inhabitants ∪ pharmacy cells (
7c6768f;MinPopSizeForPharmacyLocation := 50). Chris: keeps ~98 % of pharmacy locations, search space 7.5 % → 2.9 % of EU cells; Lewis: "the best option". Luxembourg's candidates fell 1 599 → 945 while its LINEAR S1 improved slightly (−7.98 % vs −7.66 % travel), and the 2.5× smaller LP made country-level Poland tractable (29 h). The same commit fixed a wiring bug: the 5-nearest limit had been counting school cells (GeoDMS OD matrix and choice set). -
Clients = the whole population (
033dd32;Client := 'population'), per methodology §2.1; both network sides had to be rebuilt because client cells are network nodes. -
Logistic 25/10 (
7c6768f): 30/15 was a first guess; Lewis wanted indifference below ~5–10 min and saturation by ~45. Old runs stay reproducible viaLOGISTIC_MIDPOINT/LOGISTIC_SCALE(Travel cost functions). -
Coverage-consistent baseline (
206923c).baseline_metricshad dropped clients who cannot reach any existing pharmacy (Denmark ~11 % of residents, ITG ~15 %, SE2 ~5 %) while the LP had to serve them; now they are priced like scenario stranding, and Denmark's baseline travel roughly doubled. -
Aggregated frontier (
d0ae5ef): sums facilities and travel at each common λ over the 41 disjoint areas (country-Poland excluded because its seven NUTS-1 are in), exact because the objective separates by area (Metrics aggregation and ranking). -
Common grid, no early stop (
206923c): the sweep used to stop once travel exceeded today's, so the aggregate's range ended where the first area stopped (Belgium, w = 0.1). One fixed grid for every area proved intractable under hard coverage (NL 16.7 h at w = 5.0, Austria LOGISTIC 40 h of time-outs) and triggered three solver reversals in three days (The lambda sweep and the Pareto frontier). -
Soft coverage (
4ec47a9, agreed 10 July). Hard coverage was the root cause of the stalls and of the unbracketable S1: the LP could not open fewer facilities than needed to reach everybody, so for ITG, Norway, Portugal, PL8 and the Netherlands the frontier stopped at a floor above today's count. "At most one" pharmacy per client, with BIG for an unassigned one, lets the frontier run down past ★ so every area brackets S1 and S2; the warm start stays valid between grid points and high-λ solves became cheap (few facilities open, small basis), so simplex serves both functions up to w = 5.0 LINEAR / 0.5 LOGISTIC. Formulation and the "constant drops out" trick: The facility location model explained. -
BIG fixed at c(120 min) (
settings.jl→big_cost(), envBIG_TRAVELTIME_MIN): each region's own t_max, 42 min (Paris) to 120 (Norway), had priced stranding inconsistently and broken the aggregate (Travel cost functions). -
Improvement metrics (
e75c73c,2a6ea08): the raw improvement rectangle "mostly ranks by region size", sorect_rel— fractional facility saving × fractional travel saving — replaced it; charts coloured by the pharmacy-regulation typology (559dad9) (Metrics aggregation and ranking). -
PROTECT_BASELINE(f167da2): the candidate subsample used for slow areas had kept only 555 of FRI's 1 590 baseline cells, so S2 came out with more facilities than today. The subsample is also the seed of #54 (Scope rules and data gaps). -
x/y renamed (
4cee238, 24 July): nothing numerical changed, but every older artefact uses the opposite letters (The facility location model explained).
Landbody networks. Chris's 79cb58b (31 Aug), prompted by issue #13 (every centre on Gran Canaria at the 120-min cap), replaced "largest SCC per study area" by "largest SCC per landbody" (Templates.dms around line 93); no data changed, the island links had simply been pruned. Maarten's split of ITG's baseline cost (a058fe3, #49) showed 84.6 % of it was BIG penalty on 983 169 unreachable residents; Portugal (62.6 %) and PL8 (44.4 %) were the others, so the ranked lists had been ranking coverage artefacts. After rebuilding all 42 areas only those three moved (ITG 22.30 → 4.878 min, PL8 unreachable → 0). The commit had also put baseline and LP on different client units, resolved by one ModelClient (f0acbc9). Numbers: Scope rules and data gaps; configuration: GeoDMS OD matrix and choice set.
The node fix (#50). Norway, SE2 and SE3 then failed at the alloc step, reading back the link set the network build had written. Maarten refuted his own node-id hypothesis by measurement (exactly one link had an undefined node) and found the cause: a junction-free section (a chain of links without junctions, here an island ring road) with no connector link to any OD point, so min/max over an empty group left First_ConnectorLink_rel undefined. Fix (7086928): count connector links explicitly and drop such sections (IsDisconnectedJFS) and any link with an undefined node unconditionally; Chris's component rule is untouched. Byte-identical link sets on Luxembourg and Portugal proved it a no-op elsewhere (GeoDMS OD matrix and choice set).
Region exclusion (#49 → #51). Portugal did not move: all 1 893 pharmacies lie on the mainland, every unreachable client on the Azores and Madeira — a data gap, not connectivity. Maarten proposed a landbody filter (Country_Split) and left it unapplied as a modelling decision; Chris endorsed it ("poor data coverage in these islands is a recurring theme"). Implemented as a NUTS rule (872b388; settings.jl → excluded_nuts_regions, NUTS_EXCLUDE_SHARE = 0.5): a region with more than half its inhabited cells absent from the existing OD is dropped from baseline and sweep. Only PT200 and PT300 trigger, both at 100 %; Portugal's baseline travel fell 62 % (Scope rules and data gaps).
The REGIO review (doc/deck_changes_from_review.md: 26 comments, Ana in July, Brons 6 Aug, BN 30 Aug), worked in on 4 September:
-
Trilemma dropped, "by how much" leads (comments 1–3, 5–6): all three rejected an efficiency–accessibility–demand "two out of three" framing — cost and accessibility trade off continuously under exogenous demand, and the draft's yes/no research questions ("can accessibility improve? can the count fall?") are trivially yes. BN's reading was adopted: the frontier answers "by how much" without any λ (
b3c634b). Native units first: the S1/S2 tables lead with Δ person-minutes (or Δ logistic cost) and Δ locations; λ columns in grey. - €100 000 is a placeholder (20–22): Ana wanted no values, Brons said values drive the outcome, BN resolved it: λ weights only the fixed part of the cost, the sweep runs over the multiplier w, and €100 000 only converts w into a € label — doubling it would halve every printed λ and leave every solution, S1/S2 point and ranking where it is (The lambda sweep and the Pareto frontier).
-
Descriptives first (4), a tangency diagram (41–42), logistic named (26–28: a plain logistic, not log-logistic; c(0) ≈ 0.076, not zero at zero minutes), bounds on total cost only (37–38: the LP-lower / multistart-upper sandwich certifies total cost, not travel and count separately; From LP fractions to real pharmacies); age-weighted demand and candidate neighbours listed as "Not pursued" (
ef05320). BN's proposal to rescale the logistic so that c(0) and c(60) coincide with the linear curve — which would also ease the λ-compression Brons noticed — is tabled: it changes the equity weighting the logistic was chosen for (Travel cost functions).
Cap ladder dropped formally the same day with the urban/non-urban split, pharmacist-based caps, flat-then-linear cost and logit sensitivity — confirmed with Maarten; each on Alternatives not pursued.
S1/S2 pinned (#52). The exported S1/S2 location files snapped to the nearest swept grid point; in FRC, FRH, FRJ, FRK and SE2 both scenarios were the same point (SE2's S1 had 309 open cells against 452, −31.6 %), and over 74 sweeps S1 was off by more than 10 % in 22. June's post-hoc S2 bisection had failed because it ran after the sweep had climbed through three 1-hour time-outs, and a warm start from that far basis timed out too (FRC: 75 s as a grid step). Now (29fcf7f, e25416b) S1 (on sum_y) and S2 (on multistart travel, 0.2 %) are bisected the moment their bracket closes, the sweep ends at the first time-out above it, and a refine-only mode re-pinned the 37 areas whose OD had not changed, walking the grid LP-only (a rounding costs 50–100 s per point, an LP 7 s). Result (216ac77): S1 median error 0.13 %, S2 max 0.74 %; only country-level Poland LINEAR keeps its grid point (S1 +1.6 %; solves near S1 take 3–15 h). Concepts: Scenarios S1 S2 S3; code: Code walkthrough lambda_sweep_simplex.
Italy, Hungary, Finland (#53, #44). On 7 September the OECD delivered the Italian Ministry of Health list (20 635 pharmacies, OECD-geolocated) replacing ESPON's 12 991, and Hungary (3 094; typology Type 1 / HIGH from slide 13 of the typology deck). Wired in on 10 September, it overturned the headline: ITF went from 1 951 to 4 955 pharmacies, ITG's mean travel from 4.9 to 2.0 min, and the Italian rect_rel collapsed — ITF 0.268 → 0.071, ITG 0.261 → 0.073 (ITG had been 0.384 in July, before the landbody fix); SE1, Norway, Lithuania and SE2 lead now. Finland's June failure was a GeoDMS 20.0 limitation; 20.19 reads the GeoParquet, so 2aeb6c0 reinstated it (797 pharmacies, S1 −13.5 % travel, S2 −24.7 % locations): 44 study areas as of 12 September. Why Italy went from the June parquet (20 642 pharmacies over the five NUTS-1 areas per 3a2688f; 20 637 in the country row) to ESPON in July is not recorded. The pushed deck, README and Pharmacy results September 2026 still carry the ESPON numbers; per-country provenance on Branches data and environment.
Issue #54: a non-convex lower bound in FRI. The FRI LINEAR LP curve is not convex — impossible for one LP, whose sweep can only return points on the curve's lower convex envelope (The lambda sweep and the Pareto frontier). doc/build_deck_data.py merges FRI's July full sweep (6 765 of 17 141 candidates under LOCATION_SELECTION_FACTOR=3, IPM, pre-landbody OD) with the September refine points (17 133 candidates, dual simplex): two LPs on one curve, λ not even monotone along it. Per #54, FRI was the only subsampled area⁴; it is being fully re-swept. The check exposed 16 more areas (listed on Branches data and environment) whose July OD differs marginally from the 2 September rebuild (kinks ≤ 1.5 %); a clean frontier means ~32 runs, ~20 h — awaiting Chris's call.
⁴ doc/issue48_README.md says "FRI and PL8" (README says only "the largest areas"); #54 says FRI alone. PL8's 2–3 September re-sweep set no factor, so it is most likely full-set (unverified; the header of logs/sweep_PL8_LINEAR.log would settle it).
The roadmap, in priority order (ef05320, README "Status and roadmap", confirmed with Maarten 4 Sep), with the reasoning:
- Communicate λ intuitively (person-minutes per location) — running; every reviewer found λ opaque.
-
Widen the candidate radius 5 → 10 nearest existing pharmacies, one area first. It binds at S2: 10.2 % of SE2's residents have exactly one open facility left in radius (
4267fe0); in the September results Norway is at 18.6 % and ITF on the OECD list 1.8 % (#53). Where the radius, not geography, decides who can be served, the frontier is under-estimated (Scope rules and data gaps). - RSSV candidate reduction (random-sampling spatial voting: solve many small random sub-problems, keep the candidates chosen often) to replace the stride subsample — after 2, because sub-problems on candidate subsets strand clients whose radius holds no sampled candidate, corrupting the votes.
- Exact soft-coverage p-median MIP for one area, to measure the multistart's distance from the true integer optimum (the integrality gap; Glossary); 5. territorial coverage constraints (e.g. a minimum number of pharmacies per NUTS region) as an equity lever; 6. DECIDE BN's logistic rescaling; 7. calibrate the real fixed cost; 8. capacity caps; 9. counterfactuals (−10 % facilities; replace X %; let the model choose which to close); 10. the #54 re-sweeps; 11. country-level Poland LINEAR S1 (needs the IPM path or the MIP). Terms on Background theory.
Every term in this table is defined at first use in the eras above and on Glossary.
| Date | Decision | Why | Evidence | Moved |
|---|---|---|---|---|
| 2023-08 → 2024-05 | TomTom network cleaned per country; largest SCC kept (Jip, Chris) | Reproduce TomTom connectivity |
961d2c6, c48740b, #10 |
The OD side |
| 2026-02-23 | Client reaches its 5 nearest facilities (Maarten) | Stop criterion that way only |
eaf133c; #22 |
Choice-set radius today |
| 2026-03 | Piecewise proposed (Chris), continuous asked (Maarten), quadratic "for now" | No jumps; OECD input awaited | #27; 26e39c7
|
QUADRATIC still the default¹ |
| 2026-04-01 | OD cutoff 300 → 120 min (Jip) | Not recorded |
535f796 (#15) |
Becomes BIG in July |
| 2026-04-29 | Power-law school cost rejected; linear kept | Closes schools too aggressively | #38; 658c886
|
Fixed price per location |
| 2026-05-13 → Jun | Mail thread: S1/S2/S3, A→D ladder, logistic, six indicators | JRC framing |
doc/topics.md; #43 |
June agenda |
| 2026-05-24 | Switch to pharmacies; LOGISTIC 30/15; €100 000 + €3 333 placeholders; first sweep (Maarten) | Not recorded; IPM beats simplex for a fresh solve |
94f88db, 46f23e6, 40a3d55, a9ef6cc
|
Pharmacy era |
| 2026-05-25 | Bracket S1 on sum_y, not the rounded count |
Rounded count not monotone | 9ee7ac6 |
S1 rule ever since |
| 2026-05-27 | Warm-started dual simplex, 1-2-5 per decade, sequential | Seconds instead of ~700–4 000 s | 011cafb |
Production driver |
| 2026-05-28 | NUTS-1 study areas for FR, IT, SE, PL | Countries too big as one LP |
44eaf5c, babedf4
|
42 areas |
| 2026-06-07 | Multistart rounding, stranded clients charged; S2 bisection | Top-p strands rural cells; S1 = S2 on grid |
e1c426b, b76f643
|
Gap to LP ~0–5 % |
| 2026-06-12 | All-country lists (Taina Pacheco); Finland removed (Chris) | GeoParquet broke the union on 20.0 |
0b36dcb, c11fd38; #44 |
Finland out to 10 Sep |
| 2026-06-22/23 | Cap ladder built on NL, de-emphasised next morning | No settable caps |
7e7c031…6dc70f5
|
Alternatives not pursued |
| 2026-06-24 | Interpolated S1/S2 tables; candidates = cells ≥ 50 ∪ pharmacy cells (Chris, Lewis) | "—" if unbracketed; LP 2.5× smaller |
4013c91; todo A1, 7c6768f
|
LU 1 599 → 945 candidates |
| 2026-07-02 | Clients = population; logistic 25/10; wiring bug fixed | Methodology §2.1; Lewis's kinks |
033dd32, 7c6768f
|
LU OD 5 370 → 7 995 rows |
| 2026-07-05 | 42 areas recalculated; aggregated frontier; Poland swept; Iceland dropped from the descriptives loop | Separability; Iceland's descriptives hang |
d0ae5ef; todo #7, #10 |
PL S1 −18.8 % travel |
| 2026-07-06 | Coverage-consistent baseline; common grid, no early stop | ★ priced like the frontier; aggregate needs every λ |
206923c; todo #3, #4 |
DK baseline ≈ ×2 |
| 2026-07-07/09 | Solver churn: IPM above 0.5 → always IPM → per function | Hard-coverage stalls |
86476bf, f93aea1, acd59a6
|
Superseded 16 Jul |
| 2026-07-10 | Italy from ESPON shapefile (12 991) | Not recorded |
6a208f0; #46 |
Superseded by #53 |
| 2026-07-16 | Soft coverage; BIG = c(120 min) (decided 12 Jul²); simplex for both; w_max 5.0 / 0.5 | Full-coverage floor above today's count | 4ec47a9 |
Every area brackets S1, S2 |
| 2026-07-16/20 | Rectangle, crossing, rect_rel; typology colouring |
Raw area ranks by size |
e75c73c, 2a6ea08, 559dad9
|
Ranked lists |
| 2026-07-21 |
PROTECT_BASELINE in subsampling |
Subsample dropped baseline cells | f167da2 |
FRI S2 1 772 → 1 288 |
| 2026-07-24 | Notation x = assignment, y = facility | Match ReVelle–Swain | 4cee238 |
Notation only³ |
| 2026-08-31 |
Largest SCC per landbody (Chris); ModelClient (1 Sep) |
Islands lost their network (#13); units diverged |
79cb58b, f0acbc9; #49 |
ITG 22.30 → 4.88 min |
| 2026-09-02 | #50: drop connector-less junction-free sections | One link with an undefined node | 7086928 |
NO/SE2/SE3 alloc |
| 2026-09-02 | NUTS region exclusion > 50 % unreachable (Maarten, Chris) | Azores/Madeira have no records |
872b388; #49, #51 |
PT baseline −62 % |
| 2026-09-04 | REGIO review in; ladder and five topics dropped | 26 comments; confirmed with Maarten 4 Sep |
b3c634b, f46bbf8, 7f99138, ef05320
|
Deck framing |
| 2026-09-10 | S1/S2 bisected inside the sweep; refine-only; LP-only walk | Snap off by up to 31 % |
29fcf7f, e25416b; #52 |
S1 median error 5.9 % → 0.13 % |
| 2026-09-10 | OECD Italy + Hungary; Finland back | Quality-checked lists; 20.19 reads GeoParquet |
29fcf7f, 8963d27, 2aeb6c0; #53, #44 |
44 areas; Italian ranking collapses |
| 2026-09 | #54 open: FRI bound non-convex; 16 areas flagged | Two LPs on one curve | #54 | Awaiting Chris |
¹ settings.jl line 44 defaults TRAVEL_FUNC to QUADRATIC; every production batch sets LINEAR or LOGISTIC.
² The comment at settings.jl lines 91–95 says 12 July; git log -S BIG_TRAVELTIME_MIN first hits 4ec47a9 of 16 July: dated 12 July in the comment, committed together with soft coverage.
³ Old logs, archive/*.jl and Service allocation procedure use x = open.
Open, in this order: doc/todo.md, doc/topics.md, doc/deck_changes_from_review.md, doc/replan_connectivity_fix.md, doc/region_exclusion_for_deck.md, doc/issue*_*.md; then settings.jl, where every knob carries its decision as a comment (big_cost, excluded_nuts_regions); lp_run.jl (build_lp_warmstart for soft coverage, resolve_for_basis! for #52); lambda_sweep_simplex.jl (grid comment around line 293, refinement block around line 317); cfg/main/ModelParameters.dms lines 14–41. Walkthroughs: Code walkthrough settings, Code walkthrough lp_run, Code walkthrough lambda_sweep_simplex, GeoDMS OD matrix and choice set.
- Do not mix numbers across eras. Three regenerations changed every result: 2 July (candidates, clients, logistic), 3 September (landbody, exclusion) and 12 September (OECD Italy, Hungary, Finland, pinned S1/S2 — unpushed). Deck page numbers in commit messages drift with every insertion.
-
Never recorded: why pharmacies replaced schools; why 120 min; why 1-2-5 per decade and the multistart constants; why the first logistic was 30/15; why
NUTS_EXCLUDE_SHAREis 0.5; why the exclusion was built per NUTS region rather than per landbody as Maarten proposed and Chris endorsed (likely because NUTS is the unit the descriptives and deck already use — inference); why Italy moved to ESPON; whose feedback shelved the ladder; whetherStudyArea_default = 'ITG'(flipped by79cb58b, still 'ITG') was kept on purpose. -
Open: the choice-set radius, BN's rescaling, the #54 re-sweeps, and whether the wiki should track e25416b or the unpushed
216ac77. - The mail thread, the methodology draft and the review
.docxare not in the repository; their content is second-hand throughdoc/topics.md,doc/todo.mdanddoc/deck_changes_from_review.md. The Iceland hang is on Running a sweep end to end.
- Alternatives not pursued · Scope rules and data gaps · Scenarios S1 S2 S3 · Travel cost functions
- The lambda sweep and the Pareto frontier · From LP fractions to real pharmacies · Metrics aggregation and ranking
- Branches data and environment · Pharmacy results September 2026 · Lambda sweep method · Background theory · Glossary
Start here
Understanding the method
- The facility location model explained
- Travel cost functions
- The lambda sweep and the Pareto frontier
- From LP fractions to real pharmacies
- Scenarios S1 S2 S3
- Scope rules and data gaps
- Metrics aggregation and ranking
- Background theory
Working with the code
- GeoDMS OD matrix and choice set
- Code walkthrough settings
- Code walkthrough lp_run
- Code walkthrough lambda_sweep_simplex
- Running a sweep end to end
- Log lines and output files
- Deck and charts pipeline
- Installation of Julia
Reference
- Lambda sweep method
- Pharmacy service access
- Pharmacy results September 2026
- Decision log
- Alternatives not pursued
- FAQ
- Glossary
- Service allocation procedure
External