2020 · Problem A — The Best Summer Job
AHP / TOPSIS MCDM Sensitivity Decision modelingThe prompt, restated
A graduating high-school senior with strong grades, decent savings, and an interest in earth sciences has been offered several different summer jobs/internships before college begins. Each offer differs along multiple dimensions: hourly pay, total expected earnings, location (home town vs. out of state), housing cost or stipend, learning/career-relevance, intensity (40 vs. 60 hour weeks), and "soft" criteria like fit with friends, family proximity, and the chance to travel. Some offers are concrete (a specific lab internship) and some are open-ended (start a small business of your own).
The team is asked to (1) identify the factors a thoughtful student would weigh when choosing, (2) build a model that scores any candidate job against those factors and produces a ranking, (3) apply the model to a set of representative offers — at least one of which is open-ended and one of which is geographically inconvenient — and (4) test how robust the ranking is to changes in the student's personal weights. A two-page letter to the student summarizing the recommendation is requested.
Key modeling idea
This is a textbook multi-criteria decision-making problem. The student is the single decision-maker, and the criteria split cleanly into "benefit" criteria (pay, learning, fun) and "cost" criteria (commute time, hours, expenses). The cleanest pipeline is AHP-for-weights + TOPSIS-for-scoring, with a clear sensitivity sweep on the AHP pairwise matrix.
Suggested approach
- Step 1 — Define 5–7 criteria, no more. Judges punish 12-criterion models. Pick: net earnings, learning/career fit, hours/workload, location/commute, fun & friends.
- Step 2 — Use AHP to derive weights from the student's pairwise judgments. Check the Consistency Ratio < 0.10.
- Step 3 — Score with TOPSIS: normalize each criterion to [0,1], apply weights, compute distance to ideal-best and ideal-worst.
- Step 4 — Apply to ≥5 hypothetical offers, including at least one "start your own thing" and one out-of-state offer. Tabulate the scores.
- Step 5 — Monte Carlo sensitivity (technique 10): perturb the AHP weights ±20% and show how often the top choice changes.
Data sources to consider
| Source | What you get |
|---|---|
| Bureau of Labor Statistics OES | Typical summer/intern wages by occupation and region |
| Glassdoor / LinkedIn salary pages | Realistic intern stipends for named programs |
| Numbeo / BestPlaces cost-of-living index | Adjust earnings for location |
| Google Maps Distance Matrix API | Commute time as a real input |
| CommonApp / Niche student survey data | Self-reported "career relevance" scores |
Common pitfalls and judge commentary patterns
- Inventing fake offers without a backstory. Judges want to see real-feeling jobs grounded in BLS or program-specific data.
- Skipping the Consistency Ratio. AHP without CR < 0.10 is not AHP.
- No sensitivity. A single ranking with no robustness check looks like a Numbers spreadsheet, not a model.
- Treating "open a small business" as a regular offer. It has wider variance on earnings; model it as a distribution, not a point estimate.
- Letter that just restates the table. The non-technical letter has to read like advice, not output.
Python sketch
Minimal AHP + TOPSIS over a small offer set. CR check included.
import numpy as np
# pairwise AHP matrix over 5 criteria (illustrative)
# criteria order: earn, learn, hours, location, fun
A = np.array([
[1, 1/2, 3, 2, 3 ],
[2, 1, 4, 3, 3 ],
[1/3, 1/4, 1, 1/2, 1 ],
[1/2, 1/3, 2, 1, 2 ],
[1/3, 1/3, 1, 1/2, 1 ],
])
w_unnorm = A.prod(axis=1) ** (1/A.shape[0])
w = w_unnorm / w_unnorm.sum()
lam_max = (A @ w / w).mean()
CI = (lam_max - 5) / 4
RI = 1.12
CR = CI / RI
assert CR < 0.10, f"AHP not consistent, CR={CR:.3f}"
# offers: rows = jobs, cols = criteria (raw values, benefit=+, cost=-)
offers = np.array([
# earn learn hours loc(0-10 better=close) fun
[4500, 8, 45, 9, 7], # local lab
[9000, 9, 55, 3, 6], # out-of-state research
[3000, 5, 30, 9, 9], # camp counselor at home
[6000, 7, 50, 7, 5], # corporate sales intern
[3500, 8, 35, 9, 8], # start small business
])
cost_mask = np.array([False, False, True, False, False]) # hours is cost
# TOPSIS: invert costs, then min-max normalize column-wise
X = offers.astype(float).copy()
X[:, cost_mask] = -X[:, cost_mask]
Xn = (X - X.min(0)) / (X.max(0) - X.min(0))
V = Xn * w
ideal_best, ideal_worst = V.max(0), V.min(0)
d_plus = np.linalg.norm(V - ideal_best, axis=1)
d_minus = np.linalg.norm(V - ideal_worst, axis=1)
score = d_minus / (d_plus + d_minus)
print(np.argsort(-score), score.round(3))
Sensitivity & validation checklist
- Re-run TOPSIS with each weight perturbed by ±20% — record fraction of trials where the winner changes.
- Swap the AHP pairwise matrix for an equal-weights baseline; does the top job stay?
- Test with one "dominated" offer included and confirm it never wins.
- Walk through every criterion: is the direction (benefit/cost) right?
- Confirm CR < 0.10 and state it in the paper.