Skip to content

feat(phase-8b): urban_capex_multiplier on estimate_cost#25

Merged
harsh-pandhe merged 1 commit into
mainfrom
feat/phase-8b-urban-capex
May 20, 2026
Merged

feat(phase-8b): urban_capex_multiplier on estimate_cost#25
harsh-pandhe merged 1 commit into
mainfrom
feat/phase-8b-urban-capex

Conversation

@harsh-pandhe
Copy link
Copy Markdown
Owner

Summary

The Mi Teleférico Línea Roja case-study doc (Note 4 — Capex) flagged this explicitly: the optimizer's BoM covers steel + cable + drive motor + foundations + carriers, but a real urban transit gondola also pays for electrical substation + MV distribution, signalling + station IT, land acquisition / easements, station buildings beyond the two terminals, ops control room + spare parts, local VAT + import duties + OEM engineering fees + financing.

The empirical ratio is 5–7× bare-infrastructure for urban gondolas in this size class. The optimizer was honestly under-reporting capex on every urban case study.

API (additive, fully backward-compatible)

  • CostEstimate.urban_capex_multiplier (default 1.0)
  • CostEstimate.bare_infrastructure_total — subtotal + contingency, pre-multiplier
  • CostEstimate.urban_uplift — the delta from multiplier > 1
  • CostEstimate.grand_total now == bare * multiplier
  • summary_lines() + as_csv() show the uplift only when multiplier != 1.0, so legacy callers reading the old CSV format keep working bit-for-bit
  • estimate_cost(..., urban_capex_multiplier=6.0) — new kwarg; raises ValueError for values < 1.0

Test plan

  • tests/test_urban_capex.py7 new: default 1.0 unchanged, default CSV/summary legacy-format preserved, 6× -> 6× bare, summary/CSV include uplift only when >1, <1.0 raises, Linea-Roja-style BOM with 6× recovers the published budget envelope
  • Full suite 203 → 206 passing, zero regressions

The Mi Teleférico Línea Roja case-study doc flagged this explicitly:
the optimizer's BoM covers steel + cable + drive motor + foundations
+ carriers, but a real urban transit gondola also pays for the
electrical substation + medium-voltage distribution, signalling +
station IT, land acquisition / easements, station buildings beyond
the two terminals, ops control room + spare parts, local VAT +
import duties + OEM engineering fees + financing. The empirical
ratio is 5-7x bare-infrastructure for urban gondolas in this size
class — the optimizer was honestly under-reporting capex on every
urban case study.

cost.py changes (additive, fully backward-compatible):
  - CostEstimate.urban_capex_multiplier (default 1.0)
  - CostEstimate.bare_infrastructure_total (subtotal + contingency,
    pre-multiplier — what the optimizer puts on the ground)
  - CostEstimate.urban_uplift (the delta from multiplier > 1)
  - CostEstimate.grand_total now == bare * multiplier
  - summary_lines() and as_csv() show the uplift only when
    multiplier != 1.0, so legacy callers reading the old CSV format
    keep working bit-for-bit
  - estimate_cost(..., urban_capex_multiplier=6.0) is the new kwarg;
    raises ValueError for values < 1.0

Tests: tests/test_urban_capex.py — 7 new
  - default multiplier 1.0 leaves grand_total ≡ bare_infrastructure
  - default CSV/summary unchanged (legacy format preserved)
  - multiplier 6.0 -> 6x bare, urban_uplift == 5x bare
  - summary/CSV include uplift lines only when multiplier > 1
  - <1.0 multiplier raises ValueError
  - Linea-Roja-style BOM with 6x multiplier recovers a turnkey
    envelope in the right order of magnitude vs the published budget

Full suite 203 -> 206, zero regressions.
@harsh-pandhe harsh-pandhe merged commit 9d09713 into main May 20, 2026
2 checks passed
@harsh-pandhe harsh-pandhe deleted the feat/phase-8b-urban-capex branch May 20, 2026 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant