25 February. 38.7 C. Hot dry season in Ouagadougou.
10 566 people
That is how many were left below the WHO survival threshold of 20 litres by the hand-written rulebook, and were not, on the same day, with the same outages, by this agent. 11 113 people against 546. The worst day of the year, and half a city.
One simulated day, hour by hour. Press "Show me the day" and it walks you through the four hours that matter, in about twenty seconds. Then take the hour slider yourself, change the city - the same agent, weights trained on Ouagadougou and unchanged, running under a climate it never saw - or switch the operator to the rulebook and replay the same day without learning.
And set Demand to school + clinic +30%. The district drinks a third more than the forecast announced - an epidemic at the dispensary, a school reopening - and nothing tells the agent: its input carries the shape of the usual profile, not the litres actually drawn. At 1 p.m. its tank sits 13 points lower than it planned for, and the taps still do not run dry.
Every scenario here was played in Python by the trained model and written into this page. The browser replays them - there is no model running in this tab, and saying otherwise would be a lie you could not check.
Everything above is one station with one set of constraints. Yours are different, and the honest question is not "is this impressive" but "would it do anything for me". Three constraints were swept independently, so pick the one that actually binds at your station and read the answer off a measurement rather than off a promise.
Each axis was swept on its own, holding everything else at the values this repository publishes. The combinations are not measured, so the tool answers one question at a time and says which campaign each answer comes from. Turning three sliders at once and reading the corner would be inventing a number, and this page does not do that.
That console had three pumps, three tanks, three districts and three sources of power behind it, with a grid that goes out. Here is the whole machine on one page: what the agent is allowed to see, what it decides, and the two actions that touch no pump at all.
In the language of the field: a reinforcement-learning agent schedules three district pumps against a failing grid, on a simulator calibrated on three years of measured daily records. Solar first, always.
And the object is not really water. It is operating an essential service on infrastructure that cannot be relied on. Swap the tank for a vaccine fridge, a rural health battery or a motorbike charging point, and the same four horizons have to be held together by the same hour-by-hour decision. Water is simply where we could measure it.
Judging this? GRILLE-JURY.md in the repository
maps each of the five criteria to its number and the one place that proves it.
Everything below is regenerated by a command - no figure is typed by hand.
Beating current practice is easy. Beating somebody who reads the same outage forecast is not - and that is the row that decides whether learning earned its place here.
Ouagadougou does not have one water problem. It has three.
April: 39.8 °C. Demand is up a quarter and the grid fails every evening - but the sky is clear, so the tank-as-battery works.
August: 30.1 °C and 8.7 mm of rain a day. Demand falls, and so does the sunshine the battery depends on.
The two seasons want opposite policies. That is why no fixed setting holds both.
The agent can broadcast one message: fill your jerrycans, the power is about to go. In Europe this action would be meaningless - nobody stores water at home. Here every household has containers, and one sentence at 5 p.m. moves more water than an hour of diesel.
It is not a free button.
Warning moves demand forward. It does not remove it. The tank is under more strain in the following hour, less during the cut, and the day's volume is conserved exactly.
And a false alarm costs no fuel and no money. It costs being listened to. A correct warning buys +0.04 of the city's trust; a false one costs -0.15.
That asymmetry alone fixes a break-even accuracy of 78.9 %. No penalty term forbids chatter - it is simply a losing bet, and the agent has to work that out.
Scalable is a word everyone writes and nobody measures. Here it means one thing: the weights trained on Ouagadougou, replayed unchanged on climates that were not in training, against the same hand-written rule. Twelve temperatures, twelve solar sums and twelve rainfall figures are replaced - everything the model knows about geography - and we look.
The simulator is a digital twin of the network: tanks, pumps, sources, a failing grid, and demand that follows heat and holidays - calibrated on three years of measured daily records.
You do not connect an agent to a city's water supply without one.
But a twin is useful on its own. It answers capital questions before anyone pours anything, so we asked the one a utility director actually asks:
How much bigger would the tanks have to be for the rulebook to serve the city as well as the agent does with the tanks we already have?
A figure in West African francs reads in Ouagadougou and nowhere else. But converting everything to dollars is the wrong fix: an electricity tariff varies far more between countries than an exchange rate corrects for. So the primary units here are the ones that read everywhere - kilowatt-hours, litres of diesel, kilograms of CO2, and person-days above the WHO survival threshold. Cost is a presentation layer with the local tariff written on it.
This is also the one input the project cannot fetch by itself. Climate comes from Open-Meteo with no key and no account; there is no open, reliable equivalent for city-level electricity tariffs. The figures used are declared orders of magnitude, kept in one file so a utility that knows its real tariff replaces them in a minute - better a number labelled generic than a precise one that is wrong.
Every number on this page comes from a JSON file, and every JSON file comes from a command. Nothing here was typed by hand.
pip install -r requirements.txt python -m wiiga.resultats --journees 365 # the tables above python -m wiiga.graines --journees 365 # three training seeds, mean and spread python -m wiiga.transfert --journees 365 # the city transfer python -m wiiga.equivalence --journees 365 # how much storage the agent replaces python -m wiiga.ville Chennai # plug in any city, no API key python -m wiiga.train --pas 600000 # retrain, ~20 min on a laptop CPU
This page is a single static file with its data written inside it. No server, no serverless function, no network request - it cannot break in front of you because an API changed its mind.