Jednym z najczęstszych systemów głosowania w wyborach jednoosobowych jest metoda głosowania w wielu wyborach. Mówiąc najprościej, wygrywa kandydat z największą liczbą głosów. Głosowanie w liczbie mnogiej jest jednak matematycznie niestosowne i może prowadzić do sytuacji, w których wyborcy będą zmuszani głosować na „mniejsze zło” w przeciwieństwie do kandydata, którego naprawdę wolą.
W tej grze napiszesz program korzystający z wielu systemów głosowania. Głosuje na jednego z trzech kandydatów w wyborach. Każdy kandydat jest powiązany z pewną wypłatą dla ciebie, a Twoim celem jest maksymalizacja oczekiwanej wypłaty.
Wypłaty są „równomiernie” losowo rozdzielane, zmieniane przy każdym wyborze i dodawane do 100. Kandydat A może mieć wypłatę 40, Kandydat B może mieć wypłatę 27, a Kandydat C może mieć wypłatę 33. Każdy gracz ma inny zestaw wypłat.
Kiedy nadejdzie Twoja kolej na głosowanie, będziesz mieć niekompletne informacje. Poniżej wymieniono informacje, które będziesz mieć do dyspozycji. Ponieważ nie wiesz, jakie są indywidualne wypłaty innych graczy, Twoim wyzwaniem będzie przewidzieć, jak głosują, biorąc pod uwagę obecne wyniki ankiety.
- Dotychczasowe częściowe wyniki wyborów
- Liczba uczestników (bez ciebie), którzy jeszcze nie głosowali
- Twoje osobiste wypłaty dla każdego z kandydatów
- Łączne wypłaty grupowe dla każdego z kandydatów
Po umożliwieniu każdemu graczowi głosowania, kandydat z największą liczbą głosów wygrywa zgodnie z głosowaniem mnogim. Następnie każdy gracz otrzymuje liczbę punktów odpowiadającą wypłacie od tego kandydata. W przypadku remisu głosów liczba przyznanych punktów będzie średnią z remisowanych kandydatów.
Struktura turnieju
Po pierwszym wystąpieniu uczestnik zostanie poinformowany o liczbie wyborów przeprowadzonych w turnieju. Spróbuję przeprowadzić wyjątkowo dużą liczbę wyborów. Następnie każde wybory będą przeprowadzane jeden po drugim.
Po potasowaniu uczestników każdy ma prawo do głosowania. Dostają ograniczone informacje wymienione powyżej i zwracają liczbę oznaczającą ich głos. Po każdych wyborach każdy bot otrzymuje ostateczne wyniki ankiety, a jego wynik wzrasta z tych wyborów.
Zwycięski uczestnik zostanie zwycięzcą z największą liczbą punktów po przeprowadzeniu dużej liczby wyborów. Kontroler oblicza również „znormalizowany” wynik dla każdego uczestnika, porównując jego wynik z rozkładem wyników przewidywanym dla bota o losowym głosowaniu.
Szczegóły zgłoszenia
Zgłoszenia będą miały formę klas Java 8. Każdy uczestnik musi wdrożyć następujący interfejs:
public interface Player
{
public String getName();
public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs);
public void receiveResults(int[] voteCounts, double result);
}
- Twój konstruktor powinien przyjąć jeden
int
jako parametr, który będzie reprezentował liczbę wyborów, które odbędą się. getName()
Metoda zwraca nazwę używanego na tablicy wyników. To pozwala mieć ładnie sformatowane nazwy, po prostu nie zwariuj.- Te
getVote(...)
metody powraca0
,1
albo2
oznaczać który kandydat otrzyma głosowania. receiveResults(...)
Metoda jest przede wszystkim, aby umożliwić istnienie bardziej skomplikowanych strategii, które korzystają z danych historycznych.- Możesz tworzyć dowolne inne metody / zmienne instancji, które chcesz rejestrować i przetwarzać podane informacje.
Cykl turniejowy, rozszerzony
- Każdy uczestnik jest inicjowany za pomocą
new entrantName(int numElections)
. - Dla każdego wyboru:
- Kontroler losowo określa wypłaty dla każdego gracza w tych wyborach. Kod do tego jest podany poniżej. Następnie tasuje graczy i rozpoczyna głosowanie.
- Metoda uczestnik jest
public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
wywoływana jest, a uczestnik zwraca swój głos0
,1
lub2
kandydata swojego wyboru. - Uczestnicy, których
getVote(...)
metoda nie zwróci ważnego głosu, otrzymają losowy głos. - Po tym, jak wszyscy zagłosują, kontroler określa wyniki wyborów za pomocą wielu metod.
- Uczestnicy są informowani o ostatecznej liczbie głosów i ich wypłacie za pomocą metody
public void receiveResults(int[] voteCounts, double result)
.
- Po przeprowadzeniu wszystkich wyborów zwycięzcą zostaje ten, który uzyska najwyższy wynik.
Losowy podział wypłat
Dokładny rozkład będzie miał znaczący wpływ na rozgrywkę. Wybrałem rozkład o dużym odchyleniu standardowym (około 23,9235), który może generować zarówno bardzo wysokie, jak i bardzo niskie wypłaty. Sprawdziłem, czy każda z trzech wypłat ma identyczny rozkład.
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;
}
Więcej zasad
Oto kilka bardziej ogólnych zasad.
- Twój program nie może uruchamiać / modyfikować / tworzyć instancji żadnych części kontrolera lub innych uczestników ani ich pamięci.
- Ponieważ Twój program pozostaje „na żywo” przez cały turniej, nie twórz żadnych plików.
- Nie wchodź w interakcje, nie pomagaj ani nie celuj w żadne inne programy.
- Państwo może przesłać wiele podmiotów, o ile są one dość różne, i tak długo, jak postępować zgodnie z powyższymi przepisami.
- Nie określiłem dokładnego limitu czasu, ale bardzo doceniłbym środowiska wykonawcze, które są znacznie krótsze niż sekunda na połączenie. Chcę być w stanie przeprowadzić tyle wyborów, ile to możliwe.
Kontroler
Kontroler można znaleźć tutaj . Głównym programem jest Tournament.java
. Istnieją również dwa proste boty, które będą konkurować, zatytułowane RandomBot
i PersonalFavoriteBot
. Wyślę te dwa boty w odpowiedzi.
Tabela liderów
Wygląda na to, że ExpectantBot jest obecnym liderem, a następnie Monte Carlo, a następnie 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.
Oto niektóre starsze turnieje, ale żaden z botów nie zmienił swojej funkcjonalności od czasu tych uruchomień.
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.
Przeprowadziłem również drugi 10-metrowy turniej, potwierdzając prowadzenie 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.
źródło
Array
zawiera liczbę wszystkich głosów. Mam rację?Odpowiedzi:
NoThirdPartyBot
Ten bot próbuje zgadnąć, który z kandydatów będzie trzeci, i głosuje na kandydata, którego lubi najbardziej, z dwóch czołowych graczy.
CircumspectBot
Ten bot głosuje na swojego ulubionego, który nie został matematycznie wyeliminowany.
źródło
ExpectantBot
Ten bot oblicza oczekiwaną wartość każdej opcji głosowania, zakładając, że wszyscy wyborcy będą potem głosować losowo.
źródło
HipBot
HipBot nie dba o wypłaty. Pieniądze to tylko środek uspokajający, który odwraca uwagę od prawdziwej sztuki.
HipBot chce głosować na kogoś prawdziwego , a nie tylko korporacyjnego szylinga. Chce również nosić koszulkę kampanii po (przypuszczalnie) upokarzającej porażce, więc czuje się lepszy, gdy zwycięzca zrobi coś złego.
Dlatego HipBot głosuje na osobę o najniższej liczbie głosów lub, jeśli istnieje remis, kto ma lepszą wypłatę. Jedzenie wyłącznie ekologiczne nie jest darmowe.
HipBot również nie jest testowany, więc daj mi znać, jeśli coś się dzieje.
EDYCJA: dodano bardziej konkurencyjne, zwięzłe komentarze.
źródło
PersonalFavoriteBot
Ten bot po prostu głosuje na kandydata o najwyższej osobistej wypłacie, ignorując wszystko inne. Jednym z głównych punktów tego wyzwania jest wykazanie, że nie jest to optymalna strategia.
RandomBot
Ten bot głosuje losowo. Niezależnie od liczby przeprowadzonych wyborów (o ile jest dość wysoka, na przykład ponad 100), znormalizowany wynik tego zawodnika waha się między -2 a 2.
źródło
Zwolennik
Zwolennik chce się dopasować. Uważa, że najlepszym sposobem osiągnięcia tego jest głosowanie w taki sam sposób, jak wszyscy inni, lub przynajmniej z wieloma. Zerwie więzi z własnymi preferencjami, aby wykazać odrobinę niezależności. Ale nie za dużo.
Uwaga: nie testowałem tego, więc daj mi znać, jeśli są jakieś błędy.
źródło
Monte Carlo
To symuluje dużą liczbę losowych wyborów. Następnie wybiera wybór maksymalizujący własne zyski.
źródło
StatBot
StatBot jest oparty na ExpectantBot; zamiast zakładać, że każdy głos jest jednakowo prawdopodobny, zbiera statystyki dotyczące tego, jak ludzie głosują, i wykorzystuje je do oszacowania prawdopodobieństwa.
źródło
Najlepszy żywy kandydat
Całkiem mocno zmieniona wersja mojego oryginalnego zgłoszenia. Ten nadal eliminuje kandydatów, którzy nie mogą wygrać, biorąc pod uwagę pozostałe głosy, ale następnie stosuje strategię, która próbuje zoptymalizować relatywną wypłatę, a nie absolutną. Pierwszy test polega na uwzględnieniu stosunku mojej osobistej wypłaty do ogólnej wypłaty dla każdego kandydata, szukając tam najlepszej wartości. Następnie szukam innych wskaźników, które są bardzo zbliżone do najlepszych i jeśli istnieje taki, który ma niższą ogólną wypłatę niż najlepsza, wybieram go zamiast tego. Mam nadzieję, że obniży to wypłatę innych graczy, jednocześnie utrzymując mój poziom na dość wysokim poziomie.
Ten bot działa prawie tak dobrze jak oryginał w moich własnych testach, ale nie do końca. Musimy zobaczyć, jak to działa na pełnym polu.
źródło
CircumspectBot
?Optymista
Optymista jest bardzo optymistyczny i zakłada, że połowa pozostałych wyborców zagłosuje na kandydata, który zapewni mu najlepszą wypłatę.
źródło
ABotDoNotForget
Jego cel jest prosty: określenie ogólnych tendencji za pomocą całkowitych wypłat i zliczenie czasu, w którym wygrywali niższe / średnie / wyższe. Następnie zagłosuje na tego, który najprawdopodobniej wygra.
Edytować :
Pewna zmiana dokonana w algorytmie decyzyjnym uwzględnia teraz jego najlepszą wypłatę. Powinien być teraz w stanie głosować lepiej, gdy obecna dystrybucja zmusiła go do głosowania na swoją Niższą, gdy inni głosowali na wyższe wypłaty.źródło
Priam
Priam nie znosi rekurencji. Ocenia prawdopodobieństwo każdego pozostałego bota na podstawie całkowitych wypłat, a następnie oblicza najlepszy sposób maksymalizacji jego wypłaty.
Znacznie szybciej niż Odyseusz, ponieważ nie ma rekurencji (biegnie w czasie O (n ^ 2)) i może dokonać miliona wyborów w około 15 sekund.
źródło
NoClueBot
NoClue tak naprawdę nie zna języka Java ani matematyki, więc nie ma pojęcia, czy ten stosunek wagowy pomoże mu wygrać. Ale on próbuje.
SomeClueBot
SomeClueBot został wycofany z eksploatacji.
faktycznie używa logiki! zwykł używać logiki, która okazała się nieefektywna, więc zamiast tego zwracał uwagę na całkowitą wypłatę, a nie własną. ponownie używa logiki! Ale nie radzi sobie dobrze z tymi wszystkimi zwolennikami i optymistami, a nawet ludźmi, których to nie obchodzi! :)CzasamiSecondBestBot
Zasadniczo PersonalFavouriteBot, ulepszony (teoretycznie).
źródło
Ekstremista
Zawsze głosuj na kandydata o najniższej wypłacie
źródło
SmashAttemptByEquality
Celem jest wyrównanie wszystkich kandydatów, a następnie SMASH! wszystkie inne boty w ostatniej rundzie.
Jest to niszczycielski algorytm, który próbuje wyłudzić wszystkie inne, aby wygrać.
Zauważ, że to nie zostało przetestowane !
źródło
Podstawowy bot
Podstawowy bot tylko głosuje na kandydatów, którzy nie zostali wyeliminowani i mają największą maksymalną wypłatę od tych kandydatów.
źródło
Ulubieniec Kelly
Zacząłem od CircumspectBot, ale niewiele zostało. Nudzi się na podstawie rozkładu prawdopodobieństwa pozostałych głosów, a następnie dokonuje wyboru, który maksymalizuje własną logarytmiczną użyteczność (kryterium Kelly'ego). Nie najszybszy, ale w parku piłkarskim niektórych innych. Ponadto jest dość konkurencyjny w tej dziedzinie (tak jak wtedy, gdy zacząłem nad tym pracować i pobierałem inne boty).
Dostępne również na https://gist.github.com/jkominek/dae0b3158dcd253e09e5 w przypadku, gdy jest to prostsze.
źródło
CommunismBot
Komunizm Bot myśli, że wszyscy powinniśmy się dogadać i wybrać kandydata, który będzie najlepszy dla wszystkich.
Hatebot
Hatebot zawsze wybiera najlepszego kandydata. Chyba że są imprezą śmierdzącą śmiercią 1. Ci faceci są okropni.
StrategicBot
StrategicBot głosuje na najlepszego kandydata pod warunkiem, że mieszczą się w zakresie jednego standardowego odchylenia od następnego najlepszego kandydata, biorąc pod uwagę liczbę pozostałych wyborców.
źródło
ExpectorBot
Próbuje przewidzieć, jak głosują wszystkie inne boty, obliczając średnią wypłatę dla innych. Domyślne głosy za najlepszą wypłatę, ale będą głosować na drugie najlepsze, jeśli ma więcej oczekiwanych głosów niż najlepszy, lepsza niż średnia wypłata dla mnie, a najgorsza wypłata ma szansę wygrać tę rzecz.
źródło
LockBot
Po prostu samotny filozof, szukający swojego „e” ...
źródło
Wygrana przegrana
Jeśli wygrasz, przegrywam! Tak proste. Więc ten bot głosuje na tego, który mu się podoba, a wszystkim innym nie.
źródło