2011 · Problem A — No More Space Shuttles
Integer programming Logistics / portfolio Multi-year planning Cost optimizationRead the official problem page →
The prompt, restated
The Space Shuttle Atlantis flew the program's final mission (STS-135) in July 2011, ending thirty years of U.S. crewed-cargo capability to low Earth orbit. The ISS, however, still requires roughly 30 metric tons of upmass per year [illustrative] in food, water, propellant, science payloads, spare parts, and crew rotations until its then-planned end-of-life in 2020. Teams are asked: (1) Develop a comprehensive ten-year strategy (2011–2020) to support ISS operations using the available international fleet — Russian Soyuz (crew) and Progress (cargo), European ATV, Japanese HTV, and the emerging U.S. commercial vehicles SpaceX Dragon and Orbital Cygnus. (2) Cost the program: per-launch vehicle cost, per-kilogram cargo cost, and the cost of losing redundancy if one provider stands down. (3) Produce a year-by-year launch schedule that meets crew rotation (six on station, ~6-month tours), pressurized cargo demand, unpressurized external payload demand, and propellant resupply for ISS reboost. (4) Discuss contingency: what is the plan if Dragon slips two years, or if Soyuz is grounded after a failure? (5) Write a briefing to NASA leadership summarizing the recommended portfolio, the total ten-year cost, and the single biggest risk.
The points come from the portfolio reasoning: no single vehicle can do everything (only Soyuz carries crew; only Dragon returns downmass intact; only ATV and Progress can reboost the station). The judges want to see the cargo manifest decomposed into capability classes, then matched to vehicles minimizing cost subject to demand, schedule, and redundancy constraints.
Key modeling idea
This is a multi-period, multi-commodity assignment / integer-program. Index years $t \in \{1,\dots,10\}$, vehicles $v \in V$, and cargo classes $k \in \{\text{crew},\text{pressurized},\text{unpressurized},\text{propellant},\text{downmass}\}$. Let $n_{v,t}\in\mathbb{Z}_{\ge 0}$ be the number of vehicle-$v$ flights in year $t$, with capacity $c_{v,k}$ in class $k$ and unit cost $C_v$. Annual demand for class $k$ is $d_{k,t}$. The program is $$\min \sum_{v,t} C_v\, n_{v,t} \quad \text{s.t.}\quad \sum_v c_{v,k}\, n_{v,t} \ge d_{k,t}\;\;\forall k,t,\;\; n_{v,t}\le N_v^{\max}\;\;\forall v,t,\;\; n_{v,t}\in\mathbb{Z}_{\ge 0}$$ augmented with a redundancy constraint — e.g., no class $k$ may depend on a single provider for more than 70% of annual demand [illustrative] — and a throughput constraint reflecting limited ISS docking ports and crew handover bandwidth (no more than ~6 visiting vehicles per quarter).
Suggested approach
- Step 1 — Build the vehicle table. For each vehicle, look up pressurized-cargo mass, unpressurized capacity, crew seats, propellant for reboost, whether it returns downmass, and a unit launch cost. Cite the source for each row (NASA/ESA/JAXA fact sheets, GAO cost reports).
- Step 2 — Estimate annual demand. ISS averages roughly 28–32 t/yr pressurized + unpressurized upmass and ~6 crew rotations [illustrative]. Decompose into the five classes above and document each number (Smith & Cirillo, NASA HSF Plans).
- Step 3 — Solve the integer program. With ~6 vehicles × 10 years × 5 classes, the LP relaxation is tiny; round and verify integrality. Use PuLP / OR-Tools (technique 11 — optimization).
- Step 4 — Schedule the launches. Spread the chosen $n_{v,t}$ flights across quarters so docking-port occupancy never exceeds capacity and a Soyuz crew launch is always available within the 200-day on-orbit limit of a docked Soyuz lifeboat.
- Step 5 — Contingency & sensitivity. Re-solve with each provider removed for two years and report the cost delta and unmet-demand shortfall. This is the headline finding for the briefing.
Data sources to consider
| Source | What you get |
|---|---|
| NASA Reference Guide to the International Space Station (2010 utilization ed.) | Annual logistics demand, docking ports, reboost requirements |
| GAO-11-692 NASA: Commercial Partners Are Making Progress (2011) | COTS / CRS contract values for Dragon and Cygnus; cost-per-kg benchmarks |
| ESA ATV-3 / JAXA HTV-2 mission press kits | Per-flight pressurized capacity (~6.6 t ATV, ~6 t HTV) and per-flight cost |
| Roscosmos Soyuz/Progress public manifests | Crew seats per Soyuz (3); Progress upmass (~2.4 t) and propellant capacity |
| SpaceX CRS-1 / Orbital CRS-1 contract awards (NASA 2008) | $1.6B/12 flights Dragon, $1.9B/8 flights Cygnus — unit costs and capability |
| Augustine Commission Seeking a Human Spaceflight Program Worthy of a Great Nation (2009) | Strategic context for the post-Shuttle gap and crew-vehicle policy options |
Common pitfalls
- Treating all upmass as fungible. Crew, propellant, and downmass are not interchangeable with pressurized cargo. Decompose demand by class or your manifest will look fine on paper but strand the crew.
- Ignoring docking-port capacity. ISS has a small fixed number of docking/berthing ports (~4–6 usable [illustrative]). Stacking flights into one month is infeasible regardless of cost.
- No redundancy constraint. A single-provider optimum will pick the cheapest vehicle and ignore the 2011 reality that Soyuz had recently been grounded after a Progress M-12M failure. Add an explicit "≤ 70% from one provider per class" rule.
- Wrong-currency cost figures. Mixing 2008 NASA contract awards with 2011 ESA ATV costs without inflating to a common year is a routine red flag. State the cost base year.
- No commercial-slip contingency. Dragon's first CRS mission was in late 2012, and SpaceX's schedule was famously uncertain. A plan that assumes on-time delivery and has no fallback is what graders flag.
Python sketch
Integer program for vehicle-mix selection across ten years; PuLP solver.
import pulp
import numpy as np
# --- Vehicle catalog (capacities in t, crew in seats, cost in $M, downmass kg) ---
# rows: Soyuz, Progress, ATV, HTV, Dragon, Cygnus [illustrative]
vehicles = ["Soyuz", "Progress", "ATV", "HTV", "Dragon", "Cygnus"]
cap_press = [0.10, 1.80, 6.60, 6.00, 3.30, 2.00] # pressurized cargo (t)
cap_unp = [0.00, 0.00, 0.00, 1.50, 3.30, 0.00] # unpressurized (t)
cap_crew = [3, 0, 0, 0, 0, 0] # seats per flight
cap_prop = [0.00, 0.85, 4.50, 0.00, 0.00, 0.00] # reboost propellant (t)
cap_down = [0.10, 0.00, 0.00, 0.00, 3.00, 0.00] # downmass return (t)
cost = [70, 65, 500, 300, 130, 220] # $M / flight [illustrative]
max_flights= [5, 5, 1, 1, 4, 3] # ceiling per year
# --- Annual demand for 10 years (constant for the sketch) [illustrative] ---
years = list(range(2011, 2021))
d_press = 14.0 # t/yr
d_unp = 4.0
d_crew = 6 # seat-years
d_prop = 6.0 # t/yr
d_down = 1.5 # t/yr
# --- Build and solve ---
prob = pulp.LpProblem("iss_resupply", pulp.LpMinimize)
n = {(v,t): pulp.LpVariable(f"n_{v}_{t}", lowBound=0, upBound=max_flights[v], cat="Integer")
for v in range(len(vehicles)) for t in years}
prob += pulp.lpSum(cost[v]*n[v,t] for v in range(len(vehicles)) for t in years)
for t in years:
prob += pulp.lpSum(cap_press[v]*n[v,t] for v in range(len(vehicles))) >= d_press
prob += pulp.lpSum(cap_unp[v] *n[v,t] for v in range(len(vehicles))) >= d_unp
prob += pulp.lpSum(cap_crew[v] *n[v,t] for v in range(len(vehicles))) >= d_crew
prob += pulp.lpSum(cap_prop[v] *n[v,t] for v in range(len(vehicles))) >= d_prop
prob += pulp.lpSum(cap_down[v] *n[v,t] for v in range(len(vehicles))) >= d_down
# redundancy: no single provider supplies >70% of pressurized cargo
for v in range(len(vehicles)):
prob += cap_press[v]*n[v,t] <= 0.70 * d_press
prob.solve(pulp.PULP_CBC_CMD(msg=0))
schedule = np.array([[int(n[v,t].value()) for t in years] for v in range(len(vehicles))])
total = sum(cost[v]*schedule[v,t-years[0]] for v in range(len(vehicles)) for t in years)
print("Total 10-yr cost ($M):", total)
for v,name in enumerate(vehicles):
print(f"{name:8s}", schedule[v].tolist())
Sensitivity & validation checklist
- Drop Dragon (commercial-slip scenario) for years 1–2; re-solve. The cost should rise by roughly the gap × Dragon's marginal $/kg advantage — sanity-check the magnitude.
- Sweep the redundancy cap from 50% to 100% per provider; the cost-vs-redundancy curve is the briefing's headline chart.
- Perturb pressurized demand $\pm 20\%$ — does the recommended fleet flip? If a 5% demand bump adds an extra ATV, the plan is brittle.
- Inflate vehicle unit costs by $\pm 25\%$ independently; report which line items the recommendation is sensitive to (likely ATV and HTV given their high per-flight cost).
- Cross-check the LP relaxation optimum against the integer optimum: a large gap signals that fractional flights are doing modeling work and the constraints need tightening (e.g., minimum-block sizes on commercial contracts).
- Compare the cost-per-kg implied by your optimum against the GAO benchmark ($\sim\$40\text{k}/\text{kg}$ delivered to ISS) [illustrative] — within 30% is healthy.