-
Notifications
You must be signed in to change notification settings - Fork 0
FAQ
In one sentence: the questions a colleague asks after months away from the pharmacy model, each answered in a few lines with a link to the page that owns the full story — read this when you need one answer now, follow the link when you need the why.
Where this sits: across the whole pipeline (GeoDMS → Arrow → Julia LP → λ-sweep → rounding → scenarios → deck). Every answer is a compressed pointer into The pipeline in plain words, the method pages and the how-to pages, as of September 2026 (commit e25416b; branch state on Branches data and environment; permalinks pinned to
https://github.com/ObjectVision/NetworkModel_EU/blob/e25416b/). Terms are defined in the Glossary.
λ (lambda) is the price the model charges per open pharmacy cell; the LP (linear programme, an optimisation that allows fractional answers) minimises travel + λ × open cells. w is the knob the sweep turns: λ = w * FACILITY_MIN_COSTS (100 000) in lp_run.jl → solve_at_w!, so w = 0.2 prints as €20 000. The € is a label inherited from the school-era €99 699 and never calibrated (b3c634b); λ's real unit is person-minutes per facility under LINEAR, and changing the constant re-labels λ without moving the frontier or S1/S2. Owner: The lambda sweep and the Pareto frontier.
Both live on the 1 km² population grid: a client is a populated cell weighted by its residents; a candidate is a cell the LP may open — every cell with ≥ 50 residents plus every cell holding a pharmacy today (MinPopSizeForPharmacyLocation := 50, agreed 24 June 2026: ~98 % of pharmacy locations kept in ~2.9 % of EU cells; 7c6768f). Why the 1 km cell is the facility unit is not recorded (b4bc44a). Owner: GeoDMS OD matrix and choice set.
Plot every possible network with x = open cells and y = total population travel cost; the lower-left outline of the achievable points is the Pareto frontier — no network has both fewer pharmacies and less travel than a frontier point. Today's network ★ sits above it. S1 is the frontier point straight below ★ (same count, least travel — what relocation alone saves); S2 the point straight left of it (same travel, fewest locations — how many are surplus); S3 is the curve itself.

Owner: Scenarios S1 S2 S3; formal statement in Lambda sweep method §4.
Because it may open half a pharmacy: on a ring of three clients and three candidates it opens y = (½, ½, ½), splits each client between its two nearest sites and beats every whole-number answer (6 < 7). The relaxation minimises over a larger set that still contains every integer answer, so its value is a certified lower bound — and sum_y (Σ y*, the fractional count of open cells) can read 1.5. Worked triangle on The facility location model explained; theory in Background theory §3.
frac_y (code n_frac) counts candidates with 1e-6 < y* < 1 − 1e-6: cells the LP left part-open. A few dozen out of tens of thousands (29 793 candidates in the May 2026 Netherlands log) means the relaxation is almost a real network; hundreds or thousands (high-λ tails, LOGISTIC generally) mean clients with two equally good options. Before 4cee238 (24 July 2026) the code used x for openness and y for assignment, so old logs, issue #47, Service allocation procedure and the commit message "Sum y<=1" say sum_x/frac_x; doc/build_deck_data.py accepts both. Owner: The facility location model explained (notation table); Log lines and output files ("If you open a pre-July log").
Under hard coverage several areas' full-coverage floor lay above today's count (the Netherlands: 1 899 versus 1 615 existing cells), so S1 could not be found. Soft coverage (Σ x ≤ 1; agreed 10 July, committed 16 July 2026, 4ec47a9) lets a client go unserved at a flat price BIG per resident: big_cost() in settings.jl = c(120 min) = 120 for LINEAR, 1.0 for LOGISTIC, the same everywhere because the earlier per-area worst trip (42 min in Paris, 120 in Norway) broke the cross-area aggregate. Owner: The facility location model explained (soft coverage); Travel cost functions (BIG per function and its history).
★ must be a point of the same problem as the frontier, so baseline_metrics charges BIG for every client with candidate-side OD rows but no existing-side row; before 206923c (6 July 2026) such clients were dropped, which put Denmark's and ITG's baselines below their own frontier. A data gap therefore shows up as a huge BIG bill, hence three scope rules: the country coverage filter (ModelClient in Analyses.dms), the per-landbody network rule (next question) and the NUTS region exclusion — drop a region when more than 50 % of its inhabited cells reach no existing pharmacy (872b388, issue #49; the 50 % is "as agreed", nothing more). Today only the Azores and Madeira are excluded; Portugal's baseline travel fell 62 %. Owner: Scope rules and data gaps.
A landbody is one polygon of a country's multipolygon — mainland, Sicilia, each island. The old rule kept the single largest strongly-connected road component of the whole extract, so an island without a modelled ferry link lost its network and its residents were priced at BIG — 983 169 people in ITG, 84.6 % of its baseline cost. Since 79cb58b (Chris, 31 August 2026) Roads_isConnected keeps the largest component per landbody; no data changed, ITG's baseline mean fell from 22.30 to 4.88 min. Owner: Scope rules and data gaps; configuration in GeoDMS OD matrix and choice set.
GeoDMS grows a shortest-path tree from each client and stops at five cells holding a pharmacy today (limit(...) in impedance_matrix_od64) or 120 minutes (cut(...)). The radius is fixed by today's five nearest and does not grow when the optimiser closes some, so at S2 a client whose five close is priced at BIG — the frontier is under-estimated (SE2: 10.2 % of residents one closure from stranding). Five was a school-era compute choice (issue #22); why 120 is not recorded; widening to 10 is the first roadmap item. Owner: GeoDMS OD matrix and choice set; where it binds on Scope rules and data gaps.
c(t) prices one resident's trip of t minutes. LINEAR (c = t) says a minute is a minute: communicable, but a few remote residents can pull a location towards them. LOGISTIC (c = 1/(1+e^{−(t−25)/10})) is the equity weighting the JRC side asked for — indifferent to short trips, concentrated on moving people from ~45 to ~15 minutes; retuned from 30/15 on 2 July 2026 to match Lewis's ~5- and ~45-minute kinks. The direction of the results survives both (aggregate S1 −26 % travel LINEAR, −13 % LOGISTIC) while λ differs a hundredfold, so never compare costs or λ across the two. Owner: Travel cost functions.
A LOGISTIC trip costs at most 1 per resident against up to 120 under LINEAR, so a location pays for itself at a λ about a hundred times lower: the aggregate's S1 sits at w = 0.130 under LINEAR and 0.00130 under LOGISTIC. Hence SWEEP_WMAX defaults to 0.5 for LOGISTIC and 5.0 for LINEAR, and the Netherlands' whole S1–S2 stretch falls inside one grid step — the "degeneracy" reviewer Martijn Brons noted. Bernhard Nöbauer's proposal to rescale the logistic so c(0) and c(60) match the linear curve is an open group decision (deck p63–64). Owner: Travel cost functions.
At one λ the LP total is a floor no real network can beat and the multistart set is a real network, so travel_relax + λ·sum_y ≤ integer optimum ≤ travel_multi + λ·n_open: that sandwich on total cost is the certified gap. The deck's "multi vs relax" compares travel alone; since n_open = round(sum_y) the facility terms differ by up to λ/2, and the travel-only ratio can even be negative (the Netherlands LINEAR w = 0.02 row).

Owner: From LP fractions to real pharmacies; Background theory §8.
solve_at_w! changes only the y coefficients of an LP built once per area (the cost of serving a client never depends on λ), so the previous optimal basis stays feasible and HiGHS repairs it by dual simplex in a few pivots: 45 876 iterations cold, 1 369 for the next grid point. Each solve must follow the previous one, hence one sequential Julia process per area; parallelism is workers, several run_resweep_batch.ps1 consoles each on its own area. A time-out poisons every later warm start, which is why the tail stops at the first failure (issue #52). Owner: The lambda sweep and the Pareto frontier; Background theory §6.
Sweeping λ never asks for exactly p pharmacies; it prices them, and a sloping line dropped onto the frontier rests only on its lower convex envelope: a count whose point sits above the chord between its neighbours is never touched — the count jumps past it at one λ (the grey point in the figure above). Hence S1/S2 are bracketed between two grid points and bisected. Dents are shallow in practice: S1 landed within 1 % or one facility of today's count in 87 of 88 sweeps, median error 0.13 % (issue #52). Toy with the arithmetic on The lambda sweep and the Pareto frontier; proof sketch in Background theory §5.
The Existing side is one row per cell holding at least one pharmacy (uq_cells). The Netherlands has 1 992 pharmacies in 1 617 cells, of which 1 615 are road-nearest for somebody — the facilities used (cells) line and the S1 target; a cell nobody is nearest to ("empty") is already closed as far as the scoring goes. The raw 1 992 appears only as n-raw, hard-coded for the Netherlands alone; "locations" in the deck means cells. Owner: Scenarios S1 S2 S3; "empty" pharmacies on Metrics aggregation and ranking.
The Netherlands LINEAR row at w = 0.2 (print_sweep_header / print_sweep_row, lambda_sweep_simplex.jl around lines 210 and 221):
w λ (€) sum_y travel_relax travel_topp travel_greedy travel_multi n_open fac_€ mean_t frac_y n-cells n-raw
0.2 20000.0 1899.83 4.1587045e7 4.2340372e7 4.1596596e7 4.1590157e7 1900 1.89983e8 2.3822 57 285 -92
At €20 000 per location the LP wants 1 899.83 cells' worth of openness and says travel cannot go below 41.59 M person-minutes; the multistart rounding opens 1 900 real cells at +0.007 % above that bound — essentially integral, as the 57 fractional candidates confirm. n-cells = +285 over today's 1 615, so S1 lies at a higher price. Owner: Log lines and output files (every column with units).
What do "coverage-consistent" and "coverage-honest" mean, and is mean_t comparable between the baseline block and the sweep rows?
Both say that a client with no reachable pharmacy is charged BIG per resident rather than dropped: coverage-consistent is the baseline's word (baseline_metrics, 206923c), coverage-honest the rounding's (comment above travel_of in lp_run.jl, e1c426b; before June 2026 the rounding metric dropped stranded clients, hiding that top-p abandoned hundreds of rural cells). mean_t is neither: the baseline's mean charges every stranded resident 120 minutes, a sweep row's counts assigned clients only over the whole population (lp_run.jl line 551), so the row is flattered wherever stranding matters — compare the costs, which carry BIG on both sides. Owner: The facility location model explained; the asymmetry on Log lines and output files (units table).
Three constructions: (a) the snapped row — printed scenario summary, scen in deck_data.json, region tables, exported location files — a real solve; (b) chord interpolation between the two bracketing rows — the deck's λ tables and the chart markers ◆ ■; (c) doc/frontier_metrics.py's chord on the Pareto envelope. Snapping is why, before 10 September, one grid row was nearest on both count and travel in FRC, FRH, FRJ, FRK and SE2; since 29fcf7f (10 September, issue #52) each scenario is bisected inside the sweep, so the snapped row is a pinned one (the deck_data.json in this checkout is still pre-#52). The aggregate table snaps to the nearest union row, hence S1 at 43 357 for a baseline of 43 320. Owner: Scenarios S1 S2 S3 ("Which artefact uses which definition"); Metrics aggregation and ranking.
bisect! re-solves at the midpoint in log w (√(lo·hi); eight halvings of a ×2.5 bracket land within ×1.004) until S1 is within 0.2 % of today's count (or one location if that is more) or S2 within 0.2 % of today's travel (REFINE_TOL = 0.002, not recorded as a reasoned choice), or REFINE_ITERS = 8 solves are spent. It prints S1 pinned at w=…: sum_y=… (target …) either way, so always read the residual: Denmark LOGISTIC once reported S2 "pinned" 9.5 % off after a fallback bisection across a failed point (issue #52). Owner: Scenarios S1 S2 S3; the code on Code walkthrough lambda_sweep_simplex.
Frontier chart (e.g. images/Netherlands_LINEAR.png): x = sum_y, left y = total travel cost. Solid blue = travel_multi, the rounded network — the upper bound and "the frontier"; dashed grey = travel_relax, the LP lower bound (where blue rises above grey the rounding is losing something); amber dashed, right axis = log₁₀ λ in €. ★ today; ◆ S1 straight below; ■ S2 where blue crosses today's travel — both interpolated, not snapped. The λ-axis chart (deck p65–66) reads the same sweep along λ: today's travel is the S2 level, today's count the S1 level. Owner: The lambda sweep and the Pareto frontier ("How to read the two charts"); Deck and charts pipeline.
The box spanned by ★, S1 and S2: its width is the locations you could close at equal travel, its height the travel you could save at equal count. rect_rel = (B_x − S2_x)/B_x · (B_y − S1_y)/B_y divides both by today's values because the raw area "mostly ranks by region size" (2a6ea08); the division also cancels the € placeholder. The diagonal from ★ to the far corner hits the frontier at the "balanced improvement" point, and lambda_cross is the price at which the sweep would have picked it; read on chords between solved points, all three slightly under-state the saving. Netherlands LINEAR: 0.274 × 0.199 = 0.055. Owner: Metrics aggregation and ranking.
It was missing data. The 10 September results page ranks ITF 0.268 and ITG 0.261 on rect_rel with Italy on the ESPON 2021 shapefile of 12 991 pharmacies; the OECD-geolocated Ministry of Health list delivered on 7 September has 20 635. On the regenerated results (issue #53, commit 216ac77, not on GitHub) ITG and ITF fall to 0.073 and 0.071 while SE1, Norway, Lithuania and SE2 lead. Never quote a ranking without saying which pharmacy list and which scope rules it was made on. Owner: Branches data and environment; Scope rules and data gaps.
How many study areas are in the aggregate — 41, 42, 43 or 44 — and why does its LOGISTIC range stop at w = 0.02?
Each is right for a different artefact: 42 swept at e25416b (14 countries + 28 NUTS-1 regions) and in doc/deck_data.json; 41 in the aggregate, because country-level Poland overlaps its seven NUTS-1 parts and is dropped; 44 names in build_deck_data.py's ORDER, Hungary and Finland added ahead of their sweeps; 43 disjoint areas in issue #53's regenerated aggregate. The aggregate is summed only over the w-range every area solved (aggregate_fd in doc/build_charts.py): [1e-4, 0.5] under LINEAR but [1e-4, 0.02] under LOGISTIC, because Denmark's LOGISTIC sweep stops at the 9–16 July 2026 w_max of 0.02 (f93aea1; raised to 0.5 in 4ec47a9), so the points 0.05–0.5 solved everywhere else are discarded until Denmark is re-swept. Owner: Metrics aggregation and ranking ("Counting the areas").
settings.jl line 44: travel_func = parse_func("TRAVEL_FUNC", "QUADRATIC") — the school-era placeholder (issue #27) nobody changed when LINEAR and LOGISTIC became the production pair; no commit records why (inertia — inference). A bare julia lambda_sweep_simplex.jl therefore sweeps COUNTRIES = France Italy Netherlands Sweden with a cost function nothing downstream parses. Every runner sets TRAVEL_FUNC and COUNTRIES; do the same by hand. Owner: Travel cost functions; Running a sweep end to end.
The Julia sweep is the whole bill (GeoDMS network + OD takes 9 s to 174 s per area). Full sweeps of both functions in July 2026 took ~81.5 h sequentially for 42 areas — country-level Poland 32.3 h, ITF 7.5 h. With the September tail stop the Italian areas took 1.5–3 h instead of 9–14 h; a refine-only pass 5 min (Luxembourg) to 4 h (Austria) per area and function under six-way contention (#52). --threads=N is inert — the driver spawns no tasks and sets no HiGHS threads option (inference, unmeasured); parallelism is workers, and RAM per big area, not cores, sets how many. Owner: Running a sweep end to end ("How long it takes").
Follow the Hungary/Finland precedent (issues #53, #44): a <iso3>_pharmacies.parquet under <NetworkModelDataDir>/Locations/pharmacies/, an entry in the Country enum of cfg/main/SourceData/Locations.dms, the name in every per-area list (Recipe A names them; COUNTRY_SET in doc/build_deck.mjs was missed for Hungary and Finland at e25416b); then rebuild, descriptives, sweep, deck, export. Iceland (isl) is in the enum but has no study area: it lies outside the Ardeco 2021 population grid, so it has no clients and no pharmacy OD, and a GeoDMS run on it hangs rather than errors (doc/todo.md D10; dropped from every batch on 5 July 2026, d0ae5ef; issue #44). Owner: Running a sweep end to end (Recipe A; the fix table); Branches data and environment §3.
Anything that changes the frontier — settings.jl, lp_run.jl, the grid — needs a full sweep (run_resweep_batch.ps1 -Areas a,b,c -Tag q1). If only where S1/S2 sit on an unchanged frontier matters (the #52 case), refine-only (-RefineOnly) walks the grid LP-only while the count is more than 1.5× today's, bisects each bracket as it closes and stops before the tail. The trap is issue #54: refine points join the old frontier, honest only if the OD and candidate set are unchanged. Owner: Running a sweep end to end (Recipes B, C); the light walk on Code walkthrough lambda_sweep_simplex.
Not from the exit code: the driver catches per-area exceptions, prints <area> — failed: … and exits 0. Grep the log for S1 pinned at w=… and S2 pinned at w=… with a small (target …) residual, then <Area> — scenario summary (what -SkipComplete tests for). Bad signs: FAILED … termination_status=TIME_LIMIT inside a bracket, Neither S1 … nor S2 … bracketed, post-hoc bisection. If the deck parser finds no rows, the log was most likely written by PowerShell's own > as UTF-16 (inference; the runners redirect through cmd /c for this reason). Owner: Running a sweep end to end.
Only the deck: doc/deck_data.json, agg_data.json, the metrics CSVs and the descriptives are committed, so steps 2 onward of doc/README_deck.md re-render the 10 September deck (built on the 3 September data). Nothing pharmacy-related can be solved: logs/, the Arrow exports and the S1/S2 folders live under C:\LocalData\networkmodel_eu\ on Maarten's machine; rebuilding an OD needs the TomTom/population/NUTS/pharmacy share and GeoDMS 20.19.1.m; there is no Project.toml, so Julia package versions are unpinned. Owner: Branches data and environment §5.
No script does it: rerun the deck pipeline (doc/README_deck.md, steps 2 onward), copy the ten PNGs from doc/charts/ (git-ignored) to doc/img/ (committed; last touched 1ed57f2, 10 September 2026), commit, copy them to the wiki's images/, commit and push the wiki. Because the copy is manual the two drift: at wiki HEAD 1d16cc7 the two λ-axis images are older renders than doc/img/. The four images/explainer_*.png figures come from scripts/make_figures.py in the wiki repository, not from the deck. Owner: Branches data and environment §7; Deck and charts pipeline (step 7).
Set STUDY_AREA in the shell before launching the GUI (unset, it falls back to StudyArea_default := 'ITG') and make sure the area's lambda_sweep/<FUNC>/S1, /S2 and …/baseline folders exist on that machine. Then open /Analyses/AllocateClientsToNewPharmacies/SweepResults/lin_S1/OpenFacilities (or log_S1, lin_S2, log_S2), …/ClientTravelTime_Classified for binned minutes, …/dT_lin_S1 for the change against today. SweepResults/baseline errors on any area without a June QUADRATIC folder: Analyses.dms line 381 still reads lambda_sweep/QUADRATIC/baseline. Owner: GeoDMS OD matrix and choice set ("Looking at S1/S2 on a map").
lp_run.jl → build_lp_warmstart (around line 397): one x[k] per OD row, one y[j] per candidate, Σ x ≤ 1 per client, x[k] ≤ y[j] per row. Leaving everybody unserved costs BIG × total population whatever the answer, so that constant is omitted and each x gets the coefficient (c(t) − BIG)·pop ≤ 0; HiGHS's Objective value is therefore travel_relax + λ·sum_y − BIG·Σpop, negative under LINEAR — read the sweep row, never the solver line. λ enters only in solve_at_w! (around line 464); open it first. Owner: Code walkthrough lp_run; the trick on The facility location model explained ("The constant drops out"); Toyland on The pipeline in plain words.
What is PROTECT_BASELINE, why did FRI's S2 once exceed today's count, and which of the four loaders applies it?
LOCATION_SELECTION_FACTOR = K keeps every K-th candidate so a huge area fits a solve (afef439, 27 May 2026; the Existing side is never subsampled). The blind stride also dropped most of today's pharmacy cells — FRI at K = 3 kept 555 of 1 590 — so FRI's S2 landed at 1 772 locations, more than the 1 584 cells in use today. PROTECT_BASELINE=1 (default since f167da2, 21 July 2026) keeps every candidate coinciding with an existing pharmacy cell and strides only the rest: FRI 17 141 → 6 765 candidates with 1 577 of 1 590 baseline cells kept, S2 1 772 → 1 288. Only lambda_sweep_simplex.jl → load_from is on the production path and applies both the guard and the NUTS region exclusion; the other three loaders each apply less, the source of three bugs (f6edc57, d834a7c, the cap ladder without exclusion). Owner: Scope rules and data gaps ("Candidate subsampling and PROTECT_BASELINE"); Code walkthrough settings ("The four loaders").
The .ps1 workers set COUNTRIES=<area>, TRAVEL_FUNC=<fn>, ROUNDING=multistart, MAX_PARALLEL=<Threads> (inert for this driver) and, with -RefineOnly, SWEEP_STOP_AFTER_REFINE=1. They neither set nor clear SOLVER=simplex, LP_TIME_LIMIT=3600, SWEEP_WMAX=5.0 (LINEAR) / 0.5 (LOGISTIC), SWEEP_MULTS=1,2,5, LOCATION_SELECTION_FACTOR=1, REFINE_TOL=0.002, REFINE_ITERS=8 (defaults shown), so a stray value in your shell silently changes every worker you start. The log records only w_max (the Common λ sweep banner), a subsample (kept K of M (factor=F)), the bisection tolerance and cap, and the selected rounding; SOLVER, LP_TIME_LIMIT and SWEEP_MULTS leave no trace. Owner: Running a sweep end to end (Knobs); full tables on Code walkthrough settings and Code walkthrough lambda_sweep_simplex.
Top-p (the p largest y*) and lazy greedy (CELF) are the first two of the ten starting sets that multistart polishes by swaps, so logging them costs nothing; ROUNDING (default multistart) only decides which set is selected for the arrows, cost_c and the S2 bisection. The side-by-side exposed top-p's rural failure in June 2026 (e1c426b): at Austria's LINEAR S2 point top-p strands 806 client cells, greedy 0, multistart 2. Since swaps only ever lower travel, travel_multi ≤ min(travel_topp, travel_greedy) holds by construction. Owner: From LP fractions to real pharmacies.
The May–June 2026 recipe from Lewis and Bernhard was a four-rung ladder — closures decided by a minimum and maximum catchment (residents per pharmacy) in rungs A–C, a price per location only at D — attractive because it needs no euro. Built in a day (cap_scenario.jl, 22 June), run on the Netherlands and de-emphasised the next morning (6dc70f5, "per feedback"; whose is not recorded): Dutch per-cell catchments run from 4 394 (p10) to 34 905 (max), so a cap at the maximum binds nowhere and one at p90 declares a tenth of today's network illegal — "realistic min/max bounds are hard to set". Formally dropped 4 September (ef05320). Owner: Alternatives not pursued §1.
Why is not in the repository — doc/topics.md names only the mail thread of 13 May 2026. What changed: the school LP charged λ per pupil by which an open school fell short of a minimum enrolment, so the penalty could close small schools but never trade count against travel. For pharmacies min_clients = Inf switches that term off and every open location pays the same λ (README §Algorithms); soft coverage came later, and Client became the whole population (033dd32, 2 July). Owner: Alternatives not pursued §2; dates on Decision log.
A reviewer noticed FRI's LINEAR LP lower bound is not convex — and one LP's curve must be, since a sliding line only touches the lower convex envelope. build_deck_data.py had merged FRI's July full sweep — 6 765 of 17 141 candidates (LOCATION_SELECTION_FACTOR=3), solved by IPM, on the pre-landbody OD — with September refine-only points on the full candidate set: two problems on one curve. FRI is being fully re-swept (unpushed); 16 more areas whose July OD differs marginally from the 2 September rebuild await Chris's call (~20 h). Owner: The lambda sweep and the Pareto frontier; per-area provenance on Branches data and environment §6.
ServiceAccess at e25416b is what this wiki documents and the only branch results are reproducible from; origin/main (d9f1f17, 6 August 2026) has ten later commits — nine of them Chris's GeoDMS work — but nothing pharmacy-related, and nothing has been merged either way. Every hash the September issues cite fails git cat-file -t: 216ac77 (the 11–12 September regeneration: OECD Italy, Hungary, Finland, S1/S2 pinned in 87 of 88 sweeps, new deck_data.json, doc/check_s1s2.py) and the four refine-walk refinements of #52 exist only in Maarten's working copy, so the results page is one data generation ahead of the code here. Owner: Branches data and environment §1–2.
In the roadmap's order (ef05320, deck p63): communicate λ in person-minutes per location; widen the choice-set radius 5 → 10 (Norway: 18.6 % of residents one closure from stranding at S2); RSSV candidate reduction (Alternatives not pursued §6); an exact p-median MIP to measure the integrality gap and pin S1/S2 exactly; territorial coverage constraints; decide the logistic rescaling; calibrate the real fixed cost; capacity caps; the #54 re-sweeps. Known but unfiled: the mean_t asymmetry; the stale QUADRATIC wiring in Analyses.dms; frontier_metrics.py interpolating lambda_cross linearly in w while the deck's λ columns use log w (a few percent apart; undecided which is right), and its pareto_frontier envelope, which can lose a genuine solve on a #54-style kinked curve (Metrics aggregation and ranking, Pitfalls). Owner: Decision log (Era 5).
Each answer names the file and function it rests on (settings.jl, lp_run.jl, lambda_sweep_simplex.jl, cfg/main/Analyses.dms, doc/build_deck_data.py, the .ps1 runners); the pinned permalinks and the line-by-line reading live on Code walkthrough settings, Code walkthrough lp_run, Code walkthrough lambda_sweep_simplex, GeoDMS OD matrix and choice set and Deck and charts pipeline.
-
Every number here is the e25416b generation (3 September data, ESPON Italy, snapped S1/S2 in
deck_data.json); the 12 September numbers quoted from issues #52–#54 are unpushed and cannot be verified from a checkout. -
Two S1s, four area counts, two x/y conventions,
mean_tversus cost — the four traps behind most misreadings; each has its question above. -
Rationale never recorded: 120 min; five nearest; 1-2-5 per decade;
REFINE_TOL/REFINE_ITERS;MS_RESTARTS/MS_ROUNDS/MS_SEED; 30/15 as the first logistic;NUTS_EXCLUDE_SHARE = 0.5; the 1 km facility unit; why pharmacies replaced schools; whose feedback shelved the ladder. - Questions this page does not answer belong on Glossary (terms) or Home (reading order).
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