Baselines
A baseline makes the reference behind a result explicit. CityLearn uses an operational business-as-usual controller for controller comparisons, a conventional counterfactual for legacy normalized KPIs, and a pre-event power reference for demand-response settlement. They answer different questions.
Business as usual: the operational reference
BusinessAsUsualAgent represents day-to-day equipment operation without
learning or price optimization. It runs the configured community, including
its demand, generation, devices, schedules and electrical constraints.
It is not a scenario with all equipment switched off.
Equipment or service |
BAU behaviour |
|---|---|
EVs |
Requests charging towards full SOC by default. The request uses the SOC deficit and remaining connection time, with a charging margin and the charger’s minimum charging rate. It never requests V2G. |
Stationary batteries |
Charges from PV surplus and discharges to serve local demand, including prospective EV and appliance demand. SOC thresholds and a power deadband control when this rule acts. |
Flexible appliances |
Requests the next pending cycle at its first feasible start opportunity. |
Electrical connection |
Scales EV and battery requests against configured total and per-phase import/export limits. Equipment and simulator constraints still determine the applied energy. |
Local sharing |
The scenario’s settlement rules value the resulting trajectory. BAU does not optimize the allocation or local-market price. |
Demand response |
Runs under the scenario, but has no policy that optimizes an activation target, payment or penalty. |
Other active actions |
Requests zero, clipped to the action bounds. This is not a dedicated HVAC, thermal-storage or escalator policy; the effect of zero follows each device’s action contract. |
The controller uses current equipment state and schedule information from the environment. It does not train a model, forecast prices, perform tariff arbitrage, optimize a planning horizon or coordinate communities.
Default parameters
Parameter |
Default |
Meaning |
|---|---|---|
|
|
EV charging target/cap, as a SOC ratio. |
|
|
With the default, charge towards full SOC rather than a lower requested departure target. |
|
|
Margin added to the requested normalized charging rate. |
|
|
Minimum normalized service request, in addition to the charger’s minimum rate. |
|
|
Stop requesting discharge below this SOC threshold. |
|
|
Stop requesting charge above this SOC threshold. |
|
|
Ignore small net-load differences around zero. |
|
|
Start command for a ready flexible appliance. |
The storage thresholds decide whether to request charge/discharge; they are not additional hard SOC constraints on the final timestep. Physical battery limits are applied by the simulator.
See the first simulation for a complete run using these defaults. A different operational policy can be created explicitly:
from citylearn.agents.baseline import BusinessAsUsualAgent
agent = BusinessAsUsualAgent(
env,
ev_follow_required_soc=True,
storage_min_soc=0.20,
storage_max_soc=0.90,
)
Label customized runs with their parameter values. The automatic comparison described below instantiates the native default BAU; it does not inherit parameters from a separate agent created by the user.
Automatic BAU evaluation
env.evaluate_v2() runs or reuses a separate BAU simulation up to the current
evaluation timestep. That simulation is rebuilt from the source schema, selected
members/EVs, episode window, timestep, topology mode and seed. It uses entity
mode when dynamic topology or demand response requires it. Rendering is disabled
for this internal comparison.
Results are cached for the current episode and timestep. The output adds
business_as_usual values, delta_to_business_as_usual differences and
ratio_to_business_as_usual ratios for supported metrics:
kpis = env.evaluate_v2()
reference_rows = kpis.loc[
(kpis["level"] == "district")
& kpis["cost_function"].str.contains("business_as_usual"),
["cost_function", "value"],
]
print(reference_rows.to_string(index=False))
Use include_business_as_usual=False to evaluate only the current run and
conventional counterfactual. env.run_business_as_usual_baseline(force=True)
recomputes the cached BAU reference.
Conventional evaluation counterfactual
Names containing baseline rather than business_as_usual refer to the
evaluation conditions selected through baseline_condition. The default uses
the simulator’s counterfactual series without storage and, for dynamic building
models, without partial-load control, while retaining PV.
This is a counterfactual calculation, not a second BusinessAsUsualAgent run.
EvaluationCondition also exposes alternatives, including removing PV.
Choose the same evaluation condition when comparing controllers.
For example, district_cost_ratio_to_baseline_total_ratio and
district_cost_ratio_to_business_as_usual_total_ratio have different
denominators. A value below one means lower cost than the named reference.
Demand-response baseline
DR delivery is measured against mean net power in the configured pre-event history window. The reference is frozen for each request, then used to measure movement in the requested direction during its activation.
This reference is neither the conventional counterfactual nor a BAU rollout.
Configure demand_response.baseline_window_seconds and inspect baseline
validity alongside requested, delivered and credited response. See the
DR schema and
DR KPIs.
A reference run selected in the UI
When comparing imported runs, the UI labels the first included simulation
in its imported list as Compare baseline. That is a user-selected run; it need not be the native
BAU. The business_as_usual columns inside each exported KPI table retain
their simulator-defined meaning.
Read the scorecard for matched-controller comparisons and the UI guide for the visual workflow.