← Past problems · 2018 set

2018 · Problem B — Cozy Smart House

Optimization Thermal modeling Control / schedule Sensitivity

Read the official PDF →

The prompt, restated

A homeowner is installing a "smart" climate-control system in a single-family house. The system can program heating, cooling, ventilation, blinds, and dehumidification on a per-hour schedule, learning from weather forecasts, electricity tariff schedules, occupancy patterns (everyone out 9–5 weekdays), and outdoor air-quality data (pollen, smoke). The homeowner wants the schedule to be optimal across four often-competing axes: thermal comfort, energy cost, indoor air quality, and equipment wear.

The team is asked to (1) build a thermal model of a representative home (walls, windows, internal mass), (2) define a multi-objective "comfort + cost + air quality" loss, (3) design a schedule (HVAC setpoint per hour, blinds open/closed, ventilation on/off) that minimizes that loss for a typical summer week and a typical winter week, (4) extend the schedule to a full year with a small number of seasonal "modes", and (5) write a one-page user-facing explainer for the homeowner.

Key modeling idea

This is optimization-over-time on a small thermal model. Indoor temperature $T_\text{in}(t)$ evolves under a first-order ODE driven by outdoor temperature, solar gain, and HVAC heat injection. The controller picks an HVAC schedule that minimizes a weighted sum of (comfort error)² + (electricity cost) + (CO₂ / pollen exceedance). This is a small LP or quadratic program if linearized, or a DP if discretized.

Suggested approach

  • Step 1 — Lumped-RC thermal model. $C \dfrac{dT_\text{in}}{dt} = \dfrac{T_\text{out} - T_\text{in}}{R} + q_\text{solar} + q_\text{HVAC}$. Calibrate $R$ and $C$ against a published reference home (e.g., DOE ResStock).
  • Step 2 — Loss function. $L = \alpha \cdot (T_\text{in} - T_\text{set})^2 + \beta \cdot \text{price}(t) \cdot |q_\text{HVAC}| + \gamma \cdot \text{AQ\_penalty}$. Use AHP-style weights $\alpha, \beta, \gamma$ from the homeowner.
  • Step 3 — Schedule as LP. Hourly $q_\text{HVAC}(t)$ as decision variable; linearize $|q|$. Solve with PuLP for a 168-hour week.
  • Step 4 — Compare scenarios. Hot summer week (cooling-limited), cold winter week (heating-limited), shoulder week (free cooling via ventilation).
  • Step 5 — Annual extension. Cluster days into 4–6 archetypes with k-means on (T_out, solar, AQI); generate one optimal schedule per archetype.

Data sources to consider

SourceWhat you get
NOAA NCEI Local Climatological DataHourly outdoor temperature, solar, humidity for any US site
EPA AirNow APIHourly outdoor PM2.5 / ozone / pollen
NREL ResStock / EnergyPlus reference homesRealistic RC parameters by climate zone
Utility time-of-use tariff sheetsHourly electricity prices (peak/off-peak)
ASHRAE 55 thermal-comfort standardAcceptable temperature/humidity bands
EPA Indoor airPLUS guidelinesVentilation rate targets (ACH)

Common pitfalls and judge commentary patterns

  • No thermal model. Some teams just pick a setpoint per hour without any building physics — judges flagged this.
  • Constant electricity price. The whole point of "smart" is shifting load to off-peak; modeling a single rate kills the answer.
  • Ignoring solar gain. South-facing windows are huge; not modelling them means the blinds variable is useless.
  • Forgetting humidity / air quality. The prompt explicitly asks for IAQ; optimizing only on temperature loses points.
  • Schedule presented as a wall of numbers. The user-facing explainer needs a picture, not a CSV.

Python sketch

Tiny RC thermal sim with hourly LP setpoint optimization for a 24-hour day. Extend to 168 hours and to a multi-mode annual schedule for the real submission.

import numpy as np, pulp

H = 24
T_out  = np.array([18,17,16,16,16,17,19,22,25,28,30,32, 33,34,33,32,30,28,26,24,22,20,19,18])
price  = np.array([0.10]*7 + [0.20]*4 + [0.35]*5 + [0.20]*5 + [0.10]*3)  # $/kWh
T_set  = 23.0
R, C   = 5.0, 12.0       # thermal resistance / capacitance (illustrative)
T0     = 24.0

m = pulp.LpProblem("hvac", pulp.LpMinimize)
q   = [pulp.LpVariable(f"q{t}", -3, 3)  for t in range(H)]    # kW HVAC (+ heat, - cool)
qa  = [pulp.LpVariable(f"a{t}", 0)      for t in range(H)]    # |q|
Tin = [pulp.LpVariable(f"T{t}", 18, 28) for t in range(H)]
err = [pulp.LpVariable(f"e{t}", 0)      for t in range(H)]    # |T - Tset|

alpha, beta = 5.0, 1.0
m += pulp.lpSum(alpha*err[t] + beta*price[t]*qa[t] for t in range(H))

for t in range(H):
    m += qa[t] >=  q[t]
    m += qa[t] >= -q[t]
    m += err[t] >=  (Tin[t] - T_set)
    m += err[t] >= -(Tin[t] - T_set)
    prev = T0 if t == 0 else Tin[t-1]
    m += Tin[t] == prev + (1/C) * ((T_out[t] - prev)/R + q[t])

m.solve(pulp.PULP_CBC_CMD(msg=False))
print("T_in:", [round(v.value(), 1) for v in Tin])
print("q   :", [round(v.value(), 2) for v in q])

Sensitivity & validation checklist

  • Vary loss weights $\alpha : \beta : \gamma$ across (5:1:0), (5:1:5), (1:5:1) — does the schedule change shape predictably?
  • Compare against a dumb constant-setpoint baseline; quantify $ saved.
  • Use a Phoenix summer week vs. a Minneapolis winter week — model should produce very different schedules.
  • Run with R doubled (better-insulated house); peak HVAC load should drop materially.
  • Confirm ASHRAE 55 comfort band is respected in all hours.

Related pages