Aller au contenu
Condorcet.vote Alpha
← Documentation technique

Dépouillement & recompte

Le résultat n'est jamais un bloc du registre : c'est un recalcul déterministe, à partir de la configuration publiée et des bulletins signés, que chacun peut rejouer.

Ce qui fait foi, c'est la liste figée des bulletins signés ; le recalcul en est une contre-vérification. Une divergence entre deux implémentations ou deux versions de bibliothèque serait un défaut d'un programme de calcul, pas une faille de vérifiabilité : les bulletins publiés restent inchangés. Toutes les méthodes proposées sont déterministes, le résultat est donc stable pour une liste de bulletins donnée.

Protocole v1

Entrées

Ce que lit le recompte.

Uniquement des données publiques : la configuration gelée (bloc 0), les bulletins (blocs de votes), la liste d'émargement de clôture pour les poids, et la méthode publiée avec le résultat. Le document CEF n'est pas une entrée nécessaire.

candidates[].label chaînes · configuration
Les candidats déclarés, y compris ceux que personne n'a classés. L'étiquette est le seul identifiant de candidat.
election_type preferential | fptp · configuration
Classement (méthodes de Condorcet) ou choix unique (scrutin majoritaire). Fixe aussi la règle de classement implicite.
ballot_rules objet · configuration
Les quatre paramètres de bulletin, dont les contraintes de dépouillement se déduisent par une règle fixe (ci-dessous).
seats entier ≥ 1 · configuration
Le nombre d'élus : les seats premières places du classement.
weighted_voting booléen · configuration
Si vrai, chaque bulletin pèse le poids signé dans sa charge utile ; sinon, chaque bulletin pèse 1.
ballots[].payload chaîne JSON · votes
La charge utile signée : son champ ballot (classement CEF ou /EMPTY_RANKING/) et son champ weight.
electoral_roll[].weight entier ≥ 1 · closure
Le poids autorisé de chaque votant, pour contrôler les poids signés d'une élection pondérée.
méthode nom canonique · résultat
Choisie par l'organisateur, gelée avec la configuration au lancement, publiée avec le résultat et non dans la chaîne. Désignée par son nom exact dans la bibliothèque, par exemple Schulze Winning.
Bulletins

Chaque bulletin publié, une règle mécanique.

Le contenu d'un bulletin n'est pas validé au dépôt : le dépouillement tranche, selon une règle publique et déterministe. Un bulletin écarté reste publié et vérifiable ; il est seulement exclu du classement.

  1. 1 Vérifier. Chaque bulletin publié porte une signature en anneau valide et une image de clé unique dans l'élection : la plateforme le contrôle à la réception, le vérificateur le recontrôle. Un échec serait une faute du registre, pas une règle de dépouillement.
  2. 2 Filtrer le format. Le champ ballot passe le contrôle strict de cef-writer : chaîne vide, séparateur de tag ||, rang vide (A>>B), UTF-8 invalide, saut de ligne, caractères réservés ; , # / * ^ ou candidat répété le rejettent. L'analyseur de la bibliothèque le lit ensuite, et peut le refuser à son tour. Un bulletin rejeté est nul par format : il ne devient jamais un vote.
  3. 3 Reconnaître le blanc. La sentinelle /EMPTY_RANKING/ est un bulletin blanc : une abstention, comptée.
  4. 4 Appliquer les contraintes. Les contraintes déduites de ballot_rules classent chaque vote valide ou nul par contrainte. Un classement qui nomme un candidat non déclaré compte comme exprimé ; le nom inconnu est ignoré dans les duels.
  5. 5 Peser. Dans une élection pondérée, le poids appliqué est le weight de la charge utile signée, jamais un multiplicateur lu dans le classement (le filtre de format l'interdit). Les poids signés doivent former exactement le multiensemble des poids des votants marqués has_voted, dont la somme vaut totals.voted_weight. Sans pondération, chaque vote pèse 1.

Des paramètres aux contraintes

NoTie si ties_allowed = false
Rejette un vote qui exprime une égalité, y compris l'égalité implicite des candidats non classés d'un classement partiel.
NoBlankVote si blank_allowed = false
Rejette le bulletin blanc : il est alors nul par contrainte au lieu de blanc.
CompleteRanking si partial_ranking_allowed = false
Rejette un classement qui ne nomme pas explicitement tous les candidats.
Implicit Ranking selon election_type
Activé pour preferential : un candidat non classé est à égalité en dernière position. Désactivé pour fptp : un choix unique laisse les autres candidats non classés.

Les contraintes ne sont pas publiées en tant que telles : elles se déduisent des paramètres publiés par cette règle. Un blanc est une abstention, ni une égalité ni un classement partiel : NoTie et CompleteRanking l'exemptent, seul NoBlankVote le rejette. La plateforme applique cette exemption par ses propres variantes des contraintes natives de CondorcetPHP ; un recompte indépendant doit la reproduire.

Pour une élection fptp, les paramètres publiés sont fixes (égalités interdites, classement partiel permis, classement complet jamais exigé) : NoTie s'applique toujours, NoBlankVote si l'abstention est interdite. Un classement à plusieurs préférences y est lu à sa première préférence.

Comptes

Six compteurs, deux invariants.

Calculés une fois par dépouillement, identiques pour toutes les méthodes. Un recompte sous les mêmes contraintes doit les reproduire exactement.

total entier
Les votes enregistrés par la bibliothèque.
valid entier
Les votes qui passent toutes les contraintes.
expressed entier
Les votes valides et non blancs : ceux qui font le classement.
blank entier
Les votes valides au classement vide (/EMPTY_RANKING/).
invalidByConstraint entier
Les votes enregistrés mais rejetés par une contrainte : les nuls par contrainte.
invalidByFormat entier
Les bulletins qui ne sont jamais devenus un vote : les nuls par format, hors de total.

total = valid + invalidByConstraint ; valid = expressed + blank. Le nombre de nuls publié est invalidByFormat + invalidByConstraint. Le même découpage, sommé par poids plutôt que par bulletin, donne les voix d'une élection pondérée (sans pendant pour invalidByFormat : ces bulletins ne portent aucun poids) ; sans pondération, il recopie les comptes.

Méthodes

Une méthode, fixée avant le vote.

La plateforme n'implémente aucun algorithme de vote : chaque méthode est celle de la bibliothèque julien-boudry/condorcet (CondorcetPHP), désignée par son nom exact. Le type d'élection est publié dans le bloc 0 ; la méthode, choisie par l'organisateur, est gelée avec la configuration au lancement et publiée avec le résultat.

FPTP fptp
Scrutin majoritaire uninominal : le candidat qui recueille le plus de voix l'emporte, de poids en élection pondérée. Le résultat reste un classement complet.
Schulze Winning preferential · par défaut
Schulze, variante des votes gagnants.
Schulze Margin preferential
Schulze, variante des marges.
Ranked Pairs Winning preferential
Ranked Pairs (Tideman), variante des votes gagnants.
Ranked Pairs Margin preferential
Ranked Pairs (Tideman), variante des marges.
Copeland preferential
Méthode de Copeland.
Dodgson Quick preferential
L'approximation polynomiale de la méthode de Dodgson.
  • Une variante, un nom. Chaque variante est un choix distinct, associé un pour un au nom canonique de la bibliothèque : la méthode enregistrée se rejoue telle quelle.
  • Déterministes seulement. Aucune méthode non déterministe n'est proposée : les mêmes bulletins donnent toujours le même résultat.
  • La pondération n'est pas une méthode. Avec weighted_voting, la même méthode s'applique, chaque vote portant son poids, que la bibliothèque compte nativement.
  • Les sièges sont une coupe. Les élus sont les seats premières places du classement rendu ; rien d'autre n'est calculé. Les méthodes proportionnelles de la bibliothèque ne sont pas proposées.
  • Méthodes secondaires, à titre indicatif. Pour une élection Condorcet, la page de résultats peut montrer le classement qu'auraient donné les autres méthodes de la liste sur les mêmes bulletins. Seule la méthode principale fait le résultat officiel.
Les méthodes de Condorcet, expliquées
Égalités

Aucun départage inventé.

La plateforme rapporte ce que rend la bibliothèque et ne retouche jamais le vainqueur.

  • Rangs partagés. Le classement est numéroté à partir de 1 ; des candidats à égalité partagent le même rang.
  • Cycles. En l'absence de vainqueur de Condorcet, le cycle est résolu par la méthode configurée, et par elle seule.
  • Égalité à la coupe des sièges. Si une égalité chevauche la frontière entre la N-ième et la (N+1)-ième place, personne n'est déclaré élu au-delà de la frontière. L'organisateur tranche hors de la plateforme, typiquement par un second tour organisé comme une nouvelle élection.
  • Aucun bulletin. Sans bulletin, il n'y a rien à dépouiller : le résultat officiel est vide (comptes à zéro, classement vide, aucun élu), sans appel à la bibliothèque.
Contrat de dépouillement

La version du calcul, enregistrée avec le résultat.

Chaque résultat enregistre de quoi rejouer exactement la même sémantique : la version du contrat de dépouillement, la version de la bibliothèque et la méthode. La page de résultats publique affiche la méthode et, pour une élection Condorcet, la version de la bibliothèque.

engine_contract_version entier · aujourd'hui 1
La version du contrat de dépouillement (affichable « v1 ») : la forme du document de résultat et les règles de comptage décrites sur cette page.
condorcet_library_version chaîne
La version de julien-boudry/condorcet qui a calculé le résultat (Condorcet::VERSION).
method chaîne
Le nom canonique de la méthode, tel que la bibliothèque le rapporte (Result->fromMethod).
counts, weights objets
Les six compteurs ci-dessus et leur pendant pondéré.

Le document de résultat est conservé tel que la bibliothèque le produit : pour chaque méthode, le classement, le vainqueur et le perdant, le vainqueur et le perdant de Condorcet, les avertissements ; en option, la matrice des duels. La seule opération ajoutée par la plateforme est la coupe des seats premières places.

Export CEF

Une commodité, pas une pièce du protocole.

Une fois le dépouillement terminé et le résultat publié, la page de résultats propose les bulletins au Condorcet Election Format (CEF), un format texte ouvert dont la spécification est publique, lisible par la bibliothèque Condorcet comme par toute implémentation conforme.

  • Jamais nécessaire. Le document se reconstruit à partir du seul registre : un vérificateur peut le régénérer pour recouper le fichier servi, et le recompte n'en a pas besoin.
  • Sans contraintes ni méthode. Elles n'y figurent pas : elles se lisent dans ballot_rules et dans le résultat publiés.
  • Régénéré à chaque dépouillement. Produit après chaque dépouillement réussi, y compris pour une élection sans bulletin ; un nouveau dépouillement produit un nouveau document. Il n'est jamais purgé.
/elections/{election}/results/ballots.cef
Redirige vers le document stocké, une fois l'élection publiée et le dépouillement terminé.
Spécification du format CEF

Contenu du document

#/Candidates: paramètre
Les étiquettes officielles, déclarées d'emblée : un candidat que personne n'a classé existe quand même.
#/Implicit Ranking: paramètre
true pour une élection preferential, false pour une élection fptp.
#/Weight Allowed: paramètre, pondération seulement
Présent seulement dans une élection pondérée ; chaque ligne de vote porte alors son poids signé.
une ligne par bulletin classement CEF
Le champ ballot de chaque charge utile publiée, écrit par cef-writer, blancs /EMPTY_RANKING/ compris. Les nuls par format n'y figurent pas.
Recompte indépendant

Rejouer le dépouillement soi-même.

Avec la bibliothèque de référence à la version enregistrée, le recompte reproduit le classement et les comptes à l'identique. Toute autre implémentation conforme au CEF devrait, en théorie, aboutir au même résultat.

  1. 1 Télécharger le registre de l'élection et vérifier chaque bulletin : signature, unicité des images de clé, cohérence avec la liste d'émargement et, en élection pondérée, avec les poids.
  2. 2 Lire dans le bloc 0 les candidats, le type, ballot_rules, seats et weighted_voting ; en déduire les contraintes et la règle de classement implicite.
  3. 3 Écrire chaque charge utile publiée en CEF avec cef-writer, ou appliquer le même filtre de format, avec son poids signé si l'élection est pondérée ; les rejets sont les nuls par format.
  4. 4 Calculer avec julien-boudry/condorcet, à la version enregistrée, la méthode publiée avec le résultat, sous les contraintes déduites, le blanc exempté de NoTie et de CompleteRanking.
  5. 5 Comparer le classement et les six compteurs au résultat publié, puis lire les élus : les seats premières places.