Method

How the model works: where kids live, how far they walk, how lines are redrawn, and how far to trust the results.

Independent analysis by a PPS parent, not an official Portland Public Schools product. Confirm anything that matters against PPS's own materials: PPS rightsizing scenarios and October 6, 2026 Board of Education meeting materials (BoardBook). Built with AI, directed by a PPS parent (how).

Overview

  1. Where kids live comes from 2020 Census blocks (9,295 of them), split into K-5, 6-8 and 9-12 by age and calibrated so that today's attendance areas reproduce 2025-26 neighborhood enrollment. These are estimates, not student addresses. See data foundation and definitions.
  2. Dual Language Immersion (DLI) and focus-option students are counted at the building that hosts their program. Their home locations are estimated, and the share of a moving immersion program’s students that follows the program is implied by PPS's own projections, not stated by PPS (solver, dli_follow.json).
  3. Walking distance is the shortest route on OpenStreetMap streets and paths from each block's center to the school, using a local OSRM foot router. Freeways, rail and the river are crossed only at real crossings. See routing and its validation.
  4. The solver takes the closures and program placements as given (the example plans use PPS A's, except where a plan says otherwise) and redraws only the attendance lines. It aims for PPS's size targets (at least 360 for K-5, 500 for 6-8 and K-8, 1,100 for 9-12, up to building capacity) and then minimizes how far kids walk. See solver method and size targets.
  5. Durability checks the same lines in every year of PPS's projection window, 2027-28 to 2031-32: a plan must match or beat PPS A's count of schools at target in each of those years. Sizes by year follow each school's own PSU July 2026 forecast; 2032-33 to 2035-36 are reported, not required, and nothing past 2035-36 is projected (solver).
  6. The model is tested against real enrollment. Predicting a school's neighborhood enrollment from Census counts alone is off by about 21-27% per school with a uniform rate, and 23-34% out of sample, so any size within about 15% of a threshold is uncertain (backtest).
  7. Results are model estimates, calibrated against PPS’s own projections (how they compare). See Limits.

Every document, dataset and tool we used, with links: How we did this.

Contents

Key finding: shorter walks and more schools at target, with a catch

Why redrawn lines do better on walks and sizes

  • PPS A’s line changes are targeted. It folds each closing school into one or two nearby schools and makes 38 targeted boundary changes (PPS scenario memo, Oct 5, 2026), but it doesn’t redraw lines around every school, so some end up too big and others too small: 20 elementary and middle schools out of range in 2031-32 on our model. PPS’s own projections show the same, such as Clark at 272 (343 with no closures) and Sunnyside, as a K-5, at 235 (the floor is 360), and George at 636 in a 623-seat building (PPS Family Guides, p. 4; capacity from PPS’s 2025-26 school profiles, second-hand).
  • PPS A adds a little to long walks; redrawing removes a lot. With today’s schools and no closures (PPS Status Quo), 1,861 elementary kids are already assigned to a farther school, past a closer open one. PPS A raises that by 109, to 1,970. The current best example we modeled cuts it to 793: 1,068 fewer than with no closures. Sending kids to the closer school also evens out sizes.
  • Size comes first, not as a side effect of walking. Every example plan must keep at least as many schools at target as PPS A, every year to 2031-32; the solver then finds the shortest walks within that.

The catch

To fit the most schools at target, the example plans hold many elementary schools just above the 360-kid minimum: in 2031-32, 17 to 22 are within 20 kids of it across the example plans (17 of 38 under the current best, which keeps Lent, Rigler and César Chávez as neighborhood schools), against 2 of 35 under PPS A.

If enrollment comes in 9% below forecast, only 15 to 17 of the 41 open elementary schools stay in range under the example plans (17 under the current best), against 25 under PPS A. (On the forecast itself: 40 or 41, against 27. The what-if keeps 17 at the 9% drop.)

The misses are shallow, though: under three of the redrawn example plans (Redrawn K-8 lines, Boundary changes, same closures and the previous best), every short school is within 32 kids of 360 (about 580 to 640 kids short in total). PPS A’s short schools are up to 129 kids under, 1,136 short in total. The 9% drop is our own stress test, not a PPS standard; PPS plans on PSU’s forecast, as all our other figures do.

So the example plans do better if PSU’s forecast holds, and worse if it misses. Aiming at a 380-kid buffer didn’t help: 380 less 9% is still under 360.

Sources: dli_home3_rh/TRADEOFFS.md (out-of-range schools under PPS A, kids assigned to a farther school; schools within 20 kids of the floor from each plan’s schools.csv) and BRIEFS.md (the 9% check, levels.K-5.schools_in_range_at_minus9pct in each scorecard.json).

Full methodology (index of documents)

Source: README.md

Solver method

Source: build/solver/METHOD.md

Show the full document: build/solver/METHOD.md

Durability horizon (current): plans must meet or beat Scenario A's count of schools at target in every year 2027-28 → 2031-32 (PPS's projection window); 2032-33 → 2035-36 is reported only; nothing past 2035-36 is modeled. See §7. History: v1 and the early v2 runs used 2031-32 → 2040-41 (PSU's district trend past 2035-36); §3b and §4 describe that older window, which configs without a "horizon" key still use.

Built 2026-10-12. Code: common.py (data), gen_configs.py (plan/option configs), solve.py (CP-SAT engine), metrics.py (scorecard). Python with OR-Tools 9.15 CP-SAT.

python gen_configs.py                     # writes configs/*.json
python metrics.py                         # baselines -> out/baselines/{today,status_quo,scenario_A,scenario_B}/
python solve.py configs/option1.json      # -> out/option1/   (add --from 6-8 to reuse the K-5 checkpoint)

Every output folder holds the same files: assign_K-5.parquet, assign_6-8.parquet and assign_9-12.parquet (idx, GEOID, school), schools.csv (per building), scorecard.json and, for solved options, infeasibility.json and solve_log.txt.

1. Inputs and the 2031-32 basis

  • Blocks: the 9,295 blocks of build/data/blocks.parquet (idx = pps-model BL index). Kids are neighborhood-program kids only (k5, m68, h912). Each block carries its old area's capture rate.
  • Scaling to PSU 2031-32. Each block's count is multiplied by its area's ratio r = PSU 2031-32 neighborhood forecast / modeled 2025-26 neighborhood kids:
    • K-5 by today's K-5 area (es_cur); 6-8 by today's 6-8 area (ms_cur). PSU forecasts each school on today's lines.
    • 9-12 by the Status-Quo 2027-28 area (sq_hs). PSU's 2031-32 HS numbers already include the end of Jefferson dual assignment (Jefferson 377 → 1,172 neighborhood).
    • PSU's "Neighborhood" program row is used where it exists, otherwise "Total". K-8s use the K-8 total ratio for both bands. Cesar Chavez uses its Neighborhood K-8 row (143 → 97).
    • Result: Status Quo lines reproduce PSU's 2031-32 neighborhood numbers by construction. District totals are K-5 13,038 (excluding Lent/Rigler DLI), 6-8 6,023, 9-12 9,261.
    • Ratios run from 0.62 (Sellwood 6-8) to 1.20 (Beach K-5).
  • Lent and Rigler K-5 areas are whole-school Spanish DLI, so their kids follow the program (lr_nbhd_share = 2% are counted as neighborhood kids). PPS's own A projections imply about this much: Kelly gains ~5 from Lent's area, and Scott stays at 470. Their 6-8 and 9-12 kids are ordinary neighborhood kids.
  • Programs (DLI strands, PISA) are fixed populations at their host building, using PSU 2031-32 program rows (common.PROGRAMS).
    • The Cesar Chavez K-8 Spanish program is split 273/443 K-5 and the rest 6-8, by its ODE grade mix.
    • Each config lists which building hosts which program. The Scenario A-based plans use Scenario A's placements.
    • Focus schools (Winterhaven, da Vinci, Odyssey, ACCESS, MLC, Benson) are fixed and outside the size test. Options 3a/3b can dissolve Winterhaven or da Vinci into the blocks with dissolve_programs (homes from focus_dli_homes.parquet).
  • Distances: local-OSRM walk (and bike) miles, block centroid → school (build/routing/*_miles.parquet). All three levels use walk miles in the objective.
    • For 9-12, walk distance is only a proxy: high schoolers ride TriMet, and transit time is the right measure.
    • The scorecard also reports bike miles for 6-8 and 9-12.
  • Hard edges: the pps-model zones are W (west of the Willamette), N (east side north of I-84) and S (east side south of I-84). A block may go to a school whose zone is in its allowed zones (az), or in the zone of its Today/Status-Quo school, which is an existing crossing. That is "no new I-84/Willamette crossings". 82 blocks straddle N/S.

2. Targets (hard, with slack)

BuildingFloorCeiling
K-5360min(functional capacity, 600)
K-8 (Astor, Skyline)500, exempt in district-like runsfunctional capacity (K-8 total)
6-8500functional capacity (85% MS rate is already in it). Harrison Park uses 890 (PPS 2025 model) instead of the 1,006 K-8-era figure
9-121,100slide-21 capacities (Jefferson 1,773, Grant 1,935, McDaniel 1,735, Roosevelt 1,404), LRFP otherwise
  • Sizes count neighborhood kids plus hosted programs.
  • Each bound has a slack variable with a huge penalty: 10,000 kid-miles per kid, which dwarfs any routing gain. A non-zero slack is therefore a proof-of-optimization-level infeasibility report for that school, never a silent relaxation.
  • "Program-only" buildings (Lent, Rigler, Chavez and Richmond under A) have no zone. Their size is fixed by the program placement and checked by the scorecard.
  • HS range (max − min) ≤ 350 is soft, penalized at 2 kid-miles per kid of excess.

3. The model (one engine, run per level)

Variables. x[i,s] ∈ {0,1} for block i and each candidate school s, with exactly one per block.

Candidates.

  • K-5: the 7 nearest (walk) eligible open schools, plus the Status-Quo school if eligible.
  • 6-8: per K-5 zone, the 5 nearest middle schools by kid-weighted walk among those eligible for most of the zone's kids, plus the zone's SQ and Scenario-A middle school. A K-8 zone feeds only its own K-8.
  • 9-12: per 6-8 zone, the 4 nearest high schools, plus SQ and A.
  • Pruning: a candidate is dropped when the block cannot connect to that school's building through blocks that also have it as a candidate. This removed 64 pairs at K-5.

Objective, in kid-miles. Weights are in the config.

  • walk: 1 per kid-mile
  • past a closer school: 0.25 per kid sent at least 0.25 mi further than the nearest eligible open school
  • moved vs Status Quo 2027-28: 0.15 per kid
  • boundary length: 3 per km of attendance-area boundary (shared Voronoi edge length from cowork edges.json; zero on zone lines)
  • optional diversity term (off except in diversity runs): per kid of a school's kids-of-color share outside ±15 points of the district share
  • split feeder: 300 each
  • HS range excess and size slack, as above

Contiguity: exact, by a distance-ordered ("star") rule. Each school's zone must contain its building's block (root).

  • A non-root block may join school s only if at least one neighbor with a strictly smaller geodesic potential φ_s also joins s. φ_s is the shortest-path distance from the root over blocks that have s as a candidate.
  • Every chain of strictly decreasing φ_s ends at the root, so every zone is connected: guaranteed, not repaired.
  • Every reachable block has such a neighbor (its shortest-path predecessor), so no candidate is excluded outright.
  • The rule is a restriction: a zone must be "geodesically star-shaped" around its school. Each run therefore also solves the relaxation with no contiguity. Its bound is a valid lower bound for any plan, contiguous or not, and we report the gap to it.
  • This formulation adds one clause per assignment variable and propagates strongly.
  • What was tried first. Lazy separator cuts (for an island C of s: x[v,s] ≤ Σ x[N(C),s]) are exact in the limit. At 7,500 blocks the 60-second re-solves oscillated: the gap swung between 1% and 19% and islands didn't go to zero, so they were replaced. The cut machinery is still in solve.py as a backstop for schools without a root.
  • Adjacency fix. pps-model NB leaves the rural Skyline / Sauvie / Bybee Lake area as about 35 fragments with no neighbors. Contiguity there was impossible, so common.adjacency() bridges each fragment to its nearest same-zone block (44 bridges, zero boundary length).

Warm starts.

  1. Solve the relaxation from the Scenario-A map hint.
  2. Greedily repair it into a star-feasible assignment (moving violators to a candidate that satisfies the rule, with geodesic-nearest as the fallback, which always satisfies it).
  3. Solve the star model from that hint.

Feeders (6-8 and 9-12).

  • Blocks are grouped by their K-5 zone (at 6-8) or their 6-8 zone (at 9-12), and group members are forced equal: clean feeders by construction.
  • Contiguity uses the same star rule at zone level. The units are connected pieces of zones, with potentials on the zone graph.
  • Phase 2 runs only if phase 1 needs any size slack. It lets a zone split (indicator z_g, x[i,s] − x[rep,s] ≤ z_g) at a cost of 300 per split, and uses block-level star contiguity. Every split is reported.
  • A middle or high school's building block roots its zone. If two buildings share a feeder zone, only the first is rooted, and the other falls back to cuts.

9-12 grouping (durable options). Whole elementary zones go to high schools, so a middle school may split between high schools but no elementary zone does. For each middle zone p and high school h, u[p,h] = OR of its elementary zones' choices. Each u costs ms_split (5,000), so every extra high school a middle zone feeds is penalized, more than the durability reward per school. Last resort (phase 2): block-level assignment within elementary zones, at split (20,000) per split zone. "Shortest walks, sized for 2031-32 only" (option1_2031only) used whole middle zones at 9-12.

Phase 2 is lexicographic for durable runs:

  • 2a minimizes only size slack, durability-count slack and splits (60 s relaxation, 180 s star model).
  • 2b re-solves the full objective with splits ≤ 2a's count, warm-started from 2a without a relaxation round.
  • The 2a assignment is kept if 2b ends with more slack.

Decomposition. Schools are linked when any block may go to both, and each connected set is solved independently. At K-5 this gives two sets: W, and N+S (linked by the 82 straddling blocks). Middle school splits into ~6 regional sets. High school is one set because of the range constraint.

Settings. 6 CP-SAT workers, seed 7. Relaxation 120 s, star model 300 s. Peak memory about 1.4 GB.

3b. Durability mode (default for every option after "Shortest walks, sized for 2031-32 only" (option1_2031only))

This section describes the original (v1 / early v2) 2031-32 → 2040-41 window. Current runs use horizon pps2031 (§7): required 2027-28 → 2031-32, per-school PSU sizes, reward for schools at target in all required years.

"Shortest walks, sized for 2031-32 only" (option1_2031only) packs schools right at the 2031-32 floor. With PSU's continued decline it collapses: K-5 goes 35/35 at target in 2031-32 → 12 in 2032-33 → 9 by 2040-41. Durability mode fixes that.

  • Years and ratios. common.PSU_MEDIUM holds the PSU medium district forecast (Table 5.2) for 2031-32 to 2040-41 by level, with K-5 = K-2 + 3-5. Every school at a level is scaled by the same ratio r_y = total_y / total_2031-32:
    • K-5: min 0.916, so a 360 floor needs 393 in 2031-32 to hold all ten years
    • 6-8: 0.917–1.043 (a 500 floor needs 545)
    • 9-12: min 0.883 (a 1,100 floor needs 1,246)
    • A per-area version would need PSU's per-school Table 5.5 by year. Our extract has only 2025-26 and 2031-32 (and PSU's school table stops at 2035-36), so it isn't done. Low/high scenarios (Tables 5.3/5.4) are not loaded.
  • Model. For each countable school s and year y there's an indicator b[s,y]. b[s,y] ⇒ size_s ≥ ⌈(floor + margin)/r_y⌉ and size_s ≤ ⌊(ceiling − margin)/r_y⌋. Countable means zoned and not floor-exempt.
  • Requirement. Σ_s b[s,y] ≥ (Scenario A's count for year y), using the same metric on the digitized A map. A slack with a penalty of 100,000 kid-miles per missing school makes any shortfall a reported infeasibility. Mode all (used by every current plan) requires every countable school every year.
  • Reward. 3,000 kid-miles per school at target in all ten years (d_s ≤ b[s,y] ∀y), plus 100 per school-year. 2031-32 floors and ceilings stay hard.
  • Splits. The split penalty is raised to 20,000 so splits are still used only for feasibility, not traded for durability.
  • 9-12 grouping (durable options). Whole elementary zones go to high schools, so a middle school may split between high schools but no elementary zone does. For each middle zone p and high school h, u[p,h] = OR of its elementary zones' choices. Each u costs ms_split (5,000), so every extra high school a middle zone feeds is penalized, more than the durability reward per school. Last resort (phase 2): block-level assignment within elementary zones, at split (20,000) per split zone. "Shortest walks, sized for 2031-32 only" (option1_2031only) used whole middle zones at 9-12.

Phase 2 is lexicographic for durable runs:

  • 2a minimizes only size slack, durability-count slack and splits (60 s relaxation, 180 s star model).
  • 2b re-solves the full objective with splits ≤ 2a's count, warm-started from 2a without a relaxation round.
  • The 2a assignment is kept if 2b ends with more slack.

Decomposition. The per-year count spans the district, so all schools at a level are solved as one component. K-5: 9,295 blocks, 65k assignment variables, 180 s relaxation plus 600 s star model.

  • Bounds. The rewards are negative objective terms, which makes the CP-SAT bound loose. For durable runs, read the gap as "unproven" rather than as a quality measure.

4. Scorecard (metrics.py)

The scorecard is the same for every plan and every level. All values use neighborhood kids on the 2031-32 basis.

  • Distance: avg walk (and avg bike for 6-8 and 9-12); % within ½, 1 and 1½ mi (plus 2 for HS).
  • Bus eligibility: kids over Oregon/PPS thresholds: walk > 1 mi at K-5; > 1.5 mi at 6-8, including K-8 6-8 per PPS's grade rule; > 1.5 mi at 9-12. The 9-12 figure ignores the TriMet-stop test.
  • Kids assigned to a farther school, past a closer one: assigned at least 0.25 mi further than the nearest eligible open school at that level, with eligibility meaning no new hard-edge crossing.
  • Size: buildings open and in range (K-8s judged on their K-8 total and listed at both K-5 and 6-8; Astor and Skyline exempt from the floor), min, max and mean utilization. Also in-range counts on the 2025-26 basis and at −9%.
  • Disruption:
    • kids reassigned vs PPS Status Quo (2027-28, no closures); the vs-Today figure is still computed but not shown (Today archived)
    • DLI kids moved, split by "building closes" vs "program moves"
    • split feeders: a destination counts if it gets ≥5% and ≥5 kids
    • % of 6-8 zones feeding one high school
    • HS enrollment range
  • Durability (durability in scorecard.json): zoned non-exempt schools at target each year of the run's horizon (current pps2031: 2027-28 to 2035-36, of which 2027-28 to 2031-32 required, count in all required years = at_target_all_required_years; older runs: 2031-32 to 2040-41, durable_through_2040_41), and each school's first year out of range and by how much. Program-only buildings are counted separately.
  • Equity: dissimilarity index (kids of color vs white kids across schools at each level, Census 2020 under-18 by block from pps-race.csv). Also the kids-of-color share of movers vs the district share.

Baselines:

  • Today: 2025-26 lines; 9-12 uses the pooled dual-assignment clusters, so Jefferson has no neighborhood area.
  • Status Quo 2027-28, PPS Scenario A and PPS Scenario B: digitized PPS maps from blocks.parquet.

5. Known limits

  • Census residents aren't enrollment. Any size within ~15% of a threshold is uncertain (backtest.md). Moved blocks carry their old area's capture rate.
  • DLI and focus home locations are estimated, and DLI 2031-32 sizes are PSU program forecasts held at the host.
  • Spanish HS DLI is regional by home address. Here it sits at its 2025-26 HS host, which matches A.
  • Middle school is solved after K-5, so K-5 lines are chosen without regard to middle school feasibility. A joint model, or a K-5 re-solve with middle school feedback, could remove some splits.
  • 9-12 is judged on walk miles; transit minutes would be better.

6. Model v2 (2026-10-12)

v2 is opt-in per config ("model_version": "v2", configs in configs/v2/, written by gen_configs_v2.py; code in v2.py plus v2 hooks in metrics.py and solve.py). Results go to out_v2/. v1 configs and out/ are untouched and still reproduce (Scenario A v1 building totals checked to within 0.001 kids, 2026-10-12). Calibration against PPS's projections is in out_v2/CALIBRATION.md. Labels: [PPS] stated in a PPS document, [inferred] our arithmetic on PPS numbers, [2nd-hand] from a community source, [choice] our modeling choice.

  1. Focus-lottery students (fix 1). Sunnyside, Bridger and Buckman enroll many students from outside their areas. In-zone students (PPS Enrollment Summary Oct 2025, "own neighborhood school": Sunnyside 219, Bridger 143, Buckman 133 [PPS]) stay on the area's blocks. The rest (ODE 2025-26 enrollment minus in-zone) are a separate population, scaled by the host's PSU row by year. Placement follows each school's own PPS text when the school itself changes, and the Family Guide p. 2 footnote ("we assume that students return to their neighborhood school" [PPS]) only for schools with no change of their own:
    • Buckman closes: its students split 50/50 Abernethy/Sunnyside [PPS: Oct 6 memo, BoardBook file 14509719, p. 2]. Lottery students are a fixed 50/50; in-zone kids follow the line.
    • Sunnyside K-5 lottery students stay through grade 5, with no new admits [PPS: Sunnyside guide p. 3, "permitted to remain through 5th grade"]. The share at Sunnyside is (2032 − year)/6 for 2027-28 to 2031-32 [inferred], then 0. The rest go home. Sunnyside 6-8 lottery students go home [choice; PPS's Hosford projection leaves no room for them].
    • Bridger keeps its K-5 focus [PPS], so its K-5 lottery students stay. Its 6-8 lottery students go to Harrison Park [PPS: Bridger guide p. 3, the stated default].
    • "Home" = Census band residents in the host's 2025-26 high-school cluster, excluding the host and the Lent/Rigler areas [choice; the same rule build/data uses for all focus homes].
  2. Lent-area non-DLI students (fix 2). About 117 Lent-area PPS students attend another neighborhood school (Marysville) [PPS: Enrollment Summary Oct 2025, Lent row; Closure Commutes says 115, 2nd-hand]. They sit on Lent-area blocks and are taken out of Marysville's area count. In today and Status Quo they attend Marysville. In the Scenario A/B baselines they stay with Marysville's students at Arleta, following PPS's stated phase-in [PPS: Marysville guide p. 3, "Avoiding multiple moves: Delaying full implementation …"]. This matches PPS's numbers (Kelly 407 vs 401, Arleta 549 vs 543). Example plans assign them by where they live, like every other kid. Open question: PPS's Kelly projection shows no new Lent-area families after 2028-29 (build/research/pps_internal_gaps.md §1).
  3. DLI arrival shares (fix 3). For each moved strand, the share that arrives at the new host is IMPLIED by PPS's Family Guide projections and PSU's strand forecast [inferred; PPS states no rate]: Atkinson→Lent 0.797–0.803, Scott→Rigler 0.812–0.825, Clark→Woodstock 0.84–0.93, Beach/James John/Sitton→Chávez ≈0.89, Beaumont→Roseway ≈0.90, Vestal and Boise-Eliot/Humboldt moves 1.0 (build/data/v2/dli_follow.json; build/research/follow_rate/report.md). Years after 2031-32 hold the 2031-32 share. Non-arrivals stay at the sending building if it still serves those grades (PPS's numbers show arrive + stay ≈ 100–112% [inferred]); otherwise they go home. A strand that doesn't move (most strands in "Boundary changes, same closures", option2) has no follow rate.
  4. Capacities (fix 4). PPS 2025-26 school profiles' functional capacity (build/data/v2/capacity_2025_26.csv) [PPS numbers, captured 2nd-hand from pps-dli-explorer snapshots; archived in build/pps-texts/school-profiles-2025-26/]. Jefferson is overridden to 1,773 post-modernization [PPS: Sept 15 2026 deck slide 21]. Boise-Eliot/Humboldt's 586 vs the Family Guide's 632 is unexplained.
  5. Utilization (fix 5). 70–100% of functional capacity is a stated PPS aim [PPS: Family Guide glossary p. 2, "Space use goal"; PPS staff, Sept 15 2026 board meeting, https://youtu.be/uAf7l-ChjFo?t=15369]. It's reported, not enforced; the ceiling stays hard at 100%.
  6. Per-school forecasts by year (fix 6). Each area's block kids, each strand and each focus population is scaled by its own PSU July 24, 2026 Table 5.5 row, year by year from 2027-28 to 2035-36 (build/data/v2/psu_table5_5_by_year.csv, parsed from build/pps-texts/boardbook-2026-10/psu-prc-pps-enrollment-forecasts-2026-27-to-2035-36.md) [PPS/PSU]. 2036-37 to 2040-41 extend each row with the PSU medium district trend by level (Table 5.2) [inferred; PSU's school rows stop at 2035-36]. Durability checks each school's own size in each year, and the solver's per-year constraints use the same sizes.
  7. Other v2 settings. Scenario A's 9-12 lines are kept in every option (fixed_assign: A_hs, because feeder splits didn't pay in v1 "Most schools at target, every year" (option1_durable, then named "Most schools that last to 2040-41")). Candidate costs are rebuilt after pruning unreachable candidates (a v1 bug, fixed for v2 only). Solver workers = 4, two runs at a time.
  8. Baseline vs options. The PPS baselines follow PPS's phase-in where PPS states one (Marysville → Arleta; Sellwood MS open through 2027-28 with its Status Quo 6-8 area, closing in 2028 [PPS: Hosford guide p. 3; Sellwood guide 2027-28 = 523], cfg phase_in, 2026-10-20; and enrolled middle schoolers staying when a 6-8 line moves between two open middle schools: 2/3 of the moved kids stay at the old school in 2027-28, 1/3 in 2028-29, i.e. enrolled 7th/8th graders, equal cohorts assumed [PPS: Tubman guide, "Option to stay ... through 8th grade"; schedule fitted to PPS 6-8 guide numbers, inferred], cfg phase_in kind enrolled_stay. Closures and K-8 grade changes move everyone. Applied to 6-8 only; K-5 not tested). Status Quo and Scenario A/B follow PPS's 6-8 maps, including the Rigler-area middle schoolers in Roseway Heights, which PPS's numbers don't reflect (pps_internal_gaps.md §3). Options draw their own lines and assign every kid by where they live.
  9. Scorecard additions. durability.levels[*].schools[*].in_range_by_year (a list aligned with durability.years) and sizes_by_year.
  10. Frontier runs (old 2031-32 → 2040-41 window; paused/superseded by §7): "Shortest walks" (frontier_k17), "Balanced: 19 at target every year" (frontier_k19), "Balanced: 21 at target every year" (frontier_k21): Scenario A's schools, programs and 9-12 lines, with the same hard rule (meet or beat A's count at target every year). There's no per-school durability reward. Instead, durability.min_durable requires at least N schools at target in all ten years (K-5 N = 17 = A, 19, 21; 6-8 none, 7, 8). "Most schools that last to 2040-41" (option1_durable, reward 3,000 kid-miles per durable school) is the end point. See out_v2/FRONTIER.md.
  11. Optional schools (optional_open; used in the capstone tests). A boolean per optional school: a closed school takes no blocks, its root block is free, and its 2031-32 floor applies only if it's open. With cap_receivers_per_closure (option 5 = 2; PPS deck 2026-10-06 p. 11, "Capped receiving schools at no more than two per closure", https://youtu.be/zOUH2Jq7Owo?t=5941), the blocks of a closed school's current area may go to at most 2 schools. The capstone tests also require every open school to be at target in all ten years (penalized slack per school). Buildings holding a fixed program or lottery population are never optional, and nothing is pinned to an optional building (DLI non-arrivals and lottery returners go home instead).
  12. Focus-option closures (options 3a, 3c, 3d). Closed focus programs' students return to neighborhood schools. In option 3a (the live what-if) they return by the catchment they live in, from a per-catchment sheet of 2025-26 focus students (build/pps-texts/focus-students-by-catchment-sheet-2025-26-public.md; second-hand: its first columns match PPS's October 2025 Enrollment Summary, but the per-program columns' source isn't stated); 21 students who live outside PPS aren't returned. Options 3c and 3d (tests) used estimated home locations instead (focus_dli_homes.parquet; district- or cluster-proportional, not published). Returners are split into K-5 and 6-8 by grade. ACCESS serves grades 1-8, so its returners are 5/8 K-5 and 3/8 6-8; its TAG services aren't modeled. Odyssey is a program inside a building, so closing it changes no building.
  13. Solver budget (v2). K-5 relaxation 180 s, first contiguity round 600 s, then up to 2 warm-started 400 s improvement rounds while 2031-32 size slack remains (an improvement round is kept only if it lowers slack). 6-8 phase 2a (feeder splits) gets 600 s; if it finds nothing, the whole-zone phase-1 plan is kept. CP-SAT's optimality gap is reported in solve_log.txt and is large (bounds are weak); results are good feasible plans, not proven optima.
  14. Middle→high feeders. In the 6-8 solve, every high school a middle zone feeds (by Scenario A's fixed 9-12 lines; a destination counts at ≥5 kids of the zone's 9-12 band) costs ms_split = 5,000 kid-miles. At least 70% of middle zones must feed one high school (penalized slack, reported as ms_to_one_hs_short). PPS Scenario A has 80%; PPS's KPI target is 100%.
  15. Elementary zones nest in high-school lines. K-5 candidates are limited to schools whose building sits in the block's own Scenario A high-school area, where the block has such a candidate. PPS's own Scenario A K-5 lines nest in 36 of 37 zones. Without this, no middle plan could reach 70% (5 of 15 at best, proven, with the earlier K-5 zones). Rebalanced PPS A uses a soft version (1 kid-mile per kid across a line) because its 1.5-mile candidate filter plus hard nesting has no contiguous plan.
  16. Tactical high-school lines (option1_durable_hs). It takes the K-5 and 6-8 lines of the earlier v2 solve (no feeder rules) and solves 9-12 by whole elementary zones. A high school may differ from Scenario A's, at 2 kid-miles per kid moved. It must keep each high school in range and meet Scenario A's count at target every year (both penalized), with ms_split per extra high school and ≥70% of middle zones feeding one high school.
  17. Write rule and checks. v2 solves write to out_v2/<run>.staging/. run_queue.py runs check_exclaves.py (every school's blocks connected on the solver adjacency; levels fixed to PPS's traced lines are exempt), writes a generic TRADEOFFS.md, renames the old folder to <run>.prev and swaps the new one in. Only then does it mark MANIFEST done.

7. PPS horizon and soft feeders

A config switch, "horizon" (common.HORIZONS), sets the durability window. Configs without it keep psu2041 (2031-32 → 2040-41, all required, 2036-41 extended with the PSU district trend), so every earlier v2 result still reproduces; the earlier configs of the reruns are kept as configs/v2/<run>_psu2041.json. Generated by gen_configs_v2.py (last block).

  1. Horizon pps2031. Required years 2027-28 → 2031-32: PPS's own projection window ("Estimates cover 2027-28 through 2031-32", PPS Family Guides p. 1, e.g. build/pps-texts/family-guide-sabin.md) [PPS]; PPS measures its targets in 2031-32. The solver requires, at every level and in each required year, at least as many zoned non-exempt schools at target as Scenario A has on the same model (penalized slack, 100,000 kid-miles per school short). Scenario A's counts, recomputed on this window [inferred: our model]: K-5 23, 23, 22, 22, 21; 6-8 9, 10, 9, 7, 7 (10, 9, 9, 7, 7 before the 2026-10-20 phase-in fixes); 9-12 5, 7, 7, 8, 8. Sizes per year come from each school's own PSU July 2026 Table 5.5 row (build/pps-texts/boardbook-2026-10/psu-prc-pps-enrollment-forecasts-2026-27-to-2035-36.md, "Enrollment Projection by Grade Group, 2026-2035") [PSU]. 2032-33 → 2035-36 are scored and reported, not optimized. The 2036-41 extension is dropped: forecasts that far out are too uncertain. The durable reward (3,000 kid-miles) now goes to a school at target in all required years, plus 100 kid-miles per school-year at target in the required years. The 2031-32 floor/ceiling stays a hard (heavily penalized) bound as before.
  2. Scorecard keys under pps2031 (durability): horizon, years (2027-28 … 2035-36), required_years, reported_years; per level at_target_zoned, at_target_all_required_years, at_target_all_years_to_2035_36 (replaces durable_through_2040_41, which is not written under this horizon); per school in_range_by_year, in_range_all_required_years, in_range_all_years; and durability.reference (Scenario A's counts on the same window, short_in_required_years, meets_reference_every_required_year). Baselines and option1_durable_msfeed_off were re-scored on this horizon without re-solving (rescore_pps2031.py).
  3. Middle→high feeders, soft. Each high school a middle zone feeds (≥5 kids of its 9-12 band, by Scenario A's fixed 9-12 lines) costs ms_split = 200 kid-miles, i.e. ~200 per extra high school. No floor (ms_hs_feeder.min_share = 0). Reported: levels.9-12.pct_ms_feeders_to_one_hs (Scenario A: 80% [inferred: our trace of PPS's A maps]); the marginal cost of the next fix is estimated per run in TRADEOFFS.md.
  4. Walkable K-5. No hard nesting of K-5 zones inside Scenario A's high-school lines (§6.15 is off for these runs). A tiny soft cost, 0.1 kid-mile per kid placed in a K-5 school across an A high-school line, breaks near-ties only; it was tested against no nesting at all (_diag_nonest_pps2031), see out_v2/option1_durable/TRADEOFFS.md.
  5. Solver limits. Original v2 limits (not the halved ones): relaxation 180 s, first contiguity round 600 s, cut rounds 60 s, feeder-split phase 2a 60 s / 600 s; 4 workers, two runs at a time.
  6. Boundary changes, same closures (option2). Atkinson Spanish → Lent and Scott Spanish → Rigler are necessary moves (Lent 274 and Rigler 321, below 360, if their strands stay home; both have no neighborhood area in A) [inferred: our model]. Avoided: MLK Jr Mandarin stays at MLK Jr, Beaumont Spanish 6-8 stays at Beaumont. All other strands are placed as in Scenario A. DLI recount: dli_moves_v2.py → out_v2/option2/dli_moves.json.
  7. Rebalanced PPS A (option4). The K-5 candidate filter is a 2.0-mile walk cap (was 1.5 mi, infeasible with contiguity).
  8. Warm starts and phase 2.
    • levels.<lev>.warm_start hints a level from another run's assignment and skips the relaxation round. Hint only, with the same rules and costs. Used for "Boundary changes, same closures" (option2) K-5, whose first original-limits solve stalled, and for "All lines redrawn, walkable K-12" (option1_full) K-5.
    • solver.phase2_warm starts the feeder-split search (phase 2a) from the feasible whole-zone plan instead of a fresh relaxation hint. That hint left dozens of contiguity violations, and 2a then timed out (6-8 kept its whole-zone shortfall) or came back worse than the whole-zone plan. The flag also rejects a phase 2 that doesn't reduce slack.
    • levels.<lev>.max_splits caps the split zones in phase 2.
    • Runs before this fix (option1_durable, option2) used the old phase 2.
  9. Walk-cap fallback (Rebalanced PPS A, option4). A block left with no reachable school inside the cap after pruning gets its 3 nearest-walk schools, plus its neighbours' nearest in-cap school, as candidates (max_walk_fallback_nearest). On the 2.0-mile cap this affects one small block on the Columbia River edge.
  10. "All lines redrawn, walkable K-12" (option1_full).
    • K-5 and 6-8 as "Redrawn K-8 lines" (option1_durable), without the A_hs-relative rules (the feeder penalty and the nesting cost).
    • 9-12 is redrawn from whole elementary zones. ≥75% of middle zones on one high school is near-hard (100,000 kid-miles per zone short). A soft push of 200 kid-miles per zone short of 85% applies, and nothing beyond (parent_floor.soft_to).
    • Elementary zones split at 9-12 only where size or durability needs it, at most 5 (max_splits).
    • High schools: floor 1,100, ceiling = capacity (Jefferson 1,773). Range (KPI < 350) soft. No new I-84/Willamette crossings.
  11. "Shortest walks" (frontier_k17), current rules. As option1_durable, with no durability reward (durable_school = school_year_at_target = 0): the walk-max plan that still meets Scenario A's count in every required year. The old-rules config is frontier_k17_psu2041.json.
  12. Feeder-order solve and phase-2 hint.
    • level_order lets a config solve K-5 → 9-12 → 6-8. "All lines redrawn, walkable K-12" (option1_full) uses it, so its middle zones are drawn inside its own new high-school lines (hs_nest: {"self": true, "hard": true}; each elementary zone takes its majority high school).
    • Phase-2 hint, finding: phase 1 satisfies the zone-level contiguity rule, but phase 2 checks the stricter block-level rule. So the whole-zone plan is not a feasible hint for phase 2a. With all variables fixed to it, CP-SAT returned INFEASIBLE (diagnostic _diag_hint_option4).
    • Phase-2 hint, fix: phase2_warm repairs it block by block (star_repair without groups) and turns on CP-SAT's repair_hint (phase2_hint_mode: "repair") for the few violations left.
  13. Phase-2 warm start: not a reliable fix. With phase2_warm + repair_hint, phase 2a still found no plan in 600 s for the 6-8 levels of option1_durable, option2 (hint with 0 violations), option4 and option1_full; it worked for option1_full's 9-12 (4 splits) and frontier_k17's 6-8 (8 splits). The old relaxation-hint path found 15 / 13 split plans for option1_durable / option2. The cause isn't known: the hint satisfies the connectivity rule, so something else in the split model rejects or ignores it. The warm start stays optional per plan.

8. Closeness by level

Priority: closeness matters most for elementary, less for middle, least for high school. How the model reflects it:

  • High school (most flexible): every current plan keeps PPS A's traced 9-12 lines. We don't redraw them. ("All lines redrawn", which did, was dropped: its high-school trips were longer than PPS A's, 2.06 vs 1.93 mi.)
  • Middle (more flexible): built from whole elementary zones (classmates stay together). It has a small penalty per extra high school a middle zone feeds, and PPS's 1.5-mile bus line (Transportation Service Guidelines §D.1).
  • Elementary (closeness first): drawn for walking and size only, with PPS's 1-mile bus line.
  • What it does not do (yet): each level is solved separately with the same walking weight (1 kid-mile per kid-mile) and the same past-a-closer-school penalty (0.25 kid-mile per kid). So no explicit rule says an elementary mile matters more than a middle-school mile.
  • Test of an explicit rule: option2_k5close gives "Boundary changes, same closures" a 4× K-5 past-a-closer-school penalty (1.0 instead of 0.25; config levels.K-5.weights, honored by solve.py _costs), leaving 6-8 unchanged. It shows what weighting elementary closeness more costs in schools at target and kids moved.
  • Not a lever for feeders: lowering the middle-school walking weight would not fix middle→high feeders. Elementary zones that straddle PPS A's HS lines block that at the middle level even at 10× the feeder penalty (option1_durable/TRADEOFFS.md, "Feeder sensitivity").

9. Line cleanup

The solver's boundary-length cost (3 kid-miles per km) was too weak to stop one-block trades for slightly shorter walks, so the walk redraws had more one-block notches than PPS's own lines. Cleanup method:

  • Stronger K-5 line cost. K-5 boundary-length cost raised in rounds to 15, 30 and 45 kid-miles per km, with past-a-closer-school 1.0 kid-mile per kid. Per-level weights are honored by solve.py _weights / _costs via levels.<lev>.weights.
  • 6-8 kept block for block (levels.6-8.fixed_run).
  • Rule-preserving cleanup (smooth_v2.py).
  • Gated swap-in (promote_clean.py), driven by clean_plan.sh.

Line quality is measured by lines_qa.py. Results and criteria are in out_v2/LINES_QA.md. "Rebalanced PPS A" (option4) is not cleaned: its notches exist to fix sizes, and cleaning them moves more kids.

Dropped: letting the solver pick which schools close

A two-stage test (capstone2.sh, capstone3.sh) let the solver choose which elementary and middle schools stay open. Stage 1 picked schools on tied pieces of the map; stage 2 redrew lines block by block. Every open school had to be at target every year, with PPS A's high-school lines. With program hosts fixed, so that no more immersion students move than in the earlier best (1,226), it closed 15 K-5 schools and Gray and Sellwood middle schools. Elementary kids assigned past a closer school fell to 866, but middle-school walks rose to 2.09 mi and 8,754 students were reassigned. It didn't beat PPS A's closures with redrawn lines. The earlier version moved immersion programs (1,611 students) and is ruled out by the rule that no plan moves more than PPS A's 1,567.

Data foundation

Source: build/data/README.md

Show the full document: build/data/README.md

Built 2026-10-11/12. Everything here can be regenerated with scripts/01..10 (run in numeric order, with the kit's .venv). The Census key is read at run time from the CENSUS_API_KEY environment variable and is never written to disk.

Deliverables

FileWhat it is
schools.csv83 rows: every K-5, K-8, 6-8 and 9-12 neighborhood school plus focus and alternative programs (Winterhaven, da Vinci, Richmond, Odyssey, ACCESS, MLC, Benson, Alliance). Columns: ids, lat/lon, capacity, 2025-26 enrollment by grade, the PSU neighborhood/DLI split, DLI strands, the modeled neighborhood kids, and PPS's 2031-32 projections under No change, A and B.
boundaries/current_K-5_K-8.geojson, current_6-8.geojson, current_9-12.geojson, current_cells_all_levels.geojsonToday's attendance areas. In the 9-12 file, the Jefferson dual-assignment zones are separate features with a cluster_2025_26 field.
blocks.parquet / blocks.csvThe 9,295 blocks from pps-model.json, in the same order (idx = BL index, so NB adjacency still applies). Each block has: current schools at each level; calibrated kids by band (k5, m68, h912); the old s_model; the raw Census counts; the calibration factors; and assignments under the Status Quo 2027-28, A and B maps at every level, each with a *_how method flag.
focus_dli.csv41 programs: 35 DLI strands, plus Winterhaven, da Vinci, Odyssey, ACCESS, MLC and Benson. Each row has 2025-26 enrollment, an estimated by-grade split, the host building and the home-location assumption.
focus_dli_homes.parquetBlock x program matrix of estimated home locations (each column sums to the program's enrollment).
scenarios.jsonScenarios A and B at every level: closures and receivers, K-8 conversions, middle and high school changes, DLI and program moves with 2025-26 counts, renames, and block-level flows (from → to, kids). It also holds PPS's own per-school projections for 2027-28 to 2031-32 from the 82 Family Guides.
scenario_maps/{status_quo,scenario_A,scenario_B}_{K-5,6-8,9-12}.geojsonLabeled polygons digitized from PPS's 2027-28 map PDFs, including scenario_A_6-8.geojson.
backtest.mdThe gate: modeled vs actual by school at every level.
raw/Downloaded sources (listed below). work/ holds intermediates. scripts/ holds the code.

Sources (all downloaded 2026-10-11)

SourceUsed forVintage
data/pps-map/pps-model.json (read only)Block universe (GEOID, centroid, pop, hu, a, s, NB)Built Oct 2026 from 2020 Census
US Census 2020 DHC, API api.census.gov/data/2020/dec/dhc: P12 (sex by 5-year age) at block level and PCT12 (single year of age) at tract level, counties 41051/41067/41005 → raw/census/Age bandsCensus day 2020-04-01
ODE Fall Membership 2025-26 (PPS Data Explorer, data/raw/fall_membership_2025_26.xlsx, sheet "School 20252026", Portland SD 1J)Enrollment by school and gradeOct 1 2025
PSU Population Research Center, PPS Enrollment Forecasts 2026-27 to 2035-36 (July 2026), Table 5.5 (PPS Data Explorer pps_enrollment_forecast_2026.pdf / .csv)Neighborhood vs DLI-program split by school (2025-26), Odyssey/ACCESS counts, 10-year forecastHistoric 2025-26
PPS Enrollment Details for Language Immersion Schools, Oct 2025 (PPS Data Explorer pps_immersion_details_2526.json)Cross-check of DLI counts (it matches PRC within a few students)Oct 2025
PPS Data Explorer, data/pps_schools.csv (commit 80ec323, 2026-10-05)NCES ids, lat/lon, LRFP 2021 functional capacity (and the "model" variant), seismic/URM, DLI languagesMixed; capacity is 2021
City of Portland School_Boundaries FeatureServer (services.arcgis.com/quVN97tn06YNGj9s/.../School_Boundaries/FeatureServer/0, 59 PPS cells, lastEdit 2025-11-03) → raw/boundaries/Current attendance areas at all 3 levelsIdentical in area (ratio 0.99992) to PPS's PPS_Boundaries_All_Grades_22_23_DRAFT service, whose layer is "PPS_Boundaries_All_Grades_23_24_FINAL" (board-approved SEGC lines in effect 2023-24 through 2025-26). Also saved.
PPS board memo Rightsizing Update: Scenario Release (Oct 5 2026) and 4 regional summaries (PPS Data Explorer pps_rightsizing_board_2026-10-06/)Scenario structureOct 3-5 2026
PPS Family Guides, one PDF per school (82), reached through the Awesome Table on pps.net/.../rightsize/how-could-your-school-be-impacted. Google Drive ids are in raw/family_guides/index.tsv.Per-school proposals and PPS projections (No change / A / B, 2027-28 to 2031-32)Oct 2026
PPS attendance-area map PDFs (Status Quo/A/B x K-5/6-8/9-12, "School Year 2027-28"), BoardBook org 915, files 14505795-14505805, via meetings.boardbook.org/Documents/DownloadPDF/<id>?org=915. The A 6-8 map is also the user's Downloads copy. → raw/scenario_maps/Digitized scenario linesModel 2026-09-24, version 10/03/2026

The scenario-page Drive links (overview and regional) are the same documents as the BoardBook memo and summaries.

Method

Age bands (2020 DHC)
  • P12 gives each block 5-9, 10-14 and 15-17. PCT12 single-year ages at the tract level split each band into single years.
  • Grade mapping. On Census day (Apr 1), with a Sept 1 cutoff, grade g is 5/12 age g+5 and 7/12 age g+6. That gives these weights:
    • K-5 = 5/12·age5 + ages 6-10 + 7/12·age11
    • 6-8 = 5/12·age11 + ages 12-13 + 7/12·age14
    • 9-12 = 5/12·age14 + ages 15-17 + 7/12·age18
    • Age 18 is not in the under-18 tables, so it is approximated by the age-17 count.
  • Smoothing. Block-level DHC ages carry differential-privacy noise. Each block's raw count is therefore block pop × (block-group band count ÷ block-group pop). This is the same smoothing the first-generation model's per-block student estimate (column s in pps-model.json) used, which we reverse-engineered: that estimate matches pop × the block-group under-18 rate within 0.8% dissimilarity.
  • These are where kids of grade age lived in 2020, used as the spatial pattern for 2025-26. Cohorts are not aged forward, because families move as children age. Totals come from enrollment, so Census levels don't matter, only the spatial pattern.
Targets (2025-26 neighborhood-program enrollment)
  • K-5 area. The PRC Table 5.5 "Neighborhood" row where PRC splits out a DLI program. Otherwise ODE grades K-5. Special cases:
    • Hayhurst = 290. ODE's 508 includes Odyssey.
    • Cesar Chavez = 143 neighborhood K-8 × 273/443 = 88.
    • Lent and Rigler, whole-school Spanish DLI with their own areas, use their full K-5 enrollment (256, 291), as the old model did.
    • Bridger, Sunnyside and Buckman include their focus-lottery students. PPS doesn't publish that share.
  • 6-8 area. The PRC Neighborhood row for middle schools (Beaumont 315, George 249, Tubman 354, Harrison Park 308, Kellogg 330, Lane 411, Mt Tabor 208, Ockley Green 397, Roseway 415, West Sylvan 567). Otherwise ODE grades 6-8 (Gray, Hosford, Jackson, Sellwood, and the K-8s; Cesar Chavez = 55).
  • 9-12. PRC Neighborhood rows: Cleveland 1336, Franklin 1578, Grant 1809, Jefferson 377, Lincoln 1469, McDaniel 1325, Roosevelt 1082, Wells 1574 (total; Wells has no program split). Benson, MLC, Alliance and PISA are excluded.
    • In 2025-26 the "Jefferson / X" zones could choose Jefferson or X. Each X is therefore calibrated as a cluster (X-only cells plus Jefferson/X cells). Jefferson's 377 is spread across the three dual zones in proportion to their raw 9-12 counts and added to the cluster targets.
  • Calibration. Each block's band count = raw × (area target ÷ area raw sum). The "capture factor" (f_es, f_ms, f_hs) stays with the block when lines move. Totals: K-5 14,372, 6-8 7,218, 9-12 10,550.
K-5: why k5 replaces s (and s is kept as s_model)
  1. 2025-26 targets instead of 2024-25 NCES totals, and the published PRC neighborhood/DLI split instead of hand estimates. The clear error this fixes: s gave Hayhurst 451, but 161 of those are Odyssey students (Odyssey is reported inside Hayhurst), so the right figure is 290. Clark's DLI was 72 in s; the actual is 91.
  2. Grade-specific ages (5-11) instead of all under-18 for the within-area distribution. This is a small gain: uniform-rate MAPE 21.1% vs 21.4%.
  • Net effect: total 14,372 vs 14,897. Areas differ from s by 6.6% MAPE, mostly the 2024-25 → 2025-26 decline.
Digitizing the scenario maps
  • The PDFs are vector, so no raster tracing was needed. Boundary lines are distinct styled paths: K-5 gold 3pt, 6-8 teal 3pt, 9-12 blue 11pt. K-8 lines are dashed maroon.
  • Georeferencing. One affine PDF→EPSG:2913 transform for all nine maps, which share the identical sheet layout:
    • Start from 24 school-label positions matched to school coordinates.
    • Refine by ICP of the Status-Quo 6-8 lines against today's middle-school lines.
    • Residual: median 71 ft, p90 143 ft. Scale is 27.88 ft/pt on both axes.
  • Labeling. Each polygon is named by regex on the label words it contains ("X K-5 Neighborhood", "X Middle School", "X High School"). Whole-school DLI schools (Lent, Rigler, Cesar Chavez, Richmond) never take a neighborhood label. Two unlabeled polygons (West Sylvan and Lincoln, whose labels sit outside their own polygons) are named by the majority current school of their blocks.
  • Block assignment. Each block goes to the smallest digitized polygon containing its centroid. Fallbacks, with the method in *_how:
    • k8_rule: K-8 areas are drawn dashed and not digitized, so those blocks keep their K-8. That means today's 9 K-8s in the Status Quo, and Astor and Skyline in A/B.
    • bybee_rule: in A/B, Faubion's Bybee Lake Shelter blocks → Astor.
    • skyline_rule: Skyline area is inset-only. 9-12 = Lincoln in SQ, Roosevelt in A/B.
    • nearest: 5-115 sliver blocks per map along rivers and gaps.
  • QA against today. Status-Quo K-5 agrees with current lines on 99.9% of blocks. 6-8 agrees on 98.7%; all 100 disagreements are the Rigler K-5 area, which the 2027-28 SQ map draws in Roseway Heights while the 2023-24 layer has Beaumont. We kept Beaumont for "today" because it fits enrollment better (backtest.md). 9-12 agrees except the dual zones, which the 2027-28 map shows as Jefferson-only. That is the phase-in of Jefferson's own boundary, which the Grant family guide confirms ("ending of Dual Assignment").
  • Because the maps digitized reliably, this is a real polygon digitization, not block-rule reconstruction. The polygon GeoJSONs omit K-8 dashed areas and the Skyline inset, so blocks.parquet is the authoritative assignment.
focus_dli home locations (assumption, not published)
  • Strand homes are proportional to Census band residents (raw_*) in the host school's 2025-26 HS cluster. PPS gives DLI lottery priority to the neighborhood, then the cluster.
  • Exceptions:
    • Japanese DLI (Richmond, Mt Tabor, Grant), Cleveland Mandarin and all focus programs are district-wide.
    • Lent and Rigler use their own area, and their students are already inside the block k5 counts. Don't double count them.
  • By-grade counts = strand total × the host school's ODE grade distribution within the band. PPS publishes DLI counts by school and program, not by grade.

Assumptions the solver must know

  1. Block kids are neighborhood-program kids only. DLI-strand and focus students are separate fixed populations (focus_dli.csv); Lent and Rigler are the exception (item 3). To close Winterhaven or da Vinci (option 3), add their focus_dli_homes columns to the blocks.
  2. Capture factors move with blocks. A moved block brings its old area's enrollment propensity. The out-of-sample error of predicting a school from Census alone is about 21-23% MAPE at K-5 and about 27% at 6-8 (17% when carrying K-5 factors), so treat sizes within ~15% of 360/500/1,100 as uncertain.
  3. Lent and Rigler areas are whole-school DLI. Their k5 (256 and 291) is all DLI students. Under A/B, Lent's area goes to Kelly and Rigler's to Scott, but PPS's own projections imply nearly all of those students stay with the DLI program: Kelly A gains about 5, and Scott A = 512 in 2027-28, not the ~755 a naive block sum gives. Treat these blocks (es_cur in {Lent, Rigler}) as DLI kids that follow the program unless you deliberately model otherwise.
  4. Sunnyside, Bridger and Buckman k5/m68 include focus-lottery students (capture 0.84-1.23). Under A/B, Sunnyside's focus ends and Buckman's arts program closes, so those areas' factors are probably too high for future years.
  5. The basis is 2025-26. PPS's projections are for 2031-32 (district K-5 down about 9%); scale by year if needed. schools.csv has PRC's 2031-32 forecast and PPS's 2031-32 scenario projections.
  6. 9-12 "current" is the cluster (hs_cluster_cur) with the dual zones pooled; hs_zone_cur keeps the raw zone. For future-year HS work use sq_hs, where Jefferson has its own area.
  7. Names.
    • K-5 uses pps-model.json names; Lee = Sunrise.
    • Middle schools use City layer names: Lane = Brentwood, Tubman = Harriet Tubman, Gray = Robert Gray.
    • "Ida B. Wells" = Ida B. Wells-Barnett.
  8. Middle-school areas follow elementary areas in the current layer, except where the City cells split Bridlemile (Gray/West Sylvan), Faubion (2 HS), Vestal, Whitman, Woodmere and Woodstock (HS splits). Feeder cleanliness can be built on whole elementary areas.

Biggest gaps

  • Where DLI and focus students live is not published. Their homes are an assumption (cluster- or district-proportional).
  • The focus-lottery share at Sunnyside, Bridger and Buckman is unknown, and so are transfer in/out flows by school. That is the main driver of the 20%+ structural error.
  • DLI counts exist only by school and program, not by grade. The grade split is estimated.
  • Capacity is the LRFP 2021 functional capacity. PPS Data Explorer's "model" capacity differs for about 10 schools, and both are given. The family guides cite slightly different "can hold" numbers (Arleta 653 vs 696; Abernethy 441 vs 522; Hosford n/a), so PPS's current capacity model isn't public.
  • ACCESS isn't a separate ODE school (PRC: 324), and its grade split is unknown.
  • Clark has no NCES id in CCD 2022 because it opened in 2023.
  • K-8 dashed lines weren't digitized as polygons. The blocks use rules instead, which matter only for Astor's Bybee Lake gain (5 blocks).

Accuracy: backtest against real enrollment

Source: build/data/backtest.md

Show the full document: build/data/backtest.md

Built 2026-10-12 by scripts/04_calibrate.py + scripts/10_backtest_md.py. All numbers are 2025-26 neighborhood-program students (school enrollment minus DLI strands, focus/lottery programs and newcomer programs where PPS/PSU publish the split; see README "Targets").

Read this first: two different tests

  1. Final calibrated blocks vs today (the solver's input). Each block's kids = Census-based raw count x its current area's capture factor, so blocks summed over today's lines reproduce actual neighborhood enrollment exactly (0.0% error at every school, every level). That is by construction, not evidence. It is the same convention the first-generation model's per-block estimate (s in pps-model.json) used.
  2. Structural backtest (the real gate). Ignore each school's own enrollment and predict it from Census residents alone:
    • uniform: one district-wide capture rate per level;
    • LOO-cluster: the capture rate of the other schools in the same high-school cluster (leave-one-out) - this is the honest out-of-sample number;
    • cross-level: carry each block's K-5 capture factor into its 6-8 kids (and 6-8 into 9-12). This measures how much school-to-school variation in "who actually enrolls in the neighborhood school" exists beyond Census age counts. It bounds the error for blocks that change school, because a moved block carries its old area's capture factor.

Summary

levelareasdistrict capture (nbhd enrolled / Census-age residents)MAPE uniformMAPE LOO-clusterMAPE cross-levelWAPE uniformschools >15% (uniform)final calibrated MAPE
K-5530.5021.1%23.2%n/a19.5%300.0%
6-8230.5027.1%34.0%16.9% (from K-5 factors)22.3%150.0%
9-12 (7 cluster units)70.5912.4%n/a14.5% (from 6-8 factors)12.7%20.0%

Other checks:

  • K-5 raw proxy: grade-specific ages (this build) MAPE 21.1% vs all-under-18 proxy (the old s method) 21.4% under a uniform rate - a small improvement, not a large one.
  • Old s (2024-25 NCES totals minus immersion estimates) vs 2025-26 neighborhood actuals: MAPE 6.6%. Biggest miss: Hayhurst s=451 vs 290 - the old K5 count included the Odyssey K-8 program (ODE reports it inside Hayhurst). Old s sums to 14,897; new k5 sums to 14372.
  • 6-8 Rigler question: the PPS 2027-28 Status-Quo map draws the Rigler K-5 area in Roseway Heights; the City/PPS 2023-24 layer has it in Beaumont. Moving it raises MAPE (27.1% -> 28.3%) and pushes Roseway to +33%/Beaumont to -23%, so the current-layer assignment (Beaumont) is kept for calibration.

Verdict

  • Census residents alone are a weak predictor of who enrolls in each neighborhood school: capture rates run from ~0.27 (Beach, Cesar Chavez: DLI-dominated) to >1 (Bridger, Sunnyside: focus lotteries). The out-of-sample error (LOO-cluster MAPE ~23% K-5, ~34% 6-8) is the honest "model error" for any school whose population is mostly new territory.
  • Because calibration is per area, the solver's error is concentrated in moved blocks: they carry their old area's capture rate. For boundary edits between similar neighborhoods this is small; for blocks moving out of DLI/focus-heavy areas (Beach, Cesar Chavez, Rigler, Lent, Sunnyside, Bridger, Buckman) it can be large - see README "Assumptions the solver must know".
  • The gate passes in the sense that matters (today is reproduced exactly; total kids per level are right; cross-level carry-over of capture factors cuts the 6-8 error from 27% to 17%), but any school-size result within ~15% of a threshold (360 / 500 / 1,100) should be treated as uncertain.

K-5 (53 current K-5/K-8 areas)

schoolactual nbhd 2025-26Census rawcaptureuniform-rate prederr %LOO-cluster err %final calibratedflag
Beach1334930.27249+87+77133>15%
Cesar Chavez883240.27163+85+7288>15%
Bridger3062481.23125-59-56306>15%
Chapman33310140.33512+54+49333>15%
Whitman1935640.34284+47+56193>15%
Sunnyside2923290.89166-43-38292>15%
Buckman2833360.84169-40-43283>15%
Marysville3043890.78197-35-29304>15%
Atkinson1884960.38250+33+58188>15%
Rosa Parks1604190.38212+32+21160>15%
Rose City Park2105450.39275+31+30210>15%
Laurelhurst3795390.70272-28-21379>15%
Ainsworth2736910.40349+28+14273>15%
Lewis2623750.70189-28-30262>15%
Abernethy2696790.40343+27+34269>15%
Lent2563690.69186-27-19256>15%
Faubion3775640.67284-25-31377>15%
Clark2736720.41339+24+23273>15%
Woodlawn3234860.67245-24-36323>15%
Woodstock1774310.41217+23+26177>15%
Alameda5158000.64404-22-13515>15%
James John2325560.42281+21+10232>15%
Boise-Eliot/Humboldt2954650.63235-20-10295>15%
Astor2644180.63211-20-31264>15%
Sitton2074890.42247+19+8207>15%
Scott2545930.43299+18+15254>15%
Glencoe3417920.43400+17+41341>15%
Arleta2305320.43268+17+37230>15%
Skyline1392310.60116-16-29139>15%
Forest Park2646040.44305+16+0264>15%
Markham3397720.44390+15+11339
Rieke2666040.44305+15+10266
Bridlemile4237250.58366-13-32423
MLK Jr1262820.45142+13+32126
Vestal2866200.46313+9+6286
Creston2194740.46239+9+27219
Duniway3626540.55330-9-9362
Chief Joseph2475320.46269+9-3247
Stephenson2815120.55258-8-15281
Llewellyn3456350.54320-7-7345
Beverly Cleary2765140.54260-6+9276
Rigler2915450.53275-6-10291
Grout3276840.48345+6+8327
Kelly2685020.53253-6+9268
Capitol Hill3296820.48344+5-1329
Maplewood2885940.48300+4-2288
Peninsula2394550.53230-4-15239
Sabin2705470.49276+2+21270
Lee2514860.52245-2-7251
Hayhurst2905870.49296+2-4290
Woodmere2264400.51222-2+13226
Irvington2595090.51257-1+16259
Vernon3446780.51342-1-5344
K-5 schools off by more than 15% (uniform rate) and likely why (hypotheses from program/transfer patterns - not verified with PPS transfer data)
  • Beach (+87%): Half of the building is the Spanish DLI strand; in-area kids who enroll in the DLI are not 'neighborhood' (capture 0.27).
  • Cesar Chavez (+85%): 2/3 of the school is Spanish DLI; neighborhood program is only ~88 K-5 kids.
  • Bridger (-59%): Creative Science focus lottery draws students from outside the area (capture >100%).
  • Chapman (+54%): Downtown/NW: high private-school share and many Census kids in non-family housing; also feeds Ainsworth DLI.
  • Whitman (+47%): Low capture: transfers out (charters, Lent DLI, Winterhaven/focus) in outer SE.
  • Sunnyside (-43%): Environmental focus lottery draws from outside the area (capture ~0.9-1.2).
  • Buckman (-40%): Arts focus option draws from outside the area.
  • Marysville (-35%): High capture; area also feeds Lent DLI under SEGC history; small raw base.
  • Atkinson (+33%): Half the school is Spanish DLI (not counted); transfers out to Winterhaven/Richmond/focus nearby.
  • Rosa Parks (+32%): Transfers out (charters, Cesar Chavez DLI), plus Census undercount of churn in subsidized housing.
  • Rose City Park (+31%): Half the school is Vietnamese DLI (not counted); transfers out.
  • Laurelhurst (-28%): Very high neighborhood capture (affluent, popular K-8); few DLI/private drains measured.
  • Ainsworth (+28%): Half the school is Spanish DLI; downtown private-school share.
  • Lewis (-28%): Small, high-capture area (Sellwood/Westmoreland).
  • Abernethy (+27%): Close-in SE with private/focus (Winterhaven, Sunnyside, Richmond) drain.
  • Lent (-27%): Whole-school Spanish DLI: enrollment includes DLI students from outside the small area.
  • Faubion (-25%): K-8 with high in-area capture plus transfers in (new building).
  • Clark (+24%): Mandarin DLI not counted; outer-SE transfers out.
  • Woodlawn (-24%): Transfers in / high capture relative to Census age counts.
  • Woodstock (+23%): Mandarin DLI not counted; Winterhaven/da Vinci draw nearby.
  • Alameda (-22%): High-income area with very high public-school capture and transfers in.
  • James John (+21%): Spanish DLI strand not counted.
  • Boise-Eliot/Humboldt (-20%): Transfers in; Census 2020 kids undercount 2025 (new housing in Eliot/Lloyd).
  • Astor (-20%): K-8 with high capture; area is small relative to its draw.
  • Sitton (+19%): Spanish DLI strand not counted.
  • Scott (+18%): Spanish DLI strand not counted.
  • Glencoe (+17%): Richmond (Japanese DLI) and focus schools draw from this area.
  • Arleta (+17%): Transfers out (Lent DLI, charters).
  • Skyline (-16%): Rural area, tiny Census base; K-8 draws some out-of-area students.
  • Forest Park (+16%): High private-school share in NW hills.

6-8 (23 current middle areas; K-8s count their own 6-8)

schoolactual nbhd 2025-26Census rawcaptureuniform-rate prederr %LOO-cluster err %final calibratedflag
George2498030.31404+62+55249>15%
Cesar Chavez551720.3286+58+3255>15%
Sunnyside1931641.1883-57-47193>15%
Bridger1401251.1263-55-42140>15%
Harrison Park3089140.34460+49+79308>15%
Laurelhurst2352620.90132-44-52235>15%
Faubion2232670.83135-40-46223>15%
Astor1371830.7592-33-49137>15%
Tubman3549070.39457+29+42354>15%
Beaumont3157870.40396+26+34315>15%
Sellwood5668340.68420-26-33566>15%
West Sylvan56713960.41703+24+39567>15%
Beverly Cleary2043140.65158-23-29204>15%
Lane4119780.42493+20+35411>15%
Vernon1953250.60164-16-20195>15%
Skyline681200.5661-11-2868
Ockley Green3978730.46440+11-16397
Kellogg3305860.56295-11+43330
Gray4327860.55396-8-2432
Mt Tabor2083820.54193-7+39208
Jackson68812720.54641-7+2688
Hosford52810940.48551+4+12528
Roseway Heights4157900.53398-4-8415
6-8 schools off by more than 15% and likely why (hypotheses from program/transfer patterns - not verified with PPS transfer data)
  • George (+62%): Most N Portland 6-8 kids attend K-8s (Astor, Cesar Chavez) or Spanish DLI; neighborhood 6-8 small.
  • Cesar Chavez (+58%): 2/3 of the school is Spanish DLI; neighborhood program is only ~88 K-5 kids.
  • Sunnyside (-57%): Environmental focus lottery draws from outside the area (capture ~0.9-1.2).
  • Bridger (-55%): Creative Science focus lottery draws students from outside the area (capture >100%).
  • Harrison Park (+49%): Recently converted from K-8; many in-area 6-8 kids in Kellogg DLI, Bridger K-8, da Vinci/Winterhaven, charters.
  • Laurelhurst (-44%): Very high neighborhood capture (affluent, popular K-8); few DLI/private drains measured.
  • Faubion (-40%): K-8 with high in-area capture plus transfers in (new building).
  • Astor (-33%): K-8 with high capture; area is small relative to its draw.
  • Tubman (+29%): Low capture; transfers out (da Vinci, Winterhaven, charters, Vernon/Faubion K-8 choices).
  • Beaumont (+26%): Spanish DLI not counted; da Vinci draws heavily from NE.
  • Sellwood (-26%): High capture, transfers in.
  • West Sylvan (+24%): Spanish DLI not counted; private-school share in West Hills.
  • Beverly Cleary (-23%): No specific explanation found; within the spread of capture rates.
  • Lane (+20%): Russian DLI small; transfers out.
  • Vernon (-16%): No specific explanation found; within the spread of capture rates.

9-12 (7 units: Jefferson's dual-assignment zones are pooled with the partner school because 2025-26 students could choose either)

schoolactual nbhd 2025-26Census rawcaptureuniform-rate prederr %LOO-cluster err %final calibratedflag
Grant196624720.801465-26n/a1966>15%
Roosevelt123824990.491481+20n/a1238>15%
Cleveland133625840.521531+15n/a1336
McDaniel138925470.551509+9n/a1389
Ida B. Wells157424490.641451-8n/a1574
Franklin157828540.551691+7n/a1578
Lincoln146924020.611423-3n/a1469
9-12 flags (likely causes, not verified)
  • Grant (-26%): Transfers in and the Jefferson dual-assignment zones mostly choose Grant.
  • Roosevelt (+20%): Transfers out (Benson, charters) and to Jefferson.

Walk and bike routing

Source: build/routing/README.md

Show the full document: build/routing/README.md

Files

  • school_points.csv: 86 CCD 2024 PPS schools (name, ncessch, level, lat, lon, grades_ccd, charter, snap distances). Includes charters (Emerson, Kairos, Le Monde, Arthur Academy, Portland Village), alternative/focus schools, MLC; filter by charter/level as needed. CCD has no 2025 file yet; 2024 is the latest. Closed or merged schools not in 2024 are absent.
  • walk_miles.parquet, bike_miles.parquet: long format, ALL pairs (9,295 blocks x 86 schools = 799,370 rows). Columns: block_idx (index in BL), geoid, school_idx (row in school_points.csv), ncessch, <mode>_miles, <mode>_seconds. Pivot: df.pivot(index='block_idx', columns='school_idx', values='walk_miles').
  • validation.md, validation_pairs.csv, build_matrices.py, validate.py, run_build.sh.
  • foot/, bike/: built OSRM graphs (MLD). osm/portland.osm.pbf: extract (lon -123.00..-122.40, lat 45.36..45.75).

Runtime: Docker via Colima (no Docker Desktop installed).

colima start --cpu 4 --memory 4 --disk 20
cd build/routing
docker run -d --name osrm-foot --restart unless-stopped -p 5001:5000 -v "$PWD/foot:/data" osrm/osrm-backend osrm-routed --algorithm mld --max-table-size 100000 /data/map.osrm
docker run -d --name osrm-bike --restart unless-stopped -p 5002:5000 -v "$PWD/bike:/data" osrm/osrm-backend osrm-routed --algorithm mld --max-table-size 100000 /data/map.osrm

If containers already exist: docker start osrm-foot osrm-bike. Stop: docker stop osrm-foot osrm-bike; colima stop.

Ports: foot = 5001, bicycle = 5002 (lon,lat order).

curl "localhost:5001/route/v1/foot/-122.6365,45.5171;-122.6514,45.5058?overview=false"
curl "localhost:5002/table/v1/bicycle/LON,LAT;LON,LAT?annotations=duration,distance"

Table distances are metres (divide by 1609.344 for miles).

Rebuild graphs: copy osm/portland.osm.pbf to foot/map.osm.pbf and bike/map.osm.pbf, then bash run_build.sh foot foot and bash run_build.sh bicycle bike.

Routing validation

Source: build/routing/validation.md

Show the full document: build/routing/validation.md

Router: OSRM MLD, foot and bicycle profiles, Geofabrik Oregon extract (2026-10-11) clipped to lon -123.00..-122.40, lat 45.36..45.75. Walk speed is the OSRM default (5 km/h).

Walk vs existing BL[i].w (public OSRM foot router)

Compared every (block, elementary) pair in BL[i].w: 65,065 pairs, 53 schools, all matched to a CCD point within 300 m.

MetricValue
Pearson r0.998
Median abs diff0.022 mi
Mean abs diff0.046 mi
95th percentile abs diff0.169 mi
99th percentile abs diff0.310 mi
Median signed diff (new - old)-0.018 mi (ours slightly shorter; ratio 0.989)
Pairs differing by > 0.25 mi1,220 (1.9%); > 0.5 mi: 148

Full pair list: validation_pairs.csv.

Outliers
  • Block 3813 (410510043001102, Linnton/Forest Park edge, -122.7336, 45.5516) and block 5262 (410510043001107): old values 2.0-3.3 mi to Beach/Astor/Cesar Chavez; ours 6-8 mi. Our route goes via Hwy 30 / St. Johns Bridge (the only real river/rail crossing). The old value is about the straight-line distance, so the public router likely snapped to a path or the wrong side of the rail/river. Ours is the defensible one.
  • Block 3668 (410510072023043, Columbia Slough / Smith-Bybee, -122.7034, 45.6035): old 1.9-3.1 mi to Astor/James John/Sitton/Rosa Parks, ours 4.9-6.6 mi. Route goes around the slough and rail yards.
  • Block 2813 (410510043001086, -122.7616, 45.5702, Forest Park): ours is 1.2-1.4 mi SHORTER than old (e.g. Astor 5.2 vs 6.5). Likely uses Forest Park trails (Leif Erikson / firelanes) that the old router either lacked or snapped differently. Population there is near zero.
  • Blocks 9203, 9159, 9056, 6345: shorter by about 1 mi to several schools; scattered, single-block differences, probably snapping/path differences.
  • An earlier build clipped at lon -122.90 produced 7 mi errors for 9 blocks west of that line (Skyline area); the final extract is widened to -123.00 and those are gone.

Hard-edge spot checks (foot router)

Five north-of-I-84 blocks routed to schools south of the freeway (I84 line from pps-model.json):

BlockToRoute miStraight miI-84 crossing at
4535Abernethy2.462.18NE 28th Ave
4576Buckman1.841.63NE Sandy Blvd
6498Glencoe2.231.66NE Campesinos Blvd, NE 47th Ave, Banfield Expressway Path (the polyline is approximate; all are real overpasses/path)
7736Grout3.432.93NE 21st Ave
357Sunnyside1.891.39NE 53rd Ave

All crossings are on named bridges/overpasses. Willamette: Buckman to Chapman uses Burnside Bridge, Abernethy to Chapman uses Hawthorne Bridge, Woodstock to Ainsworth uses Ross Island Bridge; Forest Park to Astor uses St. Johns Bridge. Rail lines and freeways are barriers in OSM because only mapped crossings connect; the detour ratios above (1.1-1.35x) are consistent with that. Rail was not exhaustively audited.

Other checks

  • No null pairs in either matrix (799,370 pairs each); every block routes to every school.
  • Bike/walk median distance ratio 1.02 (bike can use roads walkers cannot and vice versa).
  • School snap distances (school point to nearest routable way): median 30 m, max 70 m (Benson); stored as walk_snap_m / bike_snap_m in school_points.csv. Snapped to the street network, not building entrances.
  • Block centroid snap is not stored; centroids inside parks or industrial areas may snap a few hundred metres.

Size targets and scenario facts

Source: build/research/targets.md

Show the full document: build/research/targets.md

Compiled 2026-10-11. Machine-readable twin: targets.json. Source extracts (text pulled from the PDFs, so quotes can be re-checked offline) are in sources/.

How to read this. [PPS] means a primary PPS document (board deck, memo, resolution, scenario PDF, map, guideline, or the PSU forecast PPS publishes). [STATE] means Oregon statute or rule. [3P] means third-party (news, ppsdata.info/PPS Data Explorer). [DEFAULT] means no source was found and this is a proposed, clearly labeled assumption.

A key fact runs through everything below: PPS evaluates every threshold on 2031-32 projected enrollment, not today's. The scenario PDFs say, "All figures are projections for the 2031–32 school year unless noted." [PPS, scenarios overview, Oct 4 2026]. The solver should size schools against the PSU 2031-32 forecast, then check today's numbers too.


1. Size targets by level

The one official table

Every scenario PDF prints the same "Sustainability thresholds" strip:

"SUSTAINABILITY THRESHOLDS · K–5: 360 students · K–8 and middle school: 500 students · High school: 1,100 students" Source: [PPS] Scenario comparison PDF, https://drive.google.com/file/d/1ueJVC-Jo6MRKw56Jedihc6YbVdBlSB2z/view (linked from https://www.pps.net/about/portland-public-schools-information/rightsize/scenarios), and the four regional PDFs.

PPS states where the numbers come from:

"We used the threshold of 360 students for elementaries and 500 students for middle schools as guided by the prototype school description in the Quality Education Model. We applied the same number for K-8s and used the 1100 students threshold we developed during the sunsetting of Jefferson dual assignment process." Source: [PPS] Board memo, "Rightsizing Update: Equity Audit Evaluation," Aug 4 2026, https://meetings.boardbook.org/Documents/FileViewerOrPublic/915?file=3997426

Where the 360 comes from: the state's Quality Education Model prototype school, not a PPS staffing model. The QEM prototypes are "Elementary (360 students), Middle (500 students), and High (1,000 students)" [STATE, Oregon Legislature committee document, https://apps.oregonlegislature.gov/liz/2023R1/Downloads/CommitteeMeetingDocument/274502]. PPS kept 360 and 500 but raised the high school figure to 1,100.

These are floors ("schools above the sustainability threshold"). PPS publishes no upper bound at any level. The only ceiling in PPS's own framework is building functional capacity (see 1.3).

1.1 K-5
ItemValueSource
Floor360[PPS] threshold strip; Aug 4 memo (QEM prototype)
Upper boundNone stated by PPS.Searched the scenario PDFs, Sept 1/15 decks, Res. 7307, and the FAQ
Building ceilingFunctional capacity at a 100% utilization rate (K-5 and K-8)[PPS] LRFP 2021 (see 1.3)
Range KPITracked but with no target: "Range of enrollment (largest - smallest) by grade level". K5 = "560 -160 =400" actual 2025-26, "557 -168 = 389" projected 2031-32[PPS] Sept 15 2026 deck, slide 16, https://meetings.boardbook.org/Documents/FileViewerOrPublic/915?file=14430171
Solvermin 360; max = min(functional capacity, 600 [DEFAULT, carried from our earlier model])—

Today's largest K-5 is 560 (Ainsworth), so 600 doesn't bind on any real school. Keep it as a sanity cap.

1.2 K-8 (what remains)
  • Threshold: 500, the same as middle school. PPS: "We applied the same number for K-8s" [PPS, Aug 4 memo].
  • Both scenarios convert seven K-8s to K-5: Beverly Cleary, Laurelhurst, Sunnyside, Bridger Creative Science, César Chávez, Faubion and Vernon. The grade-level changes in the PDFs read: "Beverly Cleary 6–8 to Beaumont MS · Laurelhurst 6–8 to Mt. Tabor MS · Bridger Creative Science 6–8 to Harrison Park MS · Sunnyside Environmental 6–8 to Hosford MS · Faubion 6–8 to Ockley Green MS · Vernon 6–8 to Harriet Tubman MS · Chavez 6-8 to George · MLC becomes K-8" [PPS, scenarios overview]. OPB: "turning seven K-8 schools into K-5 schools... Several current K-8s are not listed as changing, including Astor, Skyline and Winterhaven." [3P, OPB Oct 6 2026, https://www.opb.org/article/2026/10/05/portland-public-schools-closures-rightsizing/]
  • K-8s left after A or B, labeled as on the Scenario A 6-8 map: Astor K-8 Neighborhood, Skyline K-8 Neighborhood, Winterhaven K-8 Focus/Option, MLC & Odyssey K-8 Focus/Option (MLC site), plus ACCESS 2-8 Focus/Option [PPS, "Grade 6-8 Attendance Areas, School Year 2027-28, Scenario A", ArcGIS export dated 10/5/2026, PPS BoardBook PDF "Scenario A - Attendance Boundaries 6-8.pdf"].
  • PSU 2031-32 forecast: Astor 418, Skyline 177, Winterhaven 310 [PPS/PSU forecast, Table 5.5, https://resources.finalsite.net/images/v1785171463/ppsnet/ejdr22voeddvux8qwlob/PPS_Forecast_2026_27.pdf]. All of them sit below 500, and PPS leaves them alone. A district-like run must exempt Astor and Skyline from the 500 floor, or the model has no feasible solution.
1.3 6-8 (middle)
ItemValueSource
Floor500[PPS] threshold strip; Aug 4 memo
Status quo 2031-32"6-8 Schools with 500 + Students: 1 in 8"; only 13% of 6-8 schools at 500+, with 7 of 15 below 400[PPS] Sept 1 2026 deck, slide 10, https://meetings.boardbook.org/Documents/FileViewerOrPublic/915?file=14357211; Aug 4 deck, slide 17
Magnitude slide"6-8 with Enrollment 500+ in 2031-32": 15 schools → 2 at 500+; 14 schools (1 closure) → 3; 13 (2 closures) → 4; 12 (3 closures) → 8[PPS] Sept 1 deck, slide 12
Utilization definition"a school's enrollment divided by its functional capacity"[3P] Willamette Week (the reporter's description, not a PPS quote), Apr 15 2026, https://www.wweek.com/news/schools/2026/04/15/pps-introduces-another-metric-to-inform-school-closures/
Functional capacity methodClassrooms 500–800 sq ft = 24 students, 800–1000 = 27, >1000 = 30 → gross capacity; minus set-asides (learning center, SPED focus room, 1-2 art/music rooms, early childhood, leased rooms); × utilization rate. "the utilization rate for these configurations [K-5, K-8] is one-hundred percent." For middle and high school, "the utilization rate for these configurations is 85%." Rates are "broadly reduced for Title I schools (five-percent) and for TSI/ CSI designations (again, five-percent)." FUNCTIONAL CAPACITY ⁄ ENROLLMENT = SCHOOL UTILIZATION (sic: the arithmetic is enrollment ÷ capacity)[PPS] Long-Range Facility Plan 2021, Vol 1, pp. 50-51, https://www.pps.net/fs/resource-manager/view/84245cbd-4298-4803-8ba9-d26fb13a9c7a
"Efficiently utilized"Named as a KPI: "1. Percent of efficiently utilized schools" (Sept 15 deck, slide 17). Defined by PPS staff the same evening as 70–100% of functional capacity (see next row).[PPS] Sept 15 deck, slide 17; Sept 15 2026 meeting video
Utilization band 70–100%A stated PPS aim (corrected 2026-10-12; an earlier version of this file said no PPS source existed). [PPS] Family Guide glossary, p. 2, "Space use goal": "The district aims to use 70%-100% of a school's available room for students. A 'No' can mean the school is below or above that range." (every guide, e.g. build/pps-texts/family-guide-rigler.md lines 82-84); PPS staff, Sept 15 2026 board meeting, https://youtu.be/uAf7l-ChjFo?t=15369 (04:16:09): "we look anywhere from 70 to 100% being efficiently utilized" (checked against the video). PPS gives no research basis for the band; none was found in its board records. WW: "higher utilization rates aren't ideal because they indicate that all instructional spaces are occupied to capacity all day."[PPS]; [3P] WW Apr 15 2026
Solvermin 500 students; utilization ≤ 100% of functional capacity (hard); utilization ≥ 70%: PPS aim (Family Guide p. 2 "Space use goal"; Sept 15 2026 meeting); reported, not a hard constraint[PPS]

Because the 85% rate is already built into functional capacity, 100% of functional capacity is a real operating ceiling, not a theoretical one. The model keeps the 70% floor as a reported metric; it would become a rule only if the 500 floor doesn't already cover it. For a 700-seat building, 500 students is 71%, so the two floors nearly coincide.

Middle-school functional capacities, LRFP 2021 [PPS]: Mt. Tabor 682 · Kellogg 803 · Hosford 696 · Jackson 908 · Sellwood 683 · Roseway Heights 803 · West Sylvan 987 · Ockley Green 689 · Gray 622 · Beaumont 701 · da Vinci 714 · Tubman 732 · George 617 · Lane (now Brentwood) 770. Harrison Park was a K-8 in 2021 and has no MS row. [3P] PPS Data Explorer lists 1006 (2021) and 890 (2025 PPS utilization-model value). PPS's 2025 utilization-model workbook came out through a records request (ppsdata.info, [3P]). Its values differ slightly (Kellogg 732, Jackson 931), so Phase 1a should pick one source and say which.

Middle-school 2031-32 status-quo forecast [PPS/PSU Table 5.5]: Beaumont 418 · George 390 · Gray 368 · Tubman 374 · Harrison Park 417 · Hosford 374 · Jackson 515 · Kellogg 471 · Lane/Brentwood 357 · Mt. Tabor 354 · Ockley Green 436 · Roseway Heights 498 · Sellwood 350 · West Sylvan 620 · da Vinci 419. The "Middle Schools Subtotal" of 6,361 includes da Vinci.

Back-of-envelope feasibility (ours): 5,942 neighborhood MS students in 2031-32, plus about 1/3 of the 3,251 K-8 students in the seven converting K-8s (≈1,080), comes to ≈7,020 sixth-to-eighth graders for the 13 neighborhood middle schools left after A. That averages ≈540, just over 13 × 500 = 6,500. The 500 floor is feasible on average but tight, and 13 schools must all clear it. Close 2 focus options adds da Vinci's 419 and Winterhaven's ≈100 sixth-to-eighth graders, which lifts the average to ≈580.

1.4 9-12 (comprehensive high schools)
ItemValueSource
Floor1,100[PPS] threshold strip
Why 1,100Set in the Jefferson dual-assignment sunset work ("the 1100 students threshold we developed during the sunsetting of Jefferson dual assignment process")[PPS] Aug 4 memo
Rationale quote"ensuring that the student body of each high school stays above 1,100 by 2030–31, which district officials say is necessary to justify comprehensive programming."[3P] WW Dec 10 2025, https://www.wweek.com/news/schools/2025/12/10/enrollment-balancing-in-north-and-northeast-portland-shows-the-consequences-of-overbuilding-high-school-capacity/
HS KPIs from "Jefferson is Rising""% of High Schools in each scenario with enroll above 1100 students (target = 100%)"; "HS Enrollment Range (target = <350)"; "% MS feeders moving to the same HS (target = 100%)"[PPS] Sept 15 2026 deck, slide 21 (image saved as sources/jefferson_is_rising_kpis_slide21.png)
Capacities on that slideJefferson 1590 (current) → 1773 (modernized), Grant 1935, McDaniel 1735, Roosevelt 1404same slide
LRFP 2021 HS functional capacitiesGrant 1,686 · Franklin 1,744 · Roosevelt 1,320 · Wells-Barnett 1,872 · Cleveland 1,859 · Lincoln 1,867 · McDaniel 1,739 · Benson 2,203 · Jefferson 1,817[PPS] LRFP 2021, p. 122
Status quo"9-12 Schools with 1100 or more students": 100% by 2031-32. Range 1,683 (2025-26) → 375 (2031-32)[PPS] Aug 4 deck, slide 17; Sept 15 deck, slide 16: "High Schools 2074 -391 =1683 / 1492 -1117 =375"
2031-32 forecastCleveland 1,318 · Franklin 1,492 · Grant 1,487 · Ida B. Wells 1,457 · Jefferson 1,183 · McDaniel 1,261 · Lincoln 1,411 · Roosevelt 1,117 · (Benson 1,213, a focus school)[PPS/PSU] Table 5.5
Upper boundNone stated. Building capacity is the ceiling. The <350 range KPI acts as an implicit cap: max ≤ min + 350.—
Solvermin 1,100 (hard); ≤ functional capacity (hard; use the slide's 2025 figures where given, LRFP otherwise); range ≤ 350 soft (status quo is already 375 in 2031-32, so a hard limit risks infeasibility)—

The Jefferson dual-assignment sunset is already decided (board vote Jan 2026, effective with 9th graders in 2027-28). PPS treats it as current state in its feeder chart: "Reflects the sunsetting of dual assignment, effective 2027-28 school year" [PPS, High School Feeder Patterns PDF, https://resources.finalsite.net/images/v1790894228/ppsnet/f2u6fbkysoabacyo484j/PPS_High_School_Feeder_Patterns_Eng.pdf]. Irvington-area students go to Grant; Peninsula and Beach Spanish DLI go to Roosevelt.


2. Dual Language Immersion (DLI)

2.1 What PPS says about strand size

No PPS minimum strand size (classes per grade or students per grade) was found. We searched the DLI department page, the scenario PDFs, the board decks (Mar 10, Mar 31, Sept 1, Sept 15), the June 2026 focus/alternative overview, the FAQ, and the SEGC equity audit (157 + 130 pp.). What PPS does say:

What Scenario A actually does is a clear structural rule. Every language ends with exactly one elementary host and one middle-school host per high-school pathway:

Language / HS pathwayToday: K-5 hosts → 6-8 host(s)Scenario AScenario B
Spanish / LincolnAinsworth → West Sylvanunchangedunchanged
Spanish / RooseveltBeach, James John, Sitton, Chávez K-8 → Ockley Green, George, ChávezChávez (K-5) → Georgesame as A
Spanish / McDanielRigler, Scott → Beaumont, Roseway HeightsRigler → Roseway Heightssame as A
Spanish / FranklinAtkinson, Lent → KelloggLent → Kelloggsame as A
Mandarin / JeffersonMLK Jr. → TubmanBoise-Eliot/Humboldt → Tubmansame as A
Mandarin / ClevelandWoodstock, Clark → Harrison ParkWoodstock → Harrison Parksame as A
Japanese / GrantRichmond → Mt. Taborunchangedunchanged
Russian / FranklinKelly → Lane (Brentwood)unchangedunchanged
Vietnamese / McDanielRose City Park → Roseway HeightsVestal → Roseway Heightsstays at Rose City Park

Sources: today's pathways come from [PPS] High School Feeder Patterns PDF p. 9 and the TLE "Alternative & Focus School Overview" (June 2026, slides 7-9, https://meetings.boardbook.org/Documents/FileViewerOrPublic/915?file=3997345). Program moves are quoted from [PPS] scenario PDFs: "Spanish: Beach, James John, and Sitton to Cesar Chavez · Atkinson to Lent · Scott to Rigler · Beaumont MS to Roseway Heights MS · Chavez 6–8 and Ockley Green MS to George MS · Vietnamese: Rose City Park to Vestal · Mandarin: Clark to Woodstock · MLK Jr. to Boise-Eliot/Humboldt". B drops the Vietnamese move. Roseway Heights hosting Spanish plus Vietnamese and Tubman hosting Mandarin also show on the A 6-8 map labels ("Roseway Heights Middle School Spanish Immersion, Vietnamese Immersion"; "Harriet Tubman Middle School Mandarin Immersion"; "George Middle School Spanish Immersion"; "Kellogg Middle School Spanish Immersion"; "Mt Tabor Middle School Japanese Immersion"; "Brentwood Middle School Russian Immersion"; "Harrison Park Middle School Mandarin Immersion"; "West Sylvan Middle School Spanish Immersion").

Spanish high-school assignment is regional by home address: "Upon completion of 8th grade Spanish DLI, students are assigned to a regional high school based on their home address." [PPS feeder PDF p. 9]. Lincoln+Wells → Lincoln; Roosevelt+Jefferson → Roosevelt; McDaniel+Grant → McDaniel; Franklin+Cleveland → Franklin.

2.2 Current strand sizes (PSU forecast, by program) [PPS/PSU Table 5.5]

Per-grade = program enrollment ÷ grades (6 for K-5, 3 for 6-8, 9 for Chávez K-8).

HostLang2025-26/grade2031-32/gradeA/B fate
Ainsworth ESSpa28747.829148.5stays
Rigler ES (whole-school)Spa28948.232153.5receives Scott
Lent ES (whole-school)Spa25642.727445.7receives Atkinson
Scott ESSpa22237.022337.2→ Rigler
Atkinson ESSpa17829.718330.5→ Lent
Beach ESSpa15525.812721.2closes → Chávez
Sitton ESSpa13823.011318.8→ Chávez
James John ESSpa13322.213622.7closes → Chávez
César Chávez K-8Spa30033.329532.8becomes K-5 host; 6-8 → George
MLK Jr. ESMan19332.219632.7→ Boise-Eliot/Humboldt
Woodstock ESMan19031.719432.3receives Clark
Clark ESMan9115.28714.5→ Woodstock
Richmond ES (whole-school)Jpn51285.349782.8stays
Kelly ESRus14323.814524.2stays
Rose City Park ESVie20734.521035.0A: closes → Vestal; B: stays
West Sylvan MSSpa11638.713344.3stays
Kellogg MSSpa20167.025785.7stays
George MSSpa10936.312341.0receives OG + Chávez 6-8
Beaumont MSSpa10133.714548.3→ Roseway Heights
Roseway Heights MSSpa9331.07826.0receives Beaumont
Ockley Green MSSpa6321.03411.3→ George
Roseway Heights MSVie6421.37224.0stays
Harrison Park MSMan11137.09832.7stays
Tubman MSMan4816.05217.3stays
Mt. Tabor MSJpn22274.021070.0stays
Lane/Brentwood MSRus3612.03010.0stays

Context [PPS TLE deck, June 2026, slide 13]: 2025-26 K "Lottery Slots" and "Enrollment" by language read Chinese 104/127, Japanese 89/104, Russian 25/25, Spanish 306/278, Vietnamese 36/52. The column order is ambiguous in the extract. K focus-option lotteries offer 26 seats per school (one class) [PPS 2026-27 K Lottery Results Summary], which is a useful marker for one class.

Students moved by A's DLI program moves (2031-32 PSU counts): elementary 1,275 (Beach 127, James John 136, Sitton 113, Atkinson 183, Scott 223, Clark 87, MLK 196, RCP 210); middle 179 (Beaumont 145, Ockley Green 34) plus Chávez 6-8 (≈98, estimated as 1/3 of 295). B drops RCP's 210. Some of these students move because their building closes (Beach, James John, RCP in A), not because of the program move. The Phase 4 "DLI kids moved" metric should split the two.

2.3 Proposed strand rule [DEFAULT, since PPS publishes none]

A first idea was "about 2 classes per grade" if PPS has no rule. Applied strictly, that fails almost every strand today (only Ainsworth, Rigler, Richmond, Kellogg and Mt. Tabor pass), so an option that keeps immersion strands in place would collapse into a plain redraw. The model uses two tiers instead:

  • Healthy strand (target, reported): ≥ 2 classes/grade. Elementary ≥ 44 students/grade (2 × 22) averaged over K-5. Middle ≥ 40 students/grade.
  • Viable strand (hard rule for an option that keeps some immersion strands in place): ≥ 1 full class/grade. Elementary ≥ 22 students/grade (≥ 132 K-5). Middle ≥ 20 students/grade (≥ 60 across 6-8).
  • Sole-pathway exemption: if a strand is the only host for its language on its HS pathway (Tubman Mandarin, Lane/Brentwood Russian, Kelly Russian, Roseway Vietnamese, Richmond/Mt. Tabor Japanese), it stays even if below viable. Moving it can't create continuity, and PPS keeps all of these in both scenarios.
  • Continuity (hard, all options): each K-5 strand feeds exactly one 6-8 strand of the same language, which feeds that language's high school (Spanish by home-address region). This matches today's chart and A.

Applying the viable rule to 2031-32 numbers: Clark (14.5/grade), Sitton (18.8) and Beach (21.2) fall below viable; Beach and James John close anyway. Ockley Green MS Spanish (11.3) falls below viable. In an option that keeps some strands in place, these still move to their pathway's surviving host, the same as A. Atkinson (30.5), Scott (37.2), James John (22.7, but its building closes) and RCP are viable where they are. In such an option, a strand whose building stays open stays put. A strand whose building closes moves to the nearest viable same-language host on its pathway, or travels with the neighborhood receiver if the receiver can hold it in range (e.g. James John → Sitton).


3. Focus options: Winterhaven and da Vinci

Winterhavenda Vinci Arts
GradesK-86-8
Enrollment316 (2025-26); 310 forecast 2031-32 [PPS/PSU]; TLE deck: "Winterhaven 316"429 (2025-26); 419 forecast 2031-32 [PPS/PSU]; TLE deck: "da Vinci 429"
Building / address3830 SE 14th Ave [PPS lottery-slot sheet]. Built 1930. PPS historic survey calls it "Winterhaven at Brooklyn School" [3P via search of a PPS ILS PDF]2508 NE Everett St [PPS lottery-slot sheet]. Built as Girls Polytechnic HS, later James Monroe HS, closed 1978 [3P, Wikipedia]
Formerly a neighborhood school?Probably: the old Brooklyn School. Its use as a neighborhood elementary and its closure date are unverifiedNo, not an elementary or middle neighborhood school. It was a district high school (Girls Poly/Monroe), not a K-8 attendance-area school
Functional capacity (LRFP 2021)261 (13 classrooms + 1 modular); utilization 112% (2021-22)714 (25 classrooms + 6 modular); utilization 63% (2021-22)
AdmissionLottery. 2026-27: K "Offered 26, Waitlist 70, Applications 143" [PPS K Lottery Results]; 23 sixth-grade transfer slots [PPS MS/HS lottery-slot sheet]Lottery at 6th grade: 150 sixth-grade slots, 3 seventh, 4 eighth [PPS MS/HS lottery-slot sheet, 2026-27]
Where students come from (top 5)"Hosford (45), Grout (32), Sellwood (26), Brentwood/ Lane (18), Out of District (15)""Ockley Green (60), Tubman (56), Roseway Heights (40), Hosford (36), Brentwood/Lane (35)"
Scenario A / BNo change in either. The A 6-8 map labels it "Winterhaven K-8 Focus/ Option"No change in either. The A 6-8 map labels it "da Vinci Middle School Focus/Option"
Vs. 500 threshold310 < 500, and the threshold applies to K-8s per the Aug 4 memo419 < 500

Enrollment-origin rows come from the [PPS] TLE Committee "Alternative & Focus School Overview," June 2026, slide 18.

What PPS has said about their size vs. 500: nothing specific that we found. The thresholds are stated generically ("K–8 and middle school: 500 students"). No document explains why focus options under 500 are untouched. The closest statements: Res. 7307 says "Access to choice programs will be balanced with the goal of assuring well-resourced neighborhood schools across our system" [PPS, https://meetings.boardbook.org/Documents/FileViewerOrPublic/915?file=3997273]. OPB reports that officials "heard from families and students in support of focus options, like art at Buckman and da Vinci and environmental issues at Sunnyside." The Oregonian, quoted by Families for Equity, says "The schools that were spared include Da Vinci Middle School, an arts magnet, and Winterhaven K-8, a science magnet." [3P].

Other focus-option moves in both scenarios: Buckman (arts K-5) closes. Sunnyside loses its environmental focus status and becomes a neighborhood K-5 [3P OPB: "its status as an environmental focus option school would be 'discontinued'"]. Odyssey moves to the MLC site. The MLC 9-12 program closes ("students move to their neighborhood high school. It is not counted as a school closure" [PPS]). MLC becomes K-8. Bridger loses grades 6-8.


4. Scenarios A and B at the middle and high school levels

All changes take effect "no later than the 2027-28 school year and will be completed within three years" [PPS FAQ, Oct 1 2026]. The 6-8 map is titled "School Year 2027-28". The superintendent recommends in November, and the board votes in December 2026.

4.1 Closures
  • A (14): "Beach · Buckman · Creston · Irvington · James John · Lewis · Maplewood · Marysville · Peninsula · Rose City Park · Sabin · Sellwood MS · Stephenson · Woodmere". B (11): the same minus Lewis, Rose City Park and Stephenson [PPS overview].
  • Sellwood MS is the only middle school closure in both. Receivers (KATU): "Hosford for students from the Llewellyn area and Brentwood for students from the Duniway and Lewis areas." The A 6-8 map labels the Sellwood building "Sellwood School Closed".
  • MLC 9-12 program closes (not counted as a closure). The Odyssey building (1849 SW 58th Ave) is shown "Odyssey Building Closed" on the A 6-8 map.
4.2 K-8 → K-5 conversions and middle-grade moves (identical in A and B)
From6-8 goes toHS of receiving MS
Beverly Cleary 6-8Beaumont MSGrant
Laurelhurst 6-8Mt. Tabor MSGrant for the Laurelhurst area; Mt. Tabor is otherwise Franklin, so the split continues (see 4.4)
Bridger Creative Science 6-8Harrison Park MSMcDaniel / Franklin split
Sunnyside Environmental 6-8Hosford MSCleveland
Faubion 6-8Ockley Green MSJefferson
Vernon 6-8Harriet Tubman MSJefferson
César Chávez 6-8 (Spanish)George MSRoosevelt
MLCbecomes K-8 (with Odyssey on site)—

Also: Irvington closes; its area goes to "Beverly Cleary for K–5 students and Beaumont for the area's middle school pathway" [3P KATU]. Today it goes to Tubman → Grant, so the Tubman/Grant split feeder goes away.

4.3 Middle schools with attendance-boundary changes

A and B list the same middle schools: Beaumont, Brentwood, George, Harriet Tubman, Harrison Park, Hosford, Jackson, Kellogg, Mt. Tabor, Ockley Green, Robert Gray [PPS overview]. Not listed: Roseway Heights (gains only the Beaumont Spanish program), West Sylvan, da Vinci, and Winterhaven. Jackson and Gray change in both, even though B keeps Stephenson open. Bridger is not a separate "6-8 school" after conversion.

Neighborhood middle schools after A (A 6-8 map): Beaumont, Brentwood (formerly Lane; PPS site: "Lane Middle School (Now Brentwood)"), George, Gray, Harrison Park, Hosford, Jackson, Kellogg, Mt. Tabor, Ockley Green, Roseway Heights, Tubman, West Sylvan = 13. Add the K-8 neighborhood schools Astor and Skyline, the focus schools da Vinci (6-8), Winterhaven (K-8) and MLC & Odyssey (K-8), and ACCESS (2-8, alternative).

4.4 High schools
  • HS with attendance-boundary changes, A and B alike: Cleveland, Franklin, Jefferson, Lincoln, McDaniel, Roosevelt. Grant and Ida B. Wells are not listed [PPS overview and regional PDFs]. Oddity: Lincoln gains or loses area, but its only neighbor, Wells, isn't listed. It may be the MLC HS closure or an omission; flag it for Phase 0.
  • No PPS 9-12 boundary map for either scenario was found. The A 6-8 map shades each middle-school zone by high-school cluster (legend: Cleveland, Franklin, Grant, Jefferson, Lincoln, McDaniel, Roosevelt, Wells-Barnett), so A's HS lines can be digitized from it. Visible on the map:
    • Tubman is now all Jefferson; the Irvington area moves to Beaumont/Grant.
    • Mt. Tabor's zone still includes a Grant-shaded Laurelhurst area alongside Franklin.
    • Harrison Park is McDaniel plus a Franklin-shaded southern piece.
    • Brentwood is Franklin plus a Cleveland-shaded western piece.
    • Hosford, which absorbs Sellwood's Llewellyn area, is all Cleveland.

    Split feeders therefore persist in A at Mt. Tabor, Harrison Park and Brentwood. This is my read of the shading, to confirm when digitizing.

  • Current split feeders, per PPS [Sept 15 deck, slides 18-19]: Bridlemile K5 (Gray / West Sylvan); Bridger and Sunnyside K8 (focus students return to their neighborhood HS); Atkinson (Kellogg Spanish DLI / Harrison Park non-DLI); Woodstock (Harrison Park Mandarin / Brentwood non-DLI); Beaumont MS (Grant / McDaniel Spanish DLI); Harriet Tubman MS (Grant / Jefferson); Harrison Park MS (Franklin / McDaniel / Cleveland Chinese DLI); Hosford MS (Cleveland / Franklin); Brentwood MS (Cleveland / Franklin); Mt. Tabor MS (Grant Japanese DLI / Franklin); Ockley Green MS (Jefferson / Roosevelt Spanish DLI).
4.5 Official boundary maps
MapStatus
Scenario A, Grade 6-8 Attendance Areas, SY 2027-28Have: PPS BoardBook PDF "Scenario A - Attendance Boundaries 6-8.pdf" (ArcGIS Pro export, "Rightsizing Model 2026.09.24 / Version: 10/5/2026 12:58 PM"). The text layer holds street and school labels only, no geometry; polygons have to be digitized.
Scenario A K-5, Scenario A 9-12, all Scenario B mapsNot found on pps.net. The scenarios page links only the overview and four regional PDFs. The "How Could Your School Be Impacted?" page loads per-school data dynamically, and it couldn't be fetched as static files.
Current HS feeder chartPPS_High_School_Feeder_Patterns_Eng.pdf (9 pp., includes the DLI feeder chart)
4.6 Stated principles relevant to lines
  • Board Policy 4.10.045-P (Student Assignment), as quoted to the board on Mar 31 2026: "A. A feeder pattern that allows as many students as possible to continue together from one school level to the next · B. Student body demographics · C. Compact boundaries that promote safer routes to schools and a sense of community as well as recognize and address natural and human-made barriers · D. Optimal use of existing facilities · E. Program and enrollment stability in the surrounding schools · F. Limiting the impact of boundary changes to the smallest number of students possible". The policy calls these a "non-prioritized list" that "may conflict with one another" [PPS, Mar 31 2026 work session book, https://meetings.boardbook.org/Documents/FileViewerOrPublic/915?file=3988980].
  • Res. 7307 Guiding Principles (May 26 2026): "...maintain a sustainable portfolio of school facilities... and prioritize walkability and safe routes to schools." Workplan: "minimizes disruption for students, families, and staff, including an assessment of cohort cohesion" [PPS].
  • FAQ: "If boundaries need to change, PPS will look at where students live, school size and space, programs, transportation, and how students move through schools from elementary to high school." [PPS FAQ, Sept 15 2026]
  • KPIs (Sept 15 deck, slide 17): "1. Percent of efficiently utilized schools · 2. Percent of students living within 1.0 and 1.5 miles of school · 3. Number of schools with split feeders · 4. Percent of middle school feeders moving to the same high school". Balance and impact KPIs (slide 20): "Percent of focal students who will experience the change · Number of Title I and CSI/TSI schools impacted · Number of students moving to a new school or site". Slide 14 also lists "Range of enrollment (largest - smallest) by grade level".
  • OPB: "She said a school's walkability was also a consideration."
  • Equity audit lesson: "Families also described how new feeder patterns disrupted peer continuity" (SEGC school-by-school volume).

5. Transportation eligibility

RuleTextSource
State mandate"A school district is required to provide transportation for elementary school students who reside more than one mile from school and for secondary school students who reside more than 1.5 miles from school."[STATE] ORS 327.043(2), https://www.oregonlegislature.gov/bills_laws/ors/ors327.html
State reimbursement"Approved transportation costs"... "(A) Elementary school students who live at least one mile from school; (B) Secondary school students who live at least 1.5 miles from school"[STATE] ORS 327.013(2)(a)
Who is "elementary""pupils attending a school offering only an elementary curriculum, any combination of grades K through 8"; students at a board-designated "junior high school or middle school may be considered secondary students"[STATE] OAR 581-023-0040(1)(a)-(b), https://oregon.public.law/rules/oar_581-023-0040 (an ODE note says the rule was amended Feb 19 2026; the amended text wasn't retrieved)
How distance is measured (state)"measured over the shortest practicable route on maintained public roadways... or over existing pedestrian facilities"[STATE] OAR 581-023-0040(1)(e)
PPS K-5"For students who live more than one mile from the elementary school they attend within their school attendance boundary."[PPS] Service Guidelines – Student Transportation, rev. 08/07/2024, §B.1, https://resources.finalsite.net/images/v1751562292/ppsnet/thzskadliar1v7qds4yc/Service_Guidelines_Student_Transportation_2024.pdf
PPS 6-8"For students who live more than one and one-half miles from the middle school they attend which is within their attendance boundary." §D.1: "within one mile... (Pre-kindergarten – 5) or within 1.5 miles for grades 6 – 8"same
PPS 9-12"High school students who reside more than one and 1.5 miles from the school they attend which is within their attendance boundary and one mile or more from TriMet, private, or other public services." §D.1: high schoolers within 1.5 mi, or within one mile of a TriMet stop, get yellow-bus service only for hazardous walking conditionssame
PPS distance method"Measurement of the most direct combination of roads, streets, highways, and public paths... from the street immediately in front of the school to the street in front of the student residence."same §B.3
PPS DLINative-speaker DLI students at their assigned school: >1 mi (ES) / >1.5 mi (MS). Non-native DLI students ride only as "hitchers" on existing routessame §B.5
High schoolers on TriMet"if you're a Portland Public School (PPS) District student in grades 9-12, you can use your school ID card to get rides on TriMet, Portland Streetcar and WES Commuter Rail during the school year."[3P] TriMet blog, Aug 20 2025, https://blog.trimet.org/2025/08/20/trimet-101-how-to-get-around-as-a-student/

For the busing-cost metric: K-5 is eligible at walk distance > 1.0 mi. 6-8 is eligible at > 1.5 mi, and that includes 6-8 students in K-8 buildings, per PPS §D.1's grade-based wording. That's stricter than OAR's school-type definition; flag it. 9-12 gets yellow bus only if > 1.5 mi and > 1.0 mi from a TriMet stop. Every other high schooler gets transit via school ID, so high-school "cost" is transit time, not bus miles.


6. Split feeders, walkability, and boundary principles: summary

PPS treats split feeders as a measured negative. Its KPIs are "Number of schools with split feeders" and "% MS feeders moving to the same HS (target = 100%)" (Jefferson KPI). Policy 4.10.045 factor A prefers "as many students as possible" continuing together. Walkability is a guiding principle (Res. 7307) and a KPI (% within 1.0 and 1.5 mi). Even so, PPS's Scenario A keeps several split feeders, apparently because DLI pathways and capacity win out. "No single factor will determine whether a school is changed or closed" [PPS FAQ].


Spec for the solver

Evaluate sizes on PSU 2031-32 projected enrollment (primary); report 2025-26 as a check. Robustness check: −9% (per PLAN).

Hard constraints per level
LevelMinMaxNotes
K-5 (neighborhood, incl. receivers)360min(functional capacity @100%, 600)600 is [DEFAULT]
K-8 (Astor, Skyline)exempt in district-like runs (PPS leaves them < 500); otherwise 500functional capacityReport the shortfall; don't force it
6-8 neighborhood MS (13 after A)500functional capacity @85% rate (i.e. utilization ≤ 100%)utilization 70–100% is a stated PPS aim [PPS, Family Guide p. 2]; ≥ 70% reported, hard only if requested
9-12 comprehensive (Cleveland, Franklin, Grant, Ida B. Wells, Jefferson, Lincoln, McDaniel, Roosevelt)1,100functional capacity: Jefferson 1,773 (modernized; 1,590 now), Grant 1,935, McDaniel 1,735, Roosevelt 1,404 (2025 slide); others LRFP 2021 (Cleveland 1,859, Franklin 1,744, Lincoln 1,867*, Wells 1,872)range (max − min) ≤ 350 as soft (status quo is 375). *Lincoln's new building capacity is unconfirmed
Focus/alt (da Vinci, Winterhaven, MLC/Odyssey, ACCESS, Benson)fixed enrollment, no boundary—Close 2 focus options removes da Vinci and Winterhaven and returns their students to the neighborhood

Feeder rules: middle zones are unions of whole K-5 zones, and high zones are unions of whole middle zones. A split is allowed only when it's needed for feasibility, and every split gets reported. PPS's own A keeps splits at Mt. Tabor, Harrison Park and Brentwood, so the district-like option must allow those three.

DLI rule
  1. Continuity (all options): for each language and HS pathway there's exactly one K-5 host and one 6-8 host. Spanish HS assignment is by home-address region (Lincoln+Wells → Lincoln; Roosevelt+Jefferson → Roosevelt; McDaniel+Grant → McDaniel; Franklin+Cleveland → Franklin). Mandarin goes MLK/BEH → Tubman → Jefferson, and Woodstock → Harrison Park → Cleveland. Japanese goes Richmond → Mt. Tabor → Grant; Russian Kelly → Brentwood → Franklin; Vietnamese RCP or Vestal → Roseway Heights → McDaniel.
  2. Viable strand [DEFAULT]: ≥ 22 students/grade averaged over K-5 (≥ 132 total), and ≥ 20/grade in 6-8 (≥ 60). Healthy: ≥ 44/grade K-5 and ≥ 40/grade 6-8 (reported).
  3. Sole-pathway exemption: a strand that's the only host on its pathway stays regardless of size.
  4. DLI students count toward their host building's size and capacity. Whole-school DLI buildings (Rigler, Lent, Richmond) have no neighborhood zone.
  5. Options that keep some immersion strands in place: a strand stays in its 2025-26 building if the building stays open and the strand is viable. Otherwise it moves to the pathway's surviving or viable host, and the solver uses A's destination unless a closer viable host exists.
Scenario-A facts the "district-like" option must replicate
  1. Closures (14): Beach, Buckman, Creston, Irvington, James John, Lewis, Maplewood, Marysville, Peninsula, Rose City Park, Sabin, Sellwood MS, Stephenson, Woodmere. The MLC 9-12 program closes too (its students go to their neighborhood HS), and the Odyssey building closes.
  2. K-8 → K-5: Beverly Cleary → Beaumont; Laurelhurst → Mt. Tabor; Bridger → Harrison Park; Sunnyside → Hosford (Sunnyside also loses its focus status); Faubion → Ockley Green; Vernon → Tubman; Chávez → George. MLC becomes K-8 with Odyssey.
  3. Remaining K-8s unchanged: Astor and Skyline (neighborhood), Winterhaven (focus).
  4. Sellwood MS split: the Llewellyn area goes to Hosford; the Duniway and Lewis areas go to Brentwood.
  5. Irvington area: K-5 goes to Beverly Cleary; 6-8 goes to Beaumont (Grant).
  6. DLI moves: Spanish Beach, James John and Sitton → Chávez; Chávez 6-8 and Ockley Green Spanish → George; Atkinson → Lent; Scott → Rigler; Beaumont MS Spanish → Roseway Heights; Vietnamese RCP → Vestal; Mandarin Clark → Woodstock; Mandarin MLK → Boise-Eliot/Humboldt. Ainsworth/West Sylvan, Richmond/Mt. Tabor, Kelly/Brentwood, Woodstock/Harrison Park and Tubman are unchanged.
  7. Other program moves: Creston DHH → Glencoe; Odyssey → MLC site; Buckman's focus program ends with the closure.
  8. K-5 receivers (KATU): Maplewood → Hayhurst + Rieke; Stephenson → Markham + Capitol Hill; Rose City Park → Scott (neighborhood); Buckman → Abernethy + Sunnyside; Creston → Atkinson; Marysville → Arleta; Woodmere → Whitman; Lewis → Duniway; Beach → Chief Joseph; James John → Sitton; Peninsula → Rosa Parks; Sabin → MLK Jr.
  9. Boundary-change lists, which bound which schools may change lines: MS: Beaumont, Brentwood, George, Tubman, Harrison Park, Hosford, Jackson, Kellogg, Mt. Tabor, Ockley Green, Gray. HS: Cleveland, Franklin, Jefferson, Lincoln, McDaniel, Roosevelt. Roseway Heights, West Sylvan, Grant and Ida B. Wells keep their lines in A.
  10. Middle-school set after A: the 13 neighborhood MS listed in 4.3 plus focus/alternative schools.
  11. Jefferson dual-assignment sunset as baseline: Peninsula-area and Beach-Spanish → Roosevelt; Irvington → Grant; everything else in the old dual zone → Jefferson.

Scenario B is the same, except: Lewis, Rose City Park and Stephenson stay open. There's no Vietnamese move. The K-5 boundary-change list drops Capitol Hill, Duniway, Llewellyn, Markham and Scott and adds Lewis. MS and HS change lists are unchanged.


Unresolved gaps

  1. No PPS DLI minimum strand size. The rule above is a labeled default derived from A's structure and PSU program counts.
  2. The 70–100% utilization band is a stated PPS aim (corrected 2026-10-12). Family Guide glossary p. 2, "Space use goal": "The district aims to use 70%-100% of a school's available room for students." PPS staff defined "efficiently used schools" the same way at the Sept 15, 2026 board meeting (https://youtu.be/uAf7l-ChjFo?t=15369). It applies to every school level, not just middle schools. PPS gives no research basis for it. 100% of functional capacity (85% rate for middle and high schools) is the ceiling; 70% is reported as PPS's floor for efficient use.
  3. No HS upper bound beyond capacity and the <350 range KPI. Post-modernization capacities are published only for Jefferson, Grant, McDaniel and Roosevelt (2025 slide). Lincoln (new building), Cleveland and Wells use LRFP 2021 values.
  4. Per-school Scenario A and B projected enrollments aren't published in the PDFs. The "How Could Your School Be Impacted?" tool is dynamic and needs a browser (/browse) to scrape.
  5. Missing maps: no Scenario A K-5 or 9-12 maps and no Scenario B maps were found. Only the A 6-8 map exists, and A's HS clusters can be read from its shading.
  6. The Lincoln-without-Wells HS boundary-change listing is unexplained.
  7. Winterhaven building history: that it was once Brooklyn neighborhood school is likely but unverified.
  8. Chávez K-8's Spanish 6-8 count isn't split out in the PSU table; ≈1/3 of 295 is my estimate.
  9. OAR 581-023-0040 was amended Feb 19 2026 and the new text wasn't retrieved. ORS 327.043's 1 / 1.5 mile mandate is unaffected.
  10. The TLE deck's DLI K "slots vs enrollment" column order is ambiguous in the text extract.

How our model compares with PPS's own projections

Source: build/solver/out_v2/CALIBRATION_public.md, build/solver/out_v2/CALIBRATION.md

PPS published projected enrollment for every school under its plans, for 2027-28 to 2031-32. They appear in the "How many students are expected?" table on page 4 of each school's Family Guide (dated October 8, 2026). PPS's "No changes" row is the Portland State University forecast (PSU Population Research Center, July 24, 2026, Table 5.5).

Our model estimates students block by block, so it can score any set of lines, including plans PPS hasn't drawn. To check it, the model was run on PPS's own lines (No changes, Scenario A and Scenario B) and compared with PPS's projections, school by school.

Summary

PPS planSchools comparedWithin 10% of PPS, 2031-32Within 5%Median differenceWithin 10%, 2027-28
PPS Status Quo7674740.0%74
PPS A6258461.6%51
PPS B6561501.6%56

Focus and alternative schools (Winterhaven, da Vinci, Odyssey, ACCESS, MLC, Benson) aren't compared, because both PPS and our model hold them fixed. 2031-32 is the main test, because PPS measures its size targets in that year.

Example: middle schools under PPS A

SchoolPPS 2027-28PPS 2028-29PPS 2029-30PPS 2030-31PPS 2031-32Our model 2031-32
Jackson618564486428404408
Tubman608546492465455423
Lane (Brentwood)384586525480457448
Gray481518551508490472
Beaumont506502501490498464
Ockley Green552486497490507521
Mt Tabor645647599580546574
Hosford602747610575557566
Kellogg507548582556579613
Harrison Park642625614578591645
West Sylvan687647670645620622
Roseway Heights655642671655628731
George604637669649636673

PPS's middle-school size goal is "more than 500 students" (Family Guide glossary). Building capacities come from PPS's 2025-26 school profiles; Hosford's is 711 and George's 623. By PPS's own numbers, 5 of these 13 schools stay between 500 and capacity in every year from 2027-28 to 2031-32. Our model gives the same count.

Why some schools differ

  • PPS's documents disagree with each other (Roseway Heights, and Beaumont under No changes). PPS's middle-school map puts the Rigler elementary area, about 104 middle schoolers, inside Roseway Heights. PPS's numbers keep those students at Beaumont. Our model follows the map. Under No changes, Beaumont and Roseway Heights together match PPS to within 0.2% (ours 914, PPS 916).
  • PPS phases some changes in; our model applies them all in 2027-28. This explains most 2027-28 differences: Lane, Kellogg, Hosford, George, Gray, Tubman, Jackson, Arleta, Llewellyn and Duniway. PPS lets current students finish where they are and moves some groups a year or two later. PPS's guides state the reasons, for example the Marysville guide, p. 3: "Delaying full implementation ensures students previously impacted by Southeast Guiding Coalition changes do not experience multiple school moves during elementary school." By 2031-32 the two mostly agree.
  • Stated modeling choices (Sunnyside +19%, Atkinson +12%, PPS A, 2031-32).
    • Sunnyside: it includes focus-lottery students in their last grandfathered year, following the Sunnyside guide (p. 3, lottery students "permitted to remain through 5th grade").
    • Atkinson: it keeps the immersion families who don't follow the program's move, an estimate PPS doesn't state.
  • Small, unexplained (Vernon, −11%, 35 students). Vernon becomes K-5. The gap comes from how a K-8's students split between K-5 and 6-8. Our model uses Census age shares; PPS uses its own grade data.

Why plan comparisons use our model, not PPS's numbers

PPS has published numbers only for its own plans. To compare the example plans with PPS A fairly, every plan, PPS A included, is scored by the same model on the same basis (2031-32, PSU forecast). When the site describes PPS A on its own, it quotes PPS's figures.

Full school-by-school table: build/solver/out_v2/calibration_table.csv. Working notes with every difference explained: build/solver/out_v2/CALIBRATION.md.

Limits

Source: index.html, README.md

In brief (from the landing page):

  • Where kids live is estimated from 2020 Census blocks, not addresses; sizes within ~15% of a threshold are uncertain.
  • Immersion and focus students’ homes are estimated.
  • Sizes by year follow PSU’s July 2026 forecast.
  • All plan results use the calibrated current model (v2).

In full (from the repository README):

  • Census blocks, not student addresses. Where kids live comes from the 2020 Census (DHC ages by block, smoothed), calibrated so today's lines reproduce 2025-26 neighborhood enrollment by school. Moved blocks carry their old area's "capture rate" (private school, transfers, charters). Out-of-sample error is about 21-27% per school, so any size within ~15% of a threshold is uncertain (build/data/backtest.md).
  • DLI and focus-program homes are estimated, not published: spread over the host's high school cluster (or district-wide) in proportion to Census kids. DLI by-grade counts are estimated.
  • Durability uses PSU's per-school forecast. Each school follows its own row in PSU's July 2026 Table 5.5 through 2035-36, the end of that forecast. PSU's low/high scenarios are not used.
  • Year-by-year results are a projection, not a forecast. Boundaries are held fixed; 2032-33 to 2035-36 are reported only.
  • Plan results are model estimates. All plans shown are model v2 runs (calibrated, PSU 2031-32 basis); see each plan's scorecard. The solver's contiguity rule (zones "star-shaped" around the school) is stricter than necessary, and middle school is solved after K-5 rather than jointly.
  • PPS's maps were digitized from vector PDFs (median georeferencing error ~70 ft). K-8 dashed areas and the Skyline inset are handled by rules. Our PPS A school sizes are within 5% of PPS's on average, but a few differ a lot.
  • High school is judged on walk miles; transit time would be the right measure. Building capacities are PPS's 2025-26 school-profile functional capacities, captured second-hand (the earlier model used the 2021 LRFP).
  • First-generation pages use an older model (NCES 2024-25 totals, public OSRM router) and are kept for reference.