L'un des systèmes de vote les plus courants pour les élections à un gagnant est la méthode du vote à la pluralité. En termes simples, le candidat avec le plus de votes gagne. Toutefois, le vote à la pluralité est mathématiquement peu judicieux et risque de créer des situations dans lesquelles les électeurs sont poussés à voter pour le "moindre de deux maux" par opposition au candidat qu'ils préfèrent vraiment.
Dans ce jeu, vous allez écrire un programme qui tire parti du système de vote à la pluralité. Il votera pour l'un des trois candidats à une élection. Chaque candidat est associé à un certain bénéfice pour vous-même et votre objectif est de maximiser le résultat escompté.
Les gains sont "uniformément" distribués au hasard, changent à chaque élection et totalisent 100. Le candidat A pourrait avoir un gain de 40, le candidat B pourrait avoir un gain de 27 et le candidat C pourrait avoir un gain de 33. Chaque joueur a un ensemble de gains différent.
Quand ce sera votre tour de voter, vous aurez des informations incomplètes. Vous trouverez ci-dessous les informations que vous aurez à votre disposition. Puisque vous ne savez pas quels sont les gains individuels des autres joueurs, votre défi sera de prédire comment ils voteraient compte tenu des résultats du sondage actuel.
- Les résultats partiels de l'élection jusqu'à présent
- Le nombre de participants (excluant vous-même), qui n'ont pas encore voté
- Vos gains personnels pour chacun des candidats
- Le total des gains de groupe pour chacun des candidats
Une fois que chaque joueur a eu la possibilité de voter, le candidat ayant obtenu le plus grand nombre de voix gagne conformément au vote à la majorité. Chaque joueur reçoit ensuite le nombre de points correspondant à son gain. En cas d'égalité des voix, le nombre de points attribués sera égal à la moyenne des candidats ex aequo.
Structure du tournoi
Lors de la première instanciation, le participant sera informé du nombre d'élections tenues dans le tournoi. Je vais tenter d'organiser un très grand nombre d'élections. Ensuite, chaque élection se déroulera une à une.
Une fois que les participants sont mélangés, on donne à chacun son tour de voter. Ils reçoivent les informations limitées énumérées ci-dessus et renvoient un numéro indiquant leur vote. Après chaque élection, chaque bot reçoit les résultats finaux du sondage et son score augmente à partir de cette élection.
Le participant victorieux sera celui qui obtiendra le score total le plus élevé après un grand nombre d'élections. Le contrôleur calcule également un score "normalisé" pour chaque concurrent en comparant son score à la distribution des scores prévue pour un bot à vote aléatoire.
Détails de la soumission
Les soumissions prendront la forme de classes Java 8. Chaque participant doit implémenter l'interface suivante:
public interface Player
{
public String getName();
public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs);
public void receiveResults(int[] voteCounts, double result);
}
- Votre constructeur devrait en prendre un
int
comme paramètre, qui représentera le nombre d’élections qui auront lieu. - La
getName()
méthode retourne le nom à utiliser dans le classement. Cela vous permet d'avoir des noms bien formatés, mais ne vous fâchez pas. - Les
getVote(...)
rendements de la méthode0
,1
ou2
pour signifier quel candidat recevra le vote. - La
receiveResults(...)
méthode vise principalement à permettre l’existence de stratégies plus complexes utilisant des données historiques. - Vous êtes autorisé à créer à peu près toutes les autres méthodes / variables d'instance que vous souhaitez enregistrer et à traiter les informations qui vous sont données.
Cycle de tournoi, élargi
- Les participants sont chacun instanciés avec
new entrantName(int numElections)
. - Pour chaque élection:
- Le contrôleur détermine aléatoirement les gains de chaque joueur pour cette élection. Le code pour cela est donné ci-dessous. Ensuite, il mélange les joueurs et les fait voter.
- La méthode du participant
public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
est invoqué, et le participant retourne leur vote0
,1
ou2
pour le candidat de leur choix. - Les participants dont la
getVote(...)
méthode ne donne pas un vote valide se verront attribuer un vote au hasard. - Une fois que tout le monde a voté, le contrôleur détermine les résultats de l'élection selon la méthode de la pluralité.
- Les participants sont informés du décompte final des votes et de leurs gains en appelant leur méthode
public void receiveResults(int[] voteCounts, double result)
.
- Une fois toutes les élections organisées, le gagnant est celui qui obtient le score le plus élevé.
La distribution aléatoire des gains
La distribution exacte aura un effet significatif sur le gameplay. J'ai choisi une distribution avec un écart type important (environ 23,9235) et capable de générer des gains très élevés et très bas. J'ai vérifié que chacun des trois gains a une distribution identique.
public int[] createPlayerPayoffs()
{
int cut1;
int cut2;
do{
cut1 = rnd.nextInt(101);
cut2 = rnd.nextInt(101);
} while (cut1 + cut2 > 100);
int rem = 100 - cut1 - cut2;
int[] set = new int[]{cut1,cut2,rem};
totalPayoffs[0] += set[0];
totalPayoffs[1] += set[1];
totalPayoffs[2] += set[2];
return set;
}
Plus de règles
Voici quelques règles plus générales.
- Votre programme ne doit pas exécuter / modifier / instancier des parties du contrôleur, des autres participants ou de leurs mémoires.
- Comme votre programme reste "en direct" pendant tout le tournoi, ne créez aucun fichier.
- Ne pas interagir avec, aider ou cibler tout autre programme entrant.
- Vous pouvez soumettre plusieurs participants, dans la mesure où ils sont raisonnablement différents et dans le respect des règles ci-dessus.
- Je n'ai pas spécifié de limite de temps exacte, mais j'apprécierais énormément les durées d'exécution nettement inférieures à une seconde par appel. Je veux pouvoir organiser autant d'élections que possible.
Le controlle
Le contrôleur peut être trouvé ici . Le programme principal est Tournament.java
. Il y a aussi deux simples robots, qui seront en compétition, intitulés RandomBot
et PersonalFavoriteBot
. Je vais poster ces deux robots dans une réponse.
Classement
Il semble que ExpectantBot soit le leader actuel, suivi de Monte Carlo, puis de StaBot.
Leaderboard - 20000000 elections:
767007688.17 ( 937.86) - ExpectantBot
766602158.17 ( 934.07) - Monte Carlo 47
766230646.17 ( 930.60) - StatBot
766054547.17 ( 928.95) - ExpectorBot
764671254.17 ( 916.02) - CircumspectBot
763618945.67 ( 906.19) - LockBot
763410502.67 ( 904.24) - PersonalFavoriteBot343
762929675.17 ( 899.75) - BasicBot
761986681.67 ( 890.93) - StrategicBot50
760322001.17 ( 875.37) - Priam
760057860.67 ( 872.90) - BestViableCandidate (2842200 from ratio, with 1422897 tie-breakers of 20000000 total runs)
759631608.17 ( 868.92) - Kelly's Favorite
759336650.67 ( 866.16) - Optimist
758564904.67 ( 858.95) - SometimesSecondBestBot
754421221.17 ( 820.22) - ABotDoNotForget
753610971.17 ( 812.65) - NoThirdPartyBot
753019290.17 ( 807.12) - NoClueBot
736394317.17 ( 651.73) - HateBot670
711344874.67 ( 417.60) - Follower
705393669.17 ( 361.97) - HipBot
691422086.17 ( 231.38) - CommunismBot0
691382708.17 ( 231.01) - SmashAttemptByEquality (on 20000000 elections)
691301072.67 ( 230.25) - RandomBot870
636705213.67 ( -280.04) - ExtremistBot
The tournament took 34573.365419071 seconds, or 576.2227569845166 minutes.
Voici quelques tournois plus anciens, mais aucun des robots n'a changé de fonctionnalité depuis ces exécutions.
Leaderboard - 10000000 elections:
383350646.83 ( 661.14) - ExpectantBot
383263734.33 ( 659.99) - LearnBot
383261776.83 ( 659.97) - Monte Carlo 48
382984800.83 ( 656.31) - ExpectorBot
382530758.33 ( 650.31) - CircumspectBot
381950600.33 ( 642.64) - PersonalFavoriteBot663
381742600.33 ( 639.89) - LockBot
381336552.33 ( 634.52) - BasicBot
381078991.83 ( 631.12) - StrategicBot232
380048521.83 ( 617.50) - Priam
380022892.33 ( 617.16) - BestViableCandidate (1418072 from ratio, with 708882 tie-breakers of 10000000 total runs)
379788384.83 ( 614.06) - Kelly's Favorite
379656387.33 ( 612.31) - Optimist
379090198.33 ( 604.83) - SometimesSecondBestBot
377210328.33 ( 579.98) - ABotDoNotForget
376821747.83 ( 574.84) - NoThirdPartyBot
376496872.33 ( 570.55) - NoClueBot
368154977.33 ( 460.28) - HateBot155
355550516.33 ( 293.67) - Follower
352727498.83 ( 256.36) - HipBot
345702626.33 ( 163.50) - RandomBot561
345639854.33 ( 162.67) - SmashAttemptByEquality (on 10000000 elections)
345567936.33 ( 161.72) - CommunismBot404
318364543.33 ( -197.86) - ExtremistBot
The tournament took 15170.484259763 seconds, or 252.84140432938332 minutes.
J'ai également organisé un deuxième tournoi de 10 m, confirmant ainsi l'avance de ExpectantBot.
Leaderboard - 10000000 elections:
383388921.83 ( 661.65) - ExpectantBot
383175701.83 ( 658.83) - Monte Carlo 46
383164037.33 ( 658.68) - LearnBot
383162018.33 ( 658.65) - ExpectorBot
382292706.83 ( 647.16) - CircumspectBot
381960530.83 ( 642.77) - LockBot
381786899.33 ( 640.47) - PersonalFavoriteBot644
381278314.83 ( 633.75) - BasicBot
381030871.83 ( 630.48) - StrategicBot372
380220471.33 ( 619.77) - BestViableCandidate (1419177 from ratio, with 711341 tie-breakers of 10000000 total runs)
380089578.33 ( 618.04) - Priam
379714345.33 ( 613.08) - Kelly's Favorite
379548799.83 ( 610.89) - Optimist
379289709.83 ( 607.46) - SometimesSecondBestBot
377082526.83 ( 578.29) - ABotDoNotForget
376886555.33 ( 575.70) - NoThirdPartyBot
376473476.33 ( 570.24) - NoClueBot
368124262.83 ( 459.88) - HateBot469
355642629.83 ( 294.89) - Follower
352691241.83 ( 255.88) - HipBot
345806934.83 ( 164.88) - CommunismBot152
345717541.33 ( 163.70) - SmashAttemptByEquality (on 10000000 elections)
345687786.83 ( 163.30) - RandomBot484
318549040.83 ( -195.42) - ExtremistBot
The tournament took 17115.327209018 seconds, or 285.25545348363335 minutes.
Array
contenant un décompte de tous les votes. Ai-je raison?