What This Tool Does
The Backpacking Resupply Optimizer helps backpackers plan lightweight, nutritionally complete food resupply boxes. Given your trip duration, calorie target, and store type, it selects a basket of shelf-stable, no-cook foods that minimizes total pack weight while meeting dietary reference intake targets — the same trade-off you face when deciding whether to carry almonds or instant mashed potatoes.
Datasets
NHANES / WWEIA — What We Eat in America
The primary source of food composition data. WWEIA is the dietary recall component of the National Health and Nutrition Examination Survey (NHANES), conducted by the USDA and CDC. Each food is assigned an 8-digit FNDDS food code with per-100g nutrient values for ~30 nutrients.
Cycles used: August 2021 – August 2023 ↗ FNDDS databases
USDA FoodAPS — National Household Food Acquisition and Purchase Survey
FoodAPS links actual grocery purchases to FNDDS food codes, providing real-world price data, package sizes, store type flags (grocery, rural, convenience store), and item descriptions from store receipts. This is the source of the "estimated price" values shown in the optimizer.
Coverage: ~4,400 foods with observed purchase prices ↗ USDA ERS FoodAPS
FNDDS At-a-Glance — Additional Food Descriptions
The 2019–2020 FNDDS "At a Glance" spreadsheet provides secondary food descriptions — brand names, common aliases, and product names — for each food code. These are shown as the gray subtitle text under each food name (e.g. "Girl Scout Tagalong; Little Debbie Nutty Bar").
Perishability Data — Days Without Refrigeration
A custom-built lookup table mapping each WWEIA food category to the number of days it can safely be carried without refrigeration. Shelf-stable categories (nuts, dried fruit, crackers) get 14+ days; perishable fresh foods get 0 days. When you set the "Days of Food" parameter, the optimizer automatically excludes foods that would spoil before the end of your trip.
Source: WWEIA_Days_Without_Refrigeration.csv (custom, based on USDA food safety guidelines)
Optimization Model
Decision Variables
For each candidate food i, the model has two variables:
g_i ≥ 0— grams of food i to packy_i ∈ {0, 1}— binary indicator: 1 if food i is selected at all (used when food diversity is > 0)
When diversity is zero, only continuous g_i variables are used and the problem is solved as
a linear program (LP) with GLOP. When diversity > 0, binary variables are added and the problem
becomes a mixed-integer program (MIP) solved with SCIP. Both solvers are from
Google OR-Tools.
Objective Function
The default objective is maximum calorie density — equivalently, minimum total weight for a fixed calorie target:
minimize Σ g_i
Carrying fewer grams to hit the same calorie goal means a lighter pack. Because calorie density varies by food (nuts ~7 kcal/g, dried fruit ~3 kcal/g, instant meals ~4 kcal/g), the optimizer gravitates toward calorie-dense foods unless constrained by nutrition or diversity.
Other available objectives:
- Lowest Cost — minimize
Σ price_i × g_i / 100 - Most Diverse — maximize a category-spread score
- Max Protein / Fiber / Vitamin C / Iron / Vitamin D — maximize that nutrient per gram
Constraints
-
Calorie target: total calories must fall within ±3% of
calories_per_day × days -
Nutrient minimums (optional, from DRI): for each nutrient with a non-zero scale,
Σ (nutrient_i / 100) × g_i ≥ DRI_min × scale. If a nutrient is physically unachievable from the available food set, the constraint is automatically relaxed and a warning is shown. - Nutrient maximums: upper bounds from the Dietary Reference Intakes (e.g. max iron 45mg/day) are enforced to prevent unsafe megadosing.
- Per-food cap: no single food may contribute more than a fraction of total calories (40% at diversity=0, relaxing toward 100% at diversity=1 to give the minimum-foods constraint room to work).
-
Category calorie cap: when diversity > 0, no food category (e.g. Nuts & Seeds)
may supply more than
(1 − 0.55×diversity)of total calories. -
Minimum distinct foods (MIP only):
Σ y_i ≥ min_foods, wheremin_foods = round(diversity × 20), capped at the candidate set size. Each selected food must also contribute at least ~50 kcal (enforced viag_i ≥ min_serving × y_i) so the binary variables correspond to meaningful portions. -
Perishability filter: foods with
days_without_refrigeration < trip_daysare excluded from the candidate set entirely.
Dietary Reference Intakes (DRI)
Nutrient minimums are scaled from DRI values computed for a 70 kg adult per day × number of trip days. The "Nutrition Profile" setting applies a multiplier to each nutrient's minimum:
- Optimal — full DRI for protein, fiber, calcium, iron, vitamin C, vitamin D; 75% for potassium, B12, zinc, magnesium, folate; 50% for choline
- Reduced — 25–50% of DRI for most nutrients; zero for zinc, magnesium, folate, choline
- None — no nutrient constraints applied
- Custom — per-nutrient sliders
Prices
All prices are estimates derived from FoodAPS purchase observations, adjusted
to 2025 dollars using category-specific food CPI series from the BLS (Consumer Price Index,
U.S. City Average, All Urban Consumers). The median observed price per 100g is multiplied by
a category-specific inflation factor; a fallback of $0.50/100g × 1.45 (overall food-at-home
inflation) is applied where no observed price exists.
Inflation multipliers by food category (2013 average to December 2025):
- Cereals & Grains, Bars & Snacks: ×1.35 (CUUR0000SAF11)
- Dairy & Cheese: ×1.39 (CUUR0000SAF114)
- Meat, Poultry, Seafood: ×1.23 (CUUR0000SAF113)
- Fruits, Vegetables, Dried Fruit: ×1.27 (CUUR0000SAF116)
- Nuts, Oils, Condiments, Beverages, Sweets: ×1.24 (CUUR0000SEFJ)
- All other / fallback: ×1.45 (CUUR0000SAF1)
inflate_prices.py is run against the
live BLS public API.
Limitations
- FoodAPS prices are from 2012–2013 and are inflation-adjusted to 2025 dollars using BLS food CPI series, but category-level indices may not capture variation within a category (e.g. organic vs. conventional).
- Only ~1,260 of 4,400 foods have observed purchase prices; the rest use the $0.50/100g fallback.
- Package sizes are derived from typical FoodAPS purchase quantities and are approximate.
- The perishability lookup is a conservative estimate based on food category, not specific products.
- Nutrient values are per-100g averages across food preparations and may not reflect the specific product you buy.