0. Hard constraints (non-negotiable)
- Never send BLS to a call that requires ALS.
- Policy logic only chooses which feasible unit, never violates level-of-care feasibility.
1. Baseline policy and scenarios
Baseline policy P0 = pure nearest ETA
- Build feasible candidate set for a call:
- Available units only.
- Filter by ALS/BLS requirement.
- Dispatch the unit with minimum ETA to scene.
Scenarios we will always test on:
- S₀: Normal load
- Current call volume, current unit fleet.
- S₁: Stress by demand
- Increased call density in a selected time window (e.g., 1.5–2× calls in peak hours).
- S₂: Stress by supply
- Reduced number of units (e.g., 75% and 50% of current fleet).
(We can combine S₁+S₂ later if needed, but these three are the core.)
2. Define “critical zones” from historical data
- Spatial binning:
- Partition service area into zones (beats / townships / grid cells — one scheme only).
- Per-zone stats from historical CAD:
- total_calls(z)
- high_priority_calls(z)
- pw_calls(z) = priority-weighted calls
- Example weights: P1=3, P2=2, others=1.
- Zone risk score:
- risk_score(z) = pw_calls(z) (or a simple tweak if needed).
- Critical zones:
- Sort zones by risk_score(z) descending.
- Pick top N (≈ 3–5) zones with:
- Sufficient volume, and
- Clear geographic meaning.
These become the critical demand zones used in rules R1/R2.
3. Baseline sim and ΔETA analysis (to get K)
Run P0 (nearest ETA) on S₀/S₁/S₂ and log:
- For each call where multiple units are feasible:
- Find the nearest unit u_near.
- Find the “best alternative” v_alt that:
- Would preserve coverage in a different way (e.g., from another zone / not last unit in a critical zone).
- Compute ΔETA = ETA(v_alt) − ETA(u_near) wherever v_alt exists.
- Look at the ΔETA distribution in these “alternative exists” cases, especially when:
- u_near is in a critical zone, or
- u_near is ALS and the call does not require ALS.
- Pick a candidate K:
- Based on median / 75th percentile of ΔETA in those relevant cases.
- Initial working range: K ≈ 2–3 minutes.
K is the maximum ETA penalty we’re willing to pay to protect coverage/ALS in those specific situations.
4. Define rule templates (no fairness)
We use nearest ETA as default and add only small exception rules.
R1 – ALS Zone Protection (for non-ALS calls)
Trigger conditions (all must hold):
- Call does not require ALS.
- u_near (nearest unit by ETA) is ALS.
- u_near is the last idle ALS in its critical zone.
- There exists another feasible unit v (BLS or ALS) such that:
- ETA(v) ≤ ETA(u_near) + K.
Action:
- Dispatch v instead of u_near.
- Otherwise, stick with u_near.
R1 never downgrades an ALS-required call.
R2 – Critical Zone Coverage (any level)
Trigger conditions (all must hold):
- u_near is the last idle unit (any level) in a critical zone.
- The incident location is outside that critical zone.
- There exists another feasible unit v such that:
- ETA(v) ≤ ETA(u_near) + K.
Action:
- Dispatch v instead of u_near.
- Otherwise, stick with u_near.
5. Policy variants to evaluate
We keep the set minimal:
- P0 – Baseline
- Pure nearest ETA (already defined).
- P1 – Nearest ETA + ALS Protection (R1 only)
- Build feasible candidates (respect ALS/BLS).
- Find u_near by ETA.
- Apply R1.
- Dispatch final chosen unit.
- P2 – Nearest ETA + ALS Protection + Critical Zone Coverage (R1 + R2)
- Build feasible candidates (respect ALS/BLS).
- Find u_near by ETA.
- Apply R1. If R1 triggers, done.
- If R1 did not trigger, apply R2.
- Dispatch final chosen unit.
No fairness rules. No weight soup. Just these stacked if/elses.
6. KPIs we will track
We limit to the smallest set that can kill or validate a policy.
- Response time (by priority)
- For high-priority:
- Mean
- P90
- P95
- % high-priority calls with response time > T (e.g., T = 15 or 20 minutes; we pick one).
- For high-priority:
- Coverage in critical zones
- For each critical zone:
- % of sim time with no idle unit within Z minutes (Z ≈ 10–12).
- Optionally aggregated across critical zones.
- For each critical zone:
- (Optional, only if cheap)
- Overall mean/P90 response for non-critical priorities just to ensure we’re not blowing them up.
Fairness metrics are out of scope for now.
7. Evaluation protocol
For each policy P0, P1, P2:
- Run on S₀ (normal) + S₁/S₂ (stress) with same seeds as far as possible.
- Compute the KPIs above.
- Use these decision rules:
- Calm-mode constraint:
- In S₀, P1/P2 must be numerically very close to P0 on high-priority response times.
- If a policy hurts calm-mode high-priority performance noticeably → discard it.
- Stress-mode benefit requirement:
- In S₁/S₂, P1/P2 must show clear improvement vs P0 on at least one of:
- High-priority tail metrics (P90/P95, % > T), or
- Coverage metrics in critical zones (% time uncovered).
- If a policy does not deliver clear benefit under stress → discard it.
- In S₁/S₂, P1/P2 must show clear improvement vs P0 on at least one of:
We keep only policies that satisfy both constraints.
8. Final deliverable: rule-based frontier
Whatever survives (likely P0 + 1–2 policies from P1/P2, with a chosen K) becomes:
- Final rule lists (plain English “policy cards”).
- Formal if/else definitions (for documentation + reproducibility).
- KPI tables/plots showing:
- P0 vs P1/P2 under normal and stress scenarios.
- Clear narrative:
- “Nearest ETA is baseline.”
- “Policy X protects ALS/coverage with ≤ Y impact in calm mode and Z% better tails / coverage under stress.”
That’s the methodology we execute.