Skip to main content

qellaris

A benchmark for switching mobile-network sectors off to save energy, scored on what each decision actually costs.

Mobile base stations burn power even when nobody is using them. Putting lightly used radio sectors to sleep saves energy, but sleep too many and people go unserved. qellaris is a test bench for methods that make that call every 15 minutes. It provides synthetic people moving on real OpenStreetMap streets, interchangeable demand forecasters and controllers, and one shared scoring rule that grades classical, quantum-inspired and reinforcement-learning methods in exactly the same way.

pip install qellaris              # benchmark, dashboard and command line
pip install "qellaris[quantum]"   # + D-Wave samplers and Qiskit (QAOA)
qellaris menu                     # a guided menu: it asks, then runs the command

Requires Python 3.11 or newer. Works on Windows, macOS and Linux.

What this is not. It makes no claim of quantum advantage, real operator radio accuracy, or a calibrated digital twin of a live network. Demand, people and capacities are synthetic. The quantum solvers are classical simulations of quantum computers; nothing is sent to real quantum hardware unless you submit the exported job yourself.


Contents

Why another benchmark? · Install · Five-minute tour · The dashboard, page by page · Command-line reference · Plug in your own forecaster or controller · Solvers · The Quantum Algorithm Zoo page · Study areas and region packages · How a schedule is scored · Fair comparisons · Equity · Data, licences and limits


Why another benchmark?

Most forecasting papers stop at accuracy, and most optimisation papers assume the forecast is perfect. In practice a network operator forecasts demand, commits a schedule, and only then learns how many people actually turned up. qellaris scores that whole loop, and splits every bad outcome into its two causes:

solver_gap + forecast_gap = total_decision_regret
  • forecast gap: what the forecast's errors cost you, given a perfect optimiser;
  • solver gap: what the optimiser cost you, given the same forecast.

All three schedules involved (yours, the reference solver's on your forecast, and the reference solver's on the true demand) start from the same network state and are scored by the same rule. So you can tell whether a forecaster or an optimiser caused a bad result.

This matters because accuracy and good decisions disagree. In the project's own runs, a seasonal forecaster was 5.6 times more accurate than a flat average (by mean absolute error), yet the schedules built on it cost 58% more in forecast gap. The flat average over-predicts in quiet hours, keeps more sectors awake, and so rarely leaves anyone unserved. The benchmark scores the decision, not the prediction.


Install

pip install qellaris

Optional extras:

Extra Adds Install
quantum dimod, dwave-samplers, qiskit, qiskit-aer, scipy: the D-Wave and QAOA solvers pip install "qellaris[quantum]"
dev pytest, build, twine pip install "qellaris[dev]"

Without the quantum extra the benchmark simply offers fewer solvers.

Downloaded maps and run results are written to a workspace/ folder in the current directory. Set the QELLARIS_HOME environment variable to put them somewhere fixed.


Five-minute tour

qellaris menu

The menu asks a few questions, prints the exact command it is about to run, and runs it. Use it to learn the commands, then type them directly. Its options:

  1. Open the dashboard
  2. Run the benchmark (quick look, all solvers, or five seeds)
  3. Browse the Quantum Algorithm Zoo
  4. Download a study area from OpenStreetMap
  5. Share or import study areas as .zip packages
  6. Worked examples (write your own agent)
  7. Which solvers are installed?

Or go straight to it:

qellaris ui                                  # dashboard at http://127.0.0.1:8765
qellaris benchmark --geography kensington    # leaderboard of every installed solver
qellaris template --compare                  # four example policies side by side
qellaris zoo --fit direct                    # quantum algorithms that could schedule

python -m qellaris <command> works the same way if your scripts folder is not on PATH.


The dashboard, page by page

qellaris ui opens an interactive dashboard (built with Mesa and Solara) in your browser. The left sidebar sets the population size, random seed, demand event, scheduling solver and map; Step and ▶ run the simulation, and Reset rebuilds it with new settings. Six named tabs:

Live map. The study area with its demand areas, how busy each one is, radio coverage, every sector (awake or asleep), the simulated people, and which mast serves which area. A toggle colours buildings by the use the model assigns them. Footprints whose OpenStreetMap tags state their use are drawn solid; ones that inherit their area's use are drawn faint. Beside the map: the time of day, the current decision and its costs, and a live solver leaderboard that runs every installed solver on the interval about to be scheduled and ranks them.

Time series. Total and forecast demand over time, the split of decision cost into forecast gap and solver gap, and energy, unserved demand and equity per interval.

Equity audit. Who actually gets served, across twelve synthetic dimensions: age, income band, device, access needs, work pattern, household and more. For each it shows the gap between best- and worst-served groups, which direction the gap runs, and whether the energy-saving schedule caused it. The same interval is replayed with every sector awake for comparison.

Demographics. Who is out there and what they are doing (travelling, at home, at work, out), with no service information at all. It is kept separate from the equity audit so "this group is large and busy" is never confused with "this group is being failed".

Study area. Download a new area by place name or bounding box, see every area you already have, switch to one with Use (no restart), save any area as a .zip region package, or drop someone else's package in. Beside it, a land-use audit shows what the area actually contains and which venue (if any) hosts the demand event.

Quantum Algorithm Zoo. Every algorithm from the Quantum Algorithm Zoo with a plain-language description, plus a guide to plugging one into the benchmark (see the Quantum Algorithm Zoo section below).


Command-line reference

Everything is one command, qellaris, with subcommands. Each subcommand also exists as its own script (qellaris-zoo, qellaris-menu, ...).

Command What it does
qellaris menu Guided menu over everything below
qellaris ui [--port 8765] [--no-browser] Interactive dashboard
qellaris benchmark [...] Forecast-and-schedule benchmark; prints a leaderboard and writes CSV/JSON results
qellaris benchmark --list-backends Which solvers are installed
qellaris equity --scenarios protective neutral ... Compare fairness rules on one identical population
qellaris train --episodes 120 Train the reinforcement-learning controller
qellaris template --compare / --forecast / --explain / --broker Worked examples for writing your own agent
qellaris region NAME --place "Camden, London" --radius-km 1 Download a study area from OpenStreetMap
qellaris region-pack list / export / import Share study areas as .zip files
qellaris zoo [--fit direct] [--search WORD] [--guide] Quantum Algorithm Zoo catalogue and guide
qellaris hardware-job JOB.json RESULT.json Decode results returned from a real quantum computer
qellaris opencellid, qellaris netbravo Fetch optional real cell-site and signal datasets

Useful benchmark options:

qellaris benchmark --geography kensington \
    --solvers greedy annealing qaoa always_on \
    --scenario entertainment_event \
    --seeds 17 23 42 101 2027 \
    --output workspace/runs/my-run
  • --geography: kensington (bundled), synthetic (no map), or the path of any downloaded study area
  • --scenario: normal, entertainment_event (best venue the area has), or a specific venue type such as park_event
  • --seeds: repeat the whole experiment and report paired confidence intervals
  • --point-forecast: schedule on the forecast itself rather than its upper bound
  • --inventory FILE.json: use your own fixed tower and sector layout

Run any command with --help for the full list.


Plug in your own forecaster or controller

No Mesa or Gymnasium subclassing is needed. Both receive plain JSON-safe lists, and two decorators register them:

from qellaris import register_agent, register_forecaster
from qellaris.template import build_env, run_episode

@register_forecaster("last-value")
class LastValue:
    def forecast(self, request):
        last = {row["zone_id"]: row["demand"] for row in request["records"]}
        return [{"step": request["train_steps"] + step, "zone_id": zone,
                 "prediction": value, "lower": value * 0.8, "upper": value * 1.2}
                for zone, value in last.items()
                for step in range(request["horizon"])]

@register_agent("busy-sectors")
class BusySectors:
    def act(self, state):
        sectors, width = state["network_shape"]
        load = state["network_vector"]
        return [int(load[i * width + 2] > 0.25) for i in range(sectors)]  # 1 = awake

result = run_episode(BusySectors(), build_env(days=1))

A controller receives, each interval, the forecast and its upper bound, which sectors were awake, eight features per sector, and a separate demographic table. It returns one 0/1 per sector. Its schedule is then scored by the shared rule. qellaris template --explain prints exactly what arrives.

For reinforcement learning there is a Gymnasium environment:

import gymnasium as gym
import qellaris.control_env   # registers the environment

env = gym.make("QaioSectorControl-v0", n_agents=240)
state, info = env.reset(seed=17)
state, reward, terminated, truncated, info = env.step(env.action_space.sample())

The reward is the negative of the same score every solver gets, and info reports energy, unserved demand and switching separately.


Solvers

Solver How it chooses Needs
greedy Builds a schedule sector by sector, then improves it locally —
exact Branch and bound; reports whether it proved its answer optimal —
annealing Simulated annealing on the QUBO formula —
rl A small learned policy (one shared linear model per sector) —
always_on Keeps every sector awake: the do-nothing reference —
dwave_anneal, tabu, steepest D-Wave's classical samplers on the QUBO [quantum]
qubo_exact Checks every combination of the QUBO core [quantum]
qaoa, qaoa_noisy QAOA circuits in Qiskit's simulator (ideal and noisy) [quantum]

QUBO is the scheduling problem rewritten as one formula over on/off variables, the input format quantum annealers and QAOA accept. A full network has too many sectors to simulate on a quantum computer, so greedy fixes the sectors it is sure about and the quantum-style solvers decide only the 12 to 16 it is least sure about (the core). They return suggested schedules only; the shared scoring grades them, so no method can look better by being marked differently.

When qaoa runs, the first test interval is also saved as hardware_job.json, which holds everything a real quantum computer needs. It is marked PREPARED_NOT_SUBMITTED until someone sends it. When results come back, qellaris hardware-job turns them into a full schedule.


The Quantum Algorithm Zoo page

The Quantum Algorithm Zoo, maintained by Stephen Jordan, catalogues quantum algorithms that are faster than the best known classical methods for some problem. qellaris lists all 74 entries, on the dashboard and from the command line, each with a short description of what the algorithm does and how. Each one is also rated for where it could fit in this benchmark:

Rating Count Meaning Examples
Wired in 1 Already runs here, on a simulator QAOA
Direct fit 9 Could choose which sectors sleep Grover search, quantum annealing, quantum-walk simulated annealing, thermal-state sampling, quantum backtracking, SDP bounds, DQI
Adjacent 13 Could help forecasting, training or checking results linear systems (HHL), quantum ML, gradient estimation, network flows
Not applicable 51 Solves a problem not in this benchmark Shor's factoring, knot invariants, hidden subgroups

Two more views explain how to add one, and in which benchmark scenarios it could make a difference. Examples are demand spikes, proving a schedule is optimal, and larger problems on real hardware.

qellaris zoo                    # the whole catalogue with descriptions
qellaris zoo --fit direct       # only the ones that could produce a schedule
qellaris zoo --search annealing
qellaris zoo --guide            # how to plug one in + which scenario to use
from qellaris import quantum_zoo

for row in quantum_zoo.by_fit("direct"):
    print(row["name"], "-", row["description"])
    print("  fits at:", row["hook"])
    print("  how:", row["how"])
    print("  when:", row["when"])

Adding a new schedule-producing algorithm means one subclass with one method:

from qellaris.quantum import QUANTUM_SOLVERS, QuboBackendSolver
from qellaris.solvers import SolverProvenance

class MyQuantumSolver(QuboBackendSolver):
    provenance = SolverProvenance("my_quantum", "quantum", "simulator",
                                  "what it is, for the results table")
    core_size = 14

    def available(self):
        return True

    def sample(self, reduced):
        # `reduced` is the QUBO for the core. Return on/off lists, best first.
        return my_algorithm(reduced)

QUANTUM_SOLVERS["my_quantum"] = MyQuantumSolver   # now usable in --solvers

The zoo's speedups describe how each algorithm scales on very large versions of its own problem. None was measured on this benchmark.


Study areas and region packages

The Kensington (London) study area ships inside the package and works offline. Any other area can be downloaded from OpenStreetMap by name or by bounding box:

qellaris region kreuzberg --place "Kreuzberg, Berlin" --radius-km 1.0
qellaris region nottingham --bbox 52.938,-1.172,52.966,-1.125
qellaris benchmark --geography workspace/regions/kreuzberg

A download saves streets, land use, building footprints and mapped masts, plus a manifest counting what arrived, so an empty layer is visible rather than silent. Areas wider than 12 km are refused before any request is made.

Downloads take minutes, so a finished area can be passed on as a single region package:

qellaris region-pack list                              # what you have, and whether it is complete
qellaris region-pack export kreuzberg -o kreuzberg.zip
qellaris region-pack import kreuzberg.zip              # on another machine

Importing accepts only the known map-layer files, refuses paths that would land outside the regions folder, and never runs anything inside the package. The dashboard's Study area page offers the same three actions with buttons.

The map shapes the simulation: the land use found in the area sets the mix of residents, commuters, students and visitors, and decides which demand events are possible. An area with no stadium gets no match day.


How a schedule is scored

Energy uses the EARTH base-station power model (Auer et al., 2011). Each transceiver chain draws 130 W when awake and idle, plus 4.7 W for every watt radiated (up to 20 W), and 75 W asleep. A 2x2 MIMO sector therefore draws 260 W idle, 448 W at full load and 150 W asleep. A sleeping sector is not free, and that is counted.

Each schedule is scored by:

  • routing demand to awake sectors with a capacity-limited maximum flow;
  • totalling energy in watt-hours, load-dependent;
  • adding a price for unserved demand (550 Wh per unit), a larger price for falling below 95% service in critical areas such as hospitals (1,100 Wh), and a small price per sector switched on or off (1.375 Wh).

Lower is better. The prices are policy choices, stated openly, not measurements. Each person's service comes from the same flow calculation, so the dashboard's "people served" always matches the solver's "demand served".


Fair comparisons

  • Paired seeds. Within a seed every solver faces exactly the same people and demand, so differences are measured seed by seed. That removes the large seed-to-seed variation that would otherwise hide real differences. --seeds reports bootstrap confidence intervals for each paired difference.
  • Held-out events. A demand spike the forecaster never saw runs beside an identical run without it, so you can see where robustness breaks.
  • Separate regimes. Service is reported separately for quiet periods and the event, so an overloaded event cell cannot hide differences elsewhere.
  • Switching and equity are reported next to energy, so a saving cannot hide as constant sector flapping or as one neglected group.
  • Honest proofs. exact reports proven_optimal per interval rather than implying a proof it ran out of time to finish.

Equity

Fairness is built into the allocation and the audit, not added as a chart at the end. Critical areas (healthcare, for example) get a 95% service floor. When capacity runs short inside an area, people with more constraints are served first. The audit reports demand-weighted service gaps across synthetic groups and attributes each gap to either the network or the energy-saving schedule.

qellaris equity compares twelve named fairness rules on one identical population, from neutral (no one prioritised) through headcount and volume_first to maximum_protection.

All attributes are synthetic scenario variables, not data about real people. Gender, ethnicity and language are not modelled. Income band is recorded for audit only and never changes behaviour.


Data, licences and limits

  • Code: MIT licence.
  • Bundled Kensington map: © OpenStreetMap contributors, Open Database Licence (ODbL). Downloaded areas carry the same attribution.
  • Optional datasets: OpenCellID (needs a free key) for approximate cell sites; JRC NetBravo (DOI 10.2905/JRC.YA8MHB0) for observed signal strength, used only to calibrate, never relabelled as observed demand.
  • Synthetic by design: demand, people, demographics, sector capacities, directions and bands are modelled unless you supply a real inventory. Do not describe results as observed operator traffic.
  • Single operator: the benchmark models one network; there is no competition between operators.
  • Not a placement tool: tower positions and sector directions are inputs (automatic or your JSON file), not something the benchmark optimises.

The test suite ships inside the package as qellaris.tests.

Metadata

Release files for qellaris 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for qellaris 0.5.0
File Size Uploaded Provenance
qellaris-0.5.0.tar.gz 2.0 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for qellaris 0.5.0
File Interpreter ABI Platform
qellaris-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 3.9 MB

Release files / qellaris-0.5.0.tar.gz

Download URL qellaris-0.5.0.tar.gz
Size 2.0 MB
Tags Source
SHA-256 checksum
How to use checksums
00103a6037f77bda915fbd3a3e6ce1ed79b1357aff9d2105cf0f02c1bb18760a
BLAKE2b-256 checksum
How to use checksums
0b977d19ce0360e274b0a329f6485b500cfe8faac7524756d63ebb7ac59b9e69
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / qellaris-0.5.0-py3-none-any.whl

Download URL qellaris-0.5.0-py3-none-any.whl
Size 1.9 MB
Tags Python 3
SHA-256 checksum
How to use checksums
193d87a0ab53187d41770ea58c984595c571eee4d94ae6ab3092e8824fd7b306
BLAKE2b-256 checksum
How to use checksums
5931187a5ba0e63508f5c0edbad4313540023848bc42b54cf170e8fa2f081750
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Security for qellaris 0.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page