Das Problem
Für ein privates Projekt bin ich auf die Herausforderung gestoßen, aus einer gegebenen Liste von Mannschaften einen Spielplan zu erstellen. Das klingt zunächst extrem trivial, hat sich aber schnell als durchaus spannend herausgestellt.
Die Liste der Mannschaften liegt als Liste von Vereins-IDs vor. Das kann ja eigentlich nicht so kompliziert sein – man bestimmt einfach über eine simple verschachtelte for-Schleife alle Kombinationsmöglichkeiten der Listeneinträge und hat das Problem gelöst. Interessant wurde es erst, als ich mir die so generierten Paare genauer angeschaut habe. Dabei waren mehrere Randbedingungen verletzt, die ich implizit vorausgesetzt hatte.
Die Randbedingungen
A. Eine Mannschaft soll an jedem Spieltag nur höchstens einmal spielen.
Die einfache verschachtelte for-Schleife führt durch die beiden Laufvariablen zwangsläufig dazu, dass an jedem Spieltag entweder die Heimmannschaft oder die Gastmannschaft mehrere Spiele zu absolvieren hat. Das ist in der praktischen Anwendung nicht sinnvoll, keine Mannschaft kann mehr als ein Spiel an einem Spieltag spielen. Es ist daher zwingend notwendig, die Paarungen passend über alle Spieltage zu verteilen.
B. Nach möglichst wenigen Spieltagen soll jede Mannschaft gegen jede andere Mannschaft gespielt haben.
Diese Bedingung erfüllt auch die einfache Schleife (wenn auch in einer unbrauchbaren Reihenfolge). Am Ende der Saison soll jede denkbare Paarung zweimal stattgefunden haben. Dabei soll die Saison so kurz wie möglich gehalten werden, d.h. die Anzahl der Spieltage soll nicht größer sein als unbedingt notwendig um alle anderen Bedingungen zu erfüllen. Daraus ergibt sich, dass etwa bei 18 Mannschaften nur 2×17 Spieltage generiert werden sollen.
C. Heim- und Auswärtsspiele sollen sich idealerweise abwechseln.
Jede Mannschaft soll im Verlauf der Saison gleich viele Heim- und Auswärtsspiele haben. Dabei sollen sich Heim- und Auswärtsspiele abwechseln, so dass auf ein Heimspiel immer ein Auswärtsspiel folgt. Dieses Problem ist nicht ideal lösbar.
Die Lösung
Nach einer anregenden Diskussion mit zwei Kollegen stand schnell fest, dass die Berechnung eines solchen „idealen“ Spielplans nicht so trivial ist wie zunächst gedacht.
Nachdem eine Kollegin mich mit den Stichworten „Graph“ und „Kantenfärbung“ in die richtige Richtung geschubst hatte, konnte ich die mathematischen Hintergründe und die Lösung für das Problem auf einer Seite der RWTH Aachen finden. Dort wird das „Spielplan-Problem“ mithilfe eines Kantenfärbungs-Algorithmus gelöst.
In der Linkliste dieses Artikels war außerdem eine Implementierung dieses Algorithmus in PHP von Andy Theiler zu finden. Andy Theiler hat seine Implementierung dankenswerterweise unter eine freie BSD-Lizenz gestellt, so dass ich seinen Code für meine Bedürfnisse anpassen und nach C++/Qt portieren konnte.
Diese angepasste Portierung stelle ich unter gleicher Lizenz bei Github zur Verfügung.