Quickstart

This page runs a first simulation. SmartCer needs a scenario: a folder with a config.json and one CSV file per node.

A SmartCer study in four steps: input data, configuration, simulation, results.

From data to results.

Important

The PyPI package does not ship any scenario. The example below uses the synthetic scenario test/fixtures/mini_cer_v1 of the repository: 4 nodes, 2 of them with a battery, 48 hours of made-up hourly data, used by the test suite. It is available from a source checkout (git clone and pip install -e ., see Installation); it is not installed by pip install smartcer. The numbers it produces illustrate the API and have no meaning for a real community. To use your own data, see the scenario format below.

The example

The code is in examples/first_simulation.py and resolves the scenario path relative to the repository root, so it runs from any directory:

python examples/first_simulation.py
from pathlib import Path

import gymnasium as gym

import smartcer  # registers SmartCer-v1
from smartcer.gym.controllers import compute_baselines


REPO_ROOT = Path(__file__).resolve().parents[1]
SCENARIO = REPO_ROOT / 'test' / 'fixtures' / 'mini_cer_v1'
OUTPUT_DIR = REPO_ROOT / 'results' / 'first_simulation'


def main() -> None:
    """Run one episode with random actions, then compare the baseline controllers."""
    env = gym.make('SmartCer-v1', scenario=SCENARIO, episode_length=24)
    obs, info = env.reset(seed=0)
    print(f'observation: {obs.shape}, action space: {env.action_space}')

    done = False
    while not done:
        action = env.action_space.sample()  # one action per battery, positive charges
        obs, reward, terminated, truncated, info = env.step(action)
        done = terminated or truncated
    print('last step welfare:', info['welfare'])
    print('last step penalty:', info['penalty'])

    kpis = compute_baselines(env.unwrapped, OUTPUT_DIR, seed=0)  # naive and rbc_community
    for name, values in kpis.items():
        print(f'{name}: welfare {values["welfare"]:.2f} EUR, '
              f'sharing rate {values["sharing_rate"]:.2f}')
    print(f'tables and KPIs written to {OUTPUT_DIR}')


if __name__ == '__main__':
    main()

What it does:

  1. gym.make('SmartCer-v1', ...) builds the environment on the scenario, with episodes of 24 steps.

  2. env.reset(seed=0) returns the first observation, a flat vector, and an info dictionary.

  3. The loop applies random actions: one value in [-1, 1] per battery, positive to charge. The episode ends with truncated=True after the last step.

  4. info['welfare'] is the breakdown of the community welfare of the last step and info['penalty'] the constraint penalty K_t.

  5. compute_baselines runs the naive (idle batteries) and rbc_community (rule-based) controllers over the same episode, returns their KPIs and writes tables to results/first_simulation/. See KPIs and outputs.

Your own scenario

A scenario folder looks like this:

{
  "format_version": "1.0",
  "name": "my_cer",
  "delta_t": 1.0,
  "units": "kWh",
  "incentive": {"model": "uniform", "unit_value": 0.11},
  "nodes": {
    "pv_1": {
      "type": "producer",
      "csv": "data/pv_1.csv",
      "storage": {
        "capacity": 100, "power_charge_max": 30, "power_discharge_max": 30,
        "efficiency_charge": 0.95, "efficiency_discharge": 0.95, "soc_min": 0.1
      }
    },
    "aggregated_load": {"type": "consumer", "csv": "data/consumers.csv"}
  }
}

The CSV columns are datetime, production and consumption (kWh per step, or kW with units: kW), sell_price and buy_price (€/kWh); which columns a node needs depends on its type. The full format is described in the configuration reference.

Next steps

  • Concepts: what the observation, the action and the reward contain, and how to add forecasts.

  • API reference: SmartCerEnv and its arguments.