Was bedeutet Macht?
Unter Macht verstehen wir den Einfluss auf das Ergebnis von Abstimmungen. Diese Vorstellung von Macht bezeichnen wir auch als Abstimmungsmacht.
- Mehr Stimmen bedeuten mehr Abstimmungsmacht.
- Erhält man nach einer Wahl mehr Stimmen als man vorher hatte, so steigt die Macht. Bleibt die Stimmenanzahl vor und nach der Wahl gleich, ändert sich die Abstimmungsmacht nicht. Ansonsten sinkt die Abstimmungsmacht.
- Mitglieder \(m_i\) einer Fraktion \(F\) können insgesamt nicht mehr Abstimmungsmacht besitzen als die Fraktion selbst, d.h. die Summe aller Abstimmungsmächte aller \(m_i\in F\) entspricht (exakt) der Abstimmungsmacht von \(F\).
- Beteiligen sich weitere Spieler und Fraktionen an dem Abstimmungsspiel, so sinkt die Macht im Allgemeinen.
- Feinden sich die Fraktionen \(F_1\) und \(F_2\) derart an, dass sie nicht bereit sind eine Koalition \(K = \{F_1,F_2\}\) einzugehen, sinkt die Abstimmungsmacht von \(F_1\) und \(F_2\).
Fraktionen, Koalitionen, Quorum
Um zu verstehen, wie Koalitionsbildung von Fraktionen, Stimmen und Quoren (Plural von Quorum) zusammenhängen, müssen wir diese Begriffe zunächst definieren:
Wir nehmen für unsere Überlegungen an, dass in einer Abstimmung alle Mitglieder einer Fraktion einstimmig entscheiden.
- Einfache Mehrheit: $$\sum_{i\in I}{s_i\gt \underbrace{0.5s}_{Q_{\gt 0.5}}}$$
- \(\frac{2}{3}\) Mehrheit: $$\sum_{i\in I}{s_i\geq \underbrace{\frac{2}{3}s}_{Q_{\geq\frac{2}{3}}}}$$
Die Abstimmung
- \(K\setminus\{F\}\) bleibt weiterhin eine gewinnende Koalition.
- \(K\setminus\{F\}\) ist nun eine verlierende Koalition.
- \(F_i\in K\)
- \(K\) ist eine gewinnende Koalition.
- \(K\setminus\{F_i\}\) ist eine verlierende Koalition.
Wir berechnen abschließend die Banzhaf-Indizes für unser Abstimmungsbeispiel mit den Fraktionen \(F_1, F_2\) und \(F_3\). Die Anzahl der gewinnenden Koalitionen, die wir bereits tabellarisch erfasst haben, genügt für die Berechnung der Banzhaf-Macht nicht, da eine Fraktion innerhalb einer gewinnenden Koalition nicht automatisch kritisch ist. Aus diesem Grund listen wir für jede Fraktion auf, für welche gewinnenden Koalitionen sie kritisch sind.
Python-Programm zur Simulation einer Wahl
Wir können uns nun ein kleines Simulationsprogramm in Python schreiben, mit dem man dieses mathematische Machtmodell auf reale Situationen anwenden und somit die "Abstimmungsmacht" (nach Banzhaf) für die an der Wahl beteiligten Parteien ermitteln kann.
Zuerst wird der Import itertools benötigt, der beim Berechnen der Potenzmenge aller Fraktionen (also zum Ermitteln der Koalitionen) verwendet wird.
import itertools
Als erstes schreiben wir uns eine kleine Fraktionsklasse. Diese erhält im Konstruktor einen Namen und eine Anzahl an Stimmen, die maßgeblich über die tatsächliche Abstimmungsmacht mitentscheidet. Diese Werte weisen wir entsprechenden Objektvariablen zu. Zusätzlich definieren wir noch je eine Objektvariable für die Banzhaf-Macht und den Banzhaf-Index. Beide Objektvariablen werden mit dem Startwert 0 initialisiert.
class Fraktion: def __init__(self, name, stimmen): self.name = name self.stimmen = stimmen self.banzhaf_macht = 0 self.banzhaf_index = 0
Nun werden für die Objektvariablen entsprechende Getter-Methoden implementiert, also get_name, get_stimmen, get_banzhaf_macht und get_banzhaf_index.
def get_name(self): return self.name def get_stimmen(self): return self.stimmen def get_banzhaf_macht(self): return self.banzhaf_macht def get_banzhaf_index(self): return self.banzhaf_index
Zudem definieren wir eine Methode ist_kritisch, die den Wert der Banzhaf-Macht um 1 erhöht. Diese Methode wird auf einer Fraktion aufgerufen, wenn das Wegbleiben der Stimmen dieser Fraktion innerhalb einer gewinnenden Koalition dafür sorgt, dass diese Koalition dann verlierend ist.
def ist_kritisch(self): self.banzhaf_macht += 1
Zum Schluss wird eine Methode berechne_banzhaf_index implementiert, die für eine Fraktion den Banzhaf-Index berechnet. Dazu wird als Parameter die Summe aller Banzhaf-Mächte n übergeben. Der Banzhaf-Index berechnet sich dann durch den Quotienten der Banzhaf-Macht und der Summe aller Banzhaf-Mächte n.
def berechne_banzhaf_index(self, n): self.banzhaf_index = self.banzhaf_macht/n
Als nächstes definieren wir eine Klasse Koalition. Da eine Koalition ein Zusammenschluss von Fraktionen ist, wird im Konstruktor eine Liste von Fraktionen übergeben und diese einer Objektvariable zugewiesen. Zudem wird eine Objektvariable stimmen definiert, die anfangs auf 0 gesetzt wird. In einer For-Schleife wird über alle Fraktionen innerhalb der Koalition iteriert und die Stimmen addiert. Die Anzahl der Stimmen einer Koalition ergibt sich schließlich als Summe der Stimmen aller darin enthaltenen Fraktionen.
class Koalition: def __init__(self, fraktionen): self.fraktionen = fraktionen self.stimmen = 0 for fraktion in self.fraktionen: self.stimmen += fraktion.get_stimmen()
Für die Objektvariablen fraktionen und stimmen werden nun entsprechende Getter-Methoden vorgesehen.
def get_stimmen(self): return self.stimmen def get_fraktionen(self): return self.fraktionen
Zusätzlich gibt es eine Funktion kritische_fraktionen, die diejenigen Fraktionen innerhalb der Koalition ermittelt, die gemäß unserer Definition kritisch sind. Dazu wird über alle Fraktionen in der Koalition iteriert und geprüft, ob die Anzahl der Stimmen in der Koalition nicht mehr ausreicht, wenn man von der Gesamtanzahl an Stimmen die der jeweiligen Fraktion entfernt. Wenn das der Fall ist, wird die Funktion ist_kritisch auf der entsprechenden Fraktion ausgerufen, welche die Banzhaf-Macht der Fraktion um 1 erhöht. Dementsprechend muss der Methode das Quorum, gegen das geprüft werden soll, als Parameter übergeben werden.
def kritische_fraktionen(self, quorum): for fraktion in self.fraktionen: if self.get_stimmen() - fraktion.get_stimmen() < quorum: fraktion.ist_kritisch()
Zum Schluss definieren wir noch eine Methode ist_gewinnend, mit der entschieden werden kann, ob abhängig von einem bestimmten Quorum, eine Koalition gewinnend ist. Das wird gemacht, indem man prüft, ob die Stimmen der Koalition das Quorum erreichen.
def ist_gewinnend(self, quorum): return self.stimmen >= quorum
Zum Schluss definieren wir noch eine Klasse Abstimmung. Diese erhält im Konstruktor ein Quorum und eine Liste mit Fraktionen, die an einer Abstimmung teilnehmen. Diese werden entsprechenden Objektvariablen zugewiesen. Zudem definieren wir zwei Objektvariablen koalitionen und gewinnend in Form einer leeren Liste, die einmal alle möglichen Koalitionen speichern und diejenigen, die gewinnend gemäß unserer Definition sind. Im Konstruktor wird die Liste mit den möglichen Koalitionen direkt gefüllt, indem wir zuerst die Potenzmenge der übergebenen Fraktionen berechnen und die Ergebnisse dann nacheinander einfügen. Wichtig ist, dass innerhalb dieser Liste Koalitionen stehen, d.h. wir erzeugen in jedem Schleifendurchlauf ein Koalitionsobjekt, das als Übergabeparameter eine Liste mit den Fraktionen erhält.
class Abstimmung: def __init__(self, quorum, *fraktionen): self.fraktionen = fraktionen self.quorum = quorum self.koalitionen = [] self.gewinnend = [] potenzmenge = [x for length in range(len(self.fraktionen)+1) for x in itertools.combinations(self.fraktionen, length)] for fraktion in potenzmenge: self.koalitionen.append(Koalition(list(fraktion)))
Als nächstes schreiben wir uns eine Methode gewinnende_koalitionen, die alle gewinnenden Koalitionen berechnet und somit die Objektvariable gewinnend füllt. Das wird getan, indem wir über alle ermittelten Koalitionen iterieren und die Koalition in die Liste der gewinnenden Koalitionen eintragen, wenn sie gewinnend ist. Um dies entscheiden zu können, verwenden wir die zuvor in der Klasse Koalition implementierte Methode ist_gewinnend.
def gewinnende_koalitionen(self): for koalition in self.koalitionen: if koalition.ist_gewinnend(self.quorum): self.gewinnend.append(koalition)
Diese Methode kann nun auch im Konstruktor aufgerufen werden.
Als nächstes schreiben wir eine Methode kritische_fraktionen, die für alle gewinnenden Koalitionen die kritischen Fraktionen berechnet und somit das Quorum an die Koalitions-Instanzen weiterreicht. Es wird einfach nur in einer For-Schleife über die gewinnenden Koalitionen iteriert und auf den Koalitions-Instanzen die Methode kritische_fraktionen aufgerufen, der das Quorum übergeben wird.
def kritische_fraktionen(self): for koalition in self.gewinnend: koalition.kritische_fraktionen(self.quorum)
Nun wird eine Methode geschrieben, mit der die Berechnung der Banzhaf-Indizes der Fraktionen getriggert werden kann. Da in der Abstimmung alle Koalitionen und Fraktionen vorhanden sind und die Fraktionen nichts voneinander wissen, braucht es diese Methode, um den Nenner des Bruchs zur Berechnung der Banzhaf-Indizes zu ermitteln. Zuerst wird dieser Nenner n mit dem Wert 0 initialisiert. Anschließend wird in einer For-Schleife über alle Fraktionen iteriert und die Banzhaf-Mächte der Fraktionen addiert. Danach wird erneut in einer For-Schleife jede Fraktion durchlaufen und die Methode berechne_banzhaf_index aufgerufen, der der zuvor ermittelte Nenner übergeben wird.
def berechne_banzhaf_indizes(self): n = 0 for fraktion in self.fraktionen: n += fraktion.get_banzhaf_macht() for fraktion in self.fraktionen: fraktion.berechne_banzhaf_index(n)
Abschließend schreiben wir eine Funktion simulieren, die nacheinander die kritischen Fraktionen und die Banzhaf-Indizes berechnet und die Ergebnisse übersichtlich ausgibt.
def simulieren(self): self.kritische_fraktionen() self.berechne_banzhaf_indizes() for fraktion in self.fraktionen: print(fraktion.get_name() + " - " + str(fraktion.get_banzhaf_index()))
Mit den Daten des Bundeswahlleiters kannst du die mathematische Machtverteilung in dem Koalitionsspiel der Bundestagswahl 2017 ermitteln. Dazu definierst du zunächst Fraktionsobjekte für alle an der Wahl beteiligten Parteien mit den entsprechenden Sitzanteilen im Bundestag. Danach instantiierst du ein Abstimmungsobjekt, dem du als Quorum 355 übergibst, da insgesamt 709 Sitze vergeben wurden und eine absolute Mehrheit erforderlich ist. Zusätzlich übergibst du die an der Wahl beteiligten Fraktionen bzw. Parteien (die Parteien, die es nicht über die 5%-Hürde geschafft haben, bleiben an dieser Stelle unbeachtet). Durch einen Aufruf der Methode simulieren auf dem Abstimmungsobjekt kannst du die Bundestagswahl 2017 simulieren bzw. die mathematische Macht der einzelnen Fraktionen ermitteln. Als Ergebnis erhältst du die folgende Übersicht:
CDU - 0.2903225806451613 SPD - 0.1935483870967742 AFD - 0.16129032258064516 FDP - 0.0967741935483871 Die Linke - 0.0967741935483871 Grüne - 0.0967741935483871 CSU - 0.06451612903225806
Dieses Programm kannst du für alle möglichen Koalitionsspiele anwenden. Ein für uns interessantes Koalitionsspiel wird wieder im Jahr 2021 gespielt.
Quellcode
Der gesamte Quellcode des Python-Simulationsprogramms kann hier heruntergeladen werden.
import itertools class Fraktion: def __init__(self, name, stimmen): self.name = name self.stimmen = stimmen self.banzhaf_macht = 0 self.banzhaf_index = 0 def get_name(self): return self.name def get_stimmen(self): return self.stimmen def get_banzhaf_macht(self): return self.banzhaf_macht def get_banzhaf_index(self): return self.banzhaf_index def ist_kritisch(self): self.banzhaf_macht += 1 def berechne_banzhaf_index(self, n): self.banzhaf_index = self.banzhaf_macht/n class Koalition: def __init__(self, fraktionen): self.fraktionen = fraktionen self.stimmen = 0 for fraktion in self.fraktionen: self.stimmen += fraktion.get_stimmen() def get_stimmen(self): return self.stimmen def get_fraktionen(self): return self.fraktionen def kritische_fraktionen(self, quorum): for fraktion in self.fraktionen: if self.get_stimmen() - fraktion.get_stimmen() < quorum: fraktion.ist_kritisch() def ist_gewinnend(self, quorum): return self.stimmen >= quorum class Abstimmung: def __init__(self, quorum, *fraktionen): self.fraktionen = fraktionen self.quorum = quorum self.koalitionen = [] self.gewinnend = [] potenzmenge = [x for length in range(len(self.fraktionen)+1) for x in itertools.combinations(self.fraktionen, length)] for fraktion in potenzmenge: self.koalitionen.append(Koalition(list(fraktion))) def gewinnende_koalitionen(self): for koalition in self.koalitionen: if koalition.ist_gewinnend(self.quorum): self.gewinnend.append(koalition) def kritische_fraktionen(self): for koalition in self.gewinnend: koalition.kritische_fraktionen(self.quorum) def berechne_banzhaf_indizes(self): n = 0 for fraktion in self.fraktionen: n += fraktion.get_banzhaf_macht() for fraktion in self.fraktionen: fraktion.berechne_banzhaf_index(n) def simulieren(self): self.gewinnende_koalitionen() self.kritische_fraktionen() self.berechne_banzhaf_indizes() for fraktion in self.fraktionen: print(fraktion.get_name() + " - " + str(fraktion.get_banzhaf_index())) cdu = Fraktion("CDU", 200) spd = Fraktion("SPD", 153) afd = Fraktion("AFD", 94) fdp = Fraktion("FDP", 80) linke = Fraktion("Die Linke", 69) gruene = Fraktion("Grüne", 67) csu = Fraktion("CSU", 46) abstimmung = Abstimmung(355, cdu, spd, afd, fdp, linke, gruene, csu) abstimmung.simulieren()