Одной из наиболее распространенных систем голосования на выборах с одним победителем является метод множественного голосования. Проще говоря, кандидат с наибольшим количеством голосов побеждает. Однако голосование во множественном числе математически несостоятельно и может создать ситуации, в которых избиратели вынуждены голосовать за «меньшее из двух зол», а не за кандидата, которого они действительно предпочитают.
В этой игре вы напишите программу, которая использует преимущества системы множественного голосования. Он будет голосовать за одного из трех кандидатов на выборах. Каждый кандидат связан с определенной выплатой за себя, и ваша цель - максимизировать ожидаемую выплату.
Выплаты «равномерно» распределяются случайным образом, меняются при каждом избрании и прибавляются к 100. Кандидат A может получить выплату 40, Кандидат B может получить выплату 27, а Кандидат C может получить выплату 33. У каждого игрока свой набор выплат.
Когда придет ваша очередь голосовать, у вас будет неполная информация. Ниже приведена информация, которая будет вам доступна. Поскольку вы не знаете, каковы индивидуальные выигрыши других игроков, вам будет сложно предсказать, как они будут голосовать, учитывая текущие результаты опроса.
- Частичные итоги выборов пока
- Количество участников (исключая вас), которые еще не проголосовали
- Ваши личные выплаты для каждого из кандидатов
- Суммарные групповые выплаты для каждого из кандидатов
После того, как каждому игроку предоставлена возможность проголосовать, кандидат с наибольшим количеством голосов побеждает в соответствии с множественным голосованием. Каждый игрок затем получает количество очков, соответствующее его выигрышу от этого кандидата. Если в голосовании есть связь, то количество набранных баллов будет средним из связанных кандидатов.
Структура турнира
При первом рассмотрении участнику сообщается количество выборов, проведенных в турнире. Я попытаюсь провести чрезвычайно большое количество выборов. Затем каждые выборы будут проводиться один за другим.
После перетасовки участников каждый получает право голосовать. Они получают ограниченную информацию, указанную выше, и возвращают число, обозначающее их голос. После того, как пройдут все выборы, каждому боту будут предоставлены окончательные результаты опроса, и их результаты увеличатся по сравнению с этими выборами.
Победителем будет тот, кто наберет наибольшее количество очков после того, как будет проведено большое количество выборов. Контроллер также вычисляет «нормированный» балл для каждого участника, сравнивая его балл с распределением баллов, предсказанным для бота со случайным голосованием.
Детали представления
Материалы будут представлены в форме классов Java 8. Каждый участник должен реализовать следующий интерфейс:
public interface Player
{
public String getName();
public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs);
public void receiveResults(int[] voteCounts, double result);
}
- Ваш конструктор должен взять один
int
параметр в качестве параметра, который будет представлять количество выборов, которые будут проведены. getName()
Метод возвращает имя , которое будет использоваться в списке лидеров. Это позволяет вам иметь красиво отформатированные имена, просто не сходите с ума.- В
getVote(...)
метод возвращает значение0
,1
или2
для обозначения которых кандидат получит голоса. receiveResults(...)
Метод главным образом для того, чтобы существование более сложных стратегий , которые используют исторические данные.- Вам разрешено создавать практически любые другие методы / переменные экземпляра, которые вы хотите записать и обработать предоставленную вам информацию.
Турнирный цикл, расширенный
- Каждый участник имеет экземпляр
new entrantName(int numElections)
. - Для каждых выборов:
- Контроллер случайным образом определяет выплаты для каждого игрока за эти выборы. Код для этого приведен ниже. Затем он перетасовывает игроков и заставляет их начать голосование.
- Метод конкурсанта
public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
вызывается, и участник возвращает свой голос из0
,1
или2
за кандидата по своему выбору. - Абитуриенты, чьи
getVote(...)
метод не возвращает действительный голос, будет назначен случайный голос. - После того, как все проголосовали, контролер определяет результаты выборов методом множественного голосования.
- Участники получают информацию об окончательном подсчете голосов и их выплате, называя свой метод
public void receiveResults(int[] voteCounts, double result)
.
- После того, как все выборы проведены, побеждает тот, кто набрал наибольшее количество очков.
Случайное распределение выплат
Точное распределение будет иметь значительное влияние на игровой процесс. Я выбрал дистрибутив с большим стандартным отклонением (около 23,9235), который способен создавать как очень высокие, так и очень низкие выплаты. Я проверил, что каждая из трех выплат имеет одинаковое распределение.
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;
}
Больше правил
Вот еще несколько обобщенных правил.
- Ваша программа не должна запускать / модифицировать / создавать экземпляры каких-либо частей контроллера или других участников или их памяти.
- Поскольку ваша программа остается «живой» на протяжении всего турнира, не создавайте никаких файлов.
- Не взаимодействуйте с другими программами, не помогайте им и не предназначайтесь для них.
- Вы можете подать несколько участников, если они разумно отличаются, и при условии соблюдения вышеуказанных правил.
- Я не указал точный лимит времени, но я был бы очень признателен за время выполнения, которое значительно меньше секунды за вызов. Я хочу провести как можно больше выборов.
Контроллер
Контроллер можно найти здесь . Основная программа есть Tournament.java
. Есть также два простых бота, которые будут соревноваться, под названием RandomBot
и PersonalFavoriteBot
. Я опубликую этих двух ботов в ответ.
Leaderboard
Похоже, ExpectantBot является текущим лидером, за которым следуют Монте-Карло и затем 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.
Вот несколько более старых турниров, но ни один из ботов не изменился по функциональности после этих запусков.
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.
Я также провел второй 10-метровый турнир, подтверждая преимущество 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
содержит подсчет всех голосов. Я прав?