Python-code bij Welke coalities zijn mogelijk?

Onderstaande code is ook als Jupyter Python Notebook te downloaden.

ToeliChting op het proGramMa

Van belang zijn de volgende variabelen:

  • regel 5: $VERBOSE$ wordt gebruikt t.b.v. hoeveelheid informatie. Als $VERBOSE = 3$, dan wordt informatie per tussenstap gegeven, als $VERBOSE = 2$, dan wordt de invoer ook volledig weergegeven, als $VERBOSE = 1$, dan wordt alleen de uitslag weergegeven. $VERBOSE = 0$ wordt gebruikt om de uitvoer te gebruiken als invoer van het programma Coalities, dat de volgende keer zal worden behandeld.
  • regel 6: $KZ$ aantal Kamerzetels. Bij andere verkiezingen kun je dit getal vervangen door het aantal zetels dat bij die verkiezingen te verdelen is. Eerste Kamer : 75 zetels, Europese verkiezingen : 26 zetels. Bij andere verkiezingen kan het aantal zetels nogal variëren.
  • regel 7: $K$ aantal Kiesgerechtigden.
  • regel 8: $N$ aantal Kiesgerechtigden dat niet is gaan stemmen (Niet opgekomen).
  • regel 9: $O$ aantal Kiesgerechtigden dat daadwerkelijk is gaan stemmen (Opkomst). Er geldt uiteraard dat $O + N = K$.
  • regel 10: $X$ aantal Ongeldige stemmen.
  • regel 11: $B$ aantal Blanco stemmen.
  • regel 12: $G$ aantal Geldige stemmen. Er geldt dat $X + B + G = O$.
  • regel 24: $S$. Dit is een verzameling waarin per partij het aantal stemmen en de namen van de partijen worden opgesomd. Er moet gelden dat de som van de stemmen voor alle partijen moet sommeren tot $G$.
  • regel 29: $V$. In $V$ komt de berekening te staan voor de Restzetels. In $V[p][0]$ komt het quotiënt te staan van het aantal stemmen voor partij $p$ gedeeld door het aantal zetels + 1. Door te sorteren (met $reverse = True$) komt de partij die een extra restzetel krijgt bovenaan te staan. In $V[p][1]$ staat het aantal toegewezen zetels. In $V[p][2]$ staat het aantal stemmen op partij $p$, en ten slotte staat in $V[p][3]$ de naam van de partij.
  • regel 30: $R$ bevat een lijst van partijen die een restzetel kregen.
  • regel 34: $KD$ Kiesdeler. Er geldt dat $KD = G / KZ$.
  • regel 45: $Vs$. Dit is hetzelfde als $V$, maar dan gesorteerd, zodat bovenaan de partij staat die een extra restzetel krijgt.
  • regel 60: $U$. Dit is uitvoer t.b.v. het programma $Coalities$ dat de volgende keer wordt behandeld.

Een theoretisCh voOrbEeld

Een theoretisch voorbeeld
import math
VERBOSE = 2  # Bij 3 worden ook de tussenresultaten getoond, bij 2 de invoer,
             # Bij 1 alleen de uitvoer. Bij 0 de variabele U, t.b.v. het programma
             # Coalities (wordt in het volgende nummer behandeld).
KZ = 150     # Kamerzetels
K = 18000000 # Kiesgerechtigden
N = 2000000  # Niet opgekomen
O = 16000000 # Opkomst
X = 500000   # Ongeldige stemmen
B = 500000   # Blanco stemmen
G = 15000000 # Geldige stemmen
if VERBOSE > 1:
    print("Statistieken")
    print("Kamerzetels:", KZ)
    print("Kiesgerechtigden:", K)
    print("Niet opgekomen:", N)
    print("Opkomst:", K - N)
    print("Ongeldige stemmen:", X)
    print("Blanco stemmen:", B)
    print("Geldige stemmen:", K - N - B - X)

S = [(10761000, "Partij A"),
     (2862000, "Partij B"),
     (1377000, "Partij C")]

sum = 0
V = []
R = []
for s in S:
    sum += s[0]
    V.append([0,0,s[0],s[1]])
KD = round(sum/KZ)
if VERBOSE > 1:
    print("Kiesdeler:", KD)
zsum = 0
for v in V:
    v[1] = math.floor(v[2]/KD)
    zsum += v[1]
    if v[1] == 0:
        v[0] = 0
    else:
        v[0] = round(v[2]/(v[1]+1),2)
Vs = sorted(V, reverse = True)
cnt = 0
if VERBOSE > 2:
    for v in Vs:
        print(v)
while KZ-zsum > 0:
    v = Vs[0]
    zsum += 1
    v[1] = v[1] + 1
    v[0] = round(v[2]/v[1],2)
    cnt += 1
    if VERBOSE > 1:
        print(cnt, v)
    R.append(v[3])
    Vs = sorted(V, reverse = True)

U = []
for v in V:
    U.append((v[1],v[3]))
U.sort()
if VERBOSE > 0:
    print("Restzetels:", len(R))
    print("Toegewezen aan:", R)
    print("Zetelverdeling:")
for i in range(len(U)):
    u = U[len(U)-i-1]
    if u[0] > 0:
        if VERBOSE > 0:
            print(u[1], ":", u[0])

VerkieziNgen 2017, 2021 en 2023

# Verkiezingen 2017 en 2021

import math

VERBOSE = 2 # Bij 3 worden ook de tussenresultaten getoond, bij 2 de invoer,
            # Bij 1 alleen de uitvoer. Bij 0 de variabele U, t.b.v. het programma
            # Coalities (wordt in het volgende nummer behandeld).
J = 2017    # Keuze 2017, 2021 of 2023 (na 1 december 2023)

if J == 2017:
    KZ = 150      # Kamerzetels
    K = 12950685  # Kiesgerechtigden
    N = 2387229   # Niet opgekomen
    O = 10563456  # Opkomst
    X = 31539     # Ongeldige stemmen
    B = 15876     # Blanco stemmen
    G = 10516041  # Geldige stemmen
if J == 2021:
    KZ = 150      # Kamerzetels
    K = 13187770  # Kiesgerechtigden
    N = 2725093   # Niet opgekomen
    O = 10462677  # Opkomst
    X = 22652     # Ongeldige stemmen
    B = 17173     # Blanco stemmen
    G = 10422852  # Geldige stemmen
if J == 2023:
    KZ = 150      # Kamerzetels
    # Waarden hieronder worden aangepast nadat de uitslag van de verkiezingen
    # is vastgesteld. Prognose: 28 november 2023
    K = 13187770  # Kiesgerechtigden
    N = 2725093   # Niet opgekomen
    O = 10462677  # Opkomst
    X = 22652     # Ongeldige stemmen
    B = 17173     # Blanco stemmen
    G = 10422852  # Geldige stemmen

print("Jaar: ", J)
print("Statistieken")
print("Kamerzetels:", KZ)
print("Kiesgerechtigden:", K)
print("Niet opgekomen:", N)
print("Opkomst:", K - N)
print("Ongeldige stemmen:", X)
print("Blanco stemmen:", B)
print("Geldige stemmen:", K - N - B - X)

S2017 = [(2238351, "VVD"),
         (1372941, "PVV"),
         (1301796, "CDA"),
         (1285819, "D66"),
         (959600, "GroenLinks"),
         (955633, "SP"),
         (599699, "PvdA"),
         (356271, "ChristenUnie"),
         (335214, "PvdD"),
         (327131, "50Plus"),
         (218950, "SGP"),
         (216147, "DENK"),
         (187162, "FvD"),
         (38209, "VoorNederland"),
         (35478, "Piratenpartij"),
         (28700, "Artikel 1"),
         (14362, "Nieuwe Wegen"),
         (12570, "OndernemersPartij"),
         (6858, "Lokaal in de Kamer"),
         (6025, "Niet Stemmers"),
         (5221, "De Burger Beweging"),
         (4945, "GeenPeil"),
         (3099, "Jezus Leeft"),
         (2938, "Vrijzinnige Partij"),
         (1492, "Libertarische Partij"),
         (726, "MenS"),
         (527, "StemNL"),
         (177, "Vrije Democratische Partij")]
S2021 = [(2279130, "VVD"),
         (1565861, "D66"),
         (1124482, "PVV"),
         (990601, "CDA"),
         (623371, "SP"),
         (597192, "PvdA"),
         (537308, "GroenLinks"),
         (523083, "FvD"),
         (399750, "PvdD"),
         (351275, "ChristenUnie"),
         (252480, "Volt"),
         (246620, "JA21"),
         (215249, "SGP"),
         (211237, "DENK"),
         (106702, "50Plus"),
         (104319, "BBB"),
         (87238, "Bij1"),
         (40731, "Code Oranje"),
         (33834, "Nida"),
         (30328, "Splinter"),
         (22816, "Piratenpartij"),
         (15297, "Jong"),
         (13198, "Trots"),
         (9264, "Lijst Henk Krol"),
         (8657, "NLBeter"),
         (8277, "Blanco Lijst"),
         (5546, "LP"),
         (5449, "Oprecht"),
         (5015, "Jezus Leeft"),
         (3744, "DFP"),
         (1880, "U-Buntu Connected Front"),
         (942, "Vrij en Sociaal Nederland"),
         (804, "Partij van de Eenheid"),
         (553, "Wij zijn Nederland"),
         (255, "Partij voor de Republiek"),
         (245, "Modern Nederland"),
         (119, "De Groenen")]
S2023 = [(2279130, "VVD"),
         (1565861, "D66"),
         (1124482, "PVV"),
         (990601, "CDA"),
         (623371, "SP"),
         (597192, "GL/PvdA"),
         (523083, "FvD"),
         (399750, "PvdD"),
         (351275, "ChristenUnie"),
         (252480, "Volt"),
         (246620, "JA21"),
         (215249, "SGP"),
         (211237, "DENK"),
         (106702, "50Plus"),
         (104319, "BBB"),
         (87238, "Bij1"),
         (40731, "Code Oranje"),
         (33834, "Nida"),
         (30328, "Splinter"),
         (22816, "Piratenpartij"),
         (15297, "Jong"),
         (13198, "Trots"),
         (9264, "Lijst Henk Krol"),
         (8657, "NLBeter"),
         (8277, "Blanco Lijst"),
         (5546, "LP"),
         (5449, "Oprecht"),
         (5015, "Jezus Leeft"),
         (3744, "DFP"),
         (1880, "U-Buntu Connected Front"),
         (942, "Vrij en Sociaal Nederland"),
         (804, "Partij van de Eenheid"),
         (553, "Wij zijn Nederland"),
         (255, "Partij voor de Republiek"),
         (245, "Modern Nederland"),
         (119, "De Groenen")]
if J == 2017:
    S = S2017
if J == 2021:
    S = S2021
if J == 2023:
    S = S2023
sum = 0
V = []
R = []
for s in S:
    sum += s[0]
    V.append([0,0,s[0],s[1]])
KD = round(sum/KZ)
print("Kiesdeler:", KD)
zsum = 0
for v in V:
    v[1] = math.floor(v[2]/KD)
    zsum += v[1]
    if v[1] == 0:
        v[0] = 0
    else:
        v[0] = -round(v[2]/(v[1]+1),2)
V.sort()
cnt = 0
if VERBOSE > 0:
    for v in V:
        print(v)
while KZ-zsum > 0:
    v = V[0]
    zsum += 1
    v[1] = v[1] + 1
    v[0] = -round(v[2]/(v[1]+1),2)
    cnt += 1
    if VERBOSE > 1:
        print(cnt, v)
    R.append(v[3])
    V.sort()
U = []
for v in V:
    U.append((v[1],v[3]))
U.sort()
print("Restzetels:", len(R))
print("Toegewezen aan:", R)
print("Zetelverdeling:")
for i in range(len(U)):
    u = U[len(U)-i-1]
    if u[0] > 0:
        print(u[1], ":", u[0])
for s in S:
    # De onderstaande uitvoer kan m.b.v. LaTeX bekeken worden
    print("{} & {} & {} & {} & {} \\\\".format(s[1],s[0],round(s[0]/KD,3), s[0]//KD, round(s[0]/KD)))

Aantal Coalities dat mogelijk is

#Aantal coalities dat mogelijk is
# Er is een coalitie van partijen A, B, ..., N als deze partijen minimaal 76 zetels
# hebben in de tweede kamer en als bovendien als 1 van de partijen niet deelneemt aan de
# coalitie het aantal zetels onder de 76 uitkomt.
# vervolg op voorafgaande programma
V = []
for u in U:
    if u[0] > 0:
        V.append(u)
V.sort(reverse = True)
lv = len(V)
print(lv)
kv = 1
Coalities = []
for v in V:
    print(v)
    kv *= 2
for k in range(kv):
    j = k
    sum = 0
    last = 0
    cnt = 0
    c = 0
    L = ""
    while j > 0:
        if j % 2 == 1:
            #print(j,V[cnt])
            L = L + V[cnt][1] + " "
            c += 1
            last = V[cnt][0]
            sum += last
        cnt += 1
        j = j // 2
    if (sum >= 76) & (sum-last < 76):
        lc = len(Coalities)
        L = str(lc+1) + ": P" + str(c) + ": " + L + ": Z" + str(sum)
        Coalities.append(L)
for c in Coalities:
    print(c)
print(len(Coalities))
print("Ready")