전략적 투표, 게임


37

단일 당선자 선거를위한 가장 일반적인 투표 시스템 중 하나는 복수 투표 방법입니다. 간단히 말해, 가장 많은 표를 얻은 후보자가 승리합니다. 그러나 복수 투표는 수학적으로 건전하지 않으며 유권자들이 자신이 선호하는 후보자에 반대하여 "두 가지 악의 적은"투표를하게되는 상황을 만들게됩니다.

이 게임에서는 복수 투표 시스템을 활용하는 프로그램을 작성하게됩니다. 선거에서 3 명의 후보 중 하나에 투표 할 것입니다. 각 후보는 자신에 대한 특정 보수와 관련이 있으며 목표는 예상 보수를 극대화하는 것입니다.

후보는 "균일하게"무작위 배분되고 각 선거에 따라 변경되며 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(...)방법은 주로 히스토리 데이터를 사용하는보다 복잡한 전략의 존재를 가능하게하는 것입니다.
  • 당신은 당신에게 주어진 정보를 기록하고 처리하기를 원하는 거의 모든 다른 메소드 / 인스턴스 변수를 만들 수 있습니다.

토너먼트 사이클, 확장

  1. 참가자는로 인스턴스화됩니다 new entrantName(int numElections).
  2. 각 선거마다 :
    1. 컨트롤러는이 선거에서 각 플레이어의 지불액을 무작위로 결정합니다. 이에 대한 코드는 다음과 같습니다. 그런 다음 플레이어를 섞어 투표를 시작합니다.
    2. 참가자의 방법은 public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)호출되며, 참가자는 자신의 투표를 반환 0, 1또는 2자신이 선택한 후보.
    3. getVote(...)방법이 유효한 투표를 반환하지 않는 참가자 에게는 무작위 투표가 할당됩니다.
    4. 모두가 투표 한 후에, 제어기는 복수의 방법에 의해 선거 결과를 결정한다.
    5. 참가자들에게 최종 투표 수와 지불 방법에 대한 정보를 제공 public void receiveResults(int[] voteCounts, double result)합니다.
  3. 모든 선거가 열리면 가장 높은 점수를 얻은 사람이 승자가됩니다.

보수의 무작위 분포

정확한 분포는 게임 플레이에 큰 영향을 미칠 것입니다. 표준 편차가 큰 분포 (약 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. 이 두 봇을 답변에 게시하겠습니다.

리더 보드

ExpectantBot가 현재 리더 인 것처럼 보이며 Monte Carlo, 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.

또한 ExpectantBot의 리드를 확인하면서 두 번째 10m 토너먼트를 진행했습니다.

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.

와우, 나도 그렇게 가난 했어요!
— Ismael Miguel

내가 코드에서 본 것에 따르면, 두 번째 매개 변수는 남아있는 투표 수입니다. 그리고 첫 번째 Array는 모든 투표 수를 포함합니다. 제가 맞습니까?
— Ismael Miguel

1
@IsmaelMiguel 예.
— PhiNotPi

1
두번째. 그들은 선거의 일부 결과이며, 그것은 당신 앞에있는 사람들이 셔플 순서로 작성한 투표입니다.
— PhiNotPi

2
유권자에게 클론을 줄 때 어떤 일이 발생하는지 살펴볼 수도 있습니다. 간단한 눈에, sometimesSecondBestBot, NoThirdPartyBot에서 모든 낙관주의는 더 큰 투표 풀에서 이익을 보인다 (AS가 extremistBot을하고, 자신의 방식으로, communismBot에 있지만 덜 중요하다).
— Saidoro

답변:


10

NoThirdPartyBot

이 봇은 어느 후보가 세 번째가 될지 추측하고, 두 선두 주자 중 가장 좋아하는 후보를 투표합니다.

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class NoThirdPartyBot implements Player {

    public NoThirdPartyBot(int e) {
    }


    @Override
    public String getName() {
        return "NoThirdPartyBot";
    }

    @Override
    public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs,
            int[] totalPayoffs) {
        List<Integer> order = order(totalPayoffs);

        if (payoffs[order.get(0)] > payoffs[order.get(1)]) {
            return order.get(0);
        } else {
            return order.get(1);
        }
    }

    static List<Integer> order(int[] array) {
        List<Integer> indexes = Arrays.asList(0, 1, 2);
        Collections.sort(indexes, (i1, i2) -> array[i2] - array[i1]);
        return indexes;
    }

    @Override
    public void receiveResults(int[] voteCounts, double result) {
    }
}

CircumspectBot

이 로봇은 수학적으로 제거되지 않은 그의 마음에 드는 것에 투표합니다.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;


public class CircumspectBot implements Player {

    public CircumspectBot(int elections) {
    }

    @Override
    public String getName() {
        return "CircumspectBot";
    }

    @Override
    public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs,
            int[] totalPayoffs) {
        List<Integer> indexes = new ArrayList<>();
        int topVote = Arrays.stream(voteCounts).max().getAsInt();
        for (int index = 0; index < 3; index++) {
            if (voteCounts[index] + votersRemaining + 1 >= topVote) {
                indexes.add(index);
            }
        }
        Collections.sort(indexes, (i1, i2) -> payoffs[i2] - payoffs[i1]);

        return indexes.get(0);
    }

    @Override
    public void receiveResults(int[] voteCounts, double result) {

    }

}

4
저는 Circumspect Bot이 Personal Favorite Bot보다 훨씬 낫습니다. 좋은.
— isaacg

10

기대 봇

이 봇은 이후에 모든 유권자가 무작위로 투표한다고 가정하여 각 투표 옵션의 예상 값을 계산합니다.

import java.util.Arrays;

public class ExpectantBot implements Player {

    public ExpectantBot(int elections) {
    }

    @Override
    public String getName() {
        return "ExpectantBot";
    }

    static double choose(int x, int y) {
        if (y < 0 || y > x) return 0;
        if (y > x/2) {
            // choose(n,k) == choose(n,n-k), 
            // so this could save a little effort
            y = x - y;
        }

        double denominator = 1.0, numerator = 1.0;
        for (int i = 1; i <= y; i++) {
            denominator *= i;
            numerator *= (x + 1 - i);
        }
        return numerator / denominator;
    }

    double expectedPayout(int[] voteCounts, int[] payoffs, int votersRemaining) {
        double total = 0.0;
        for (int firstPartyVoters = 0; firstPartyVoters <= votersRemaining; firstPartyVoters++) {
            for (int secondPartyVoters = 0; secondPartyVoters <= votersRemaining - firstPartyVoters; secondPartyVoters++) {
                int thirdPartyVoters = votersRemaining - firstPartyVoters - secondPartyVoters;

                int [] newVoteCounts = voteCounts.clone();
                newVoteCounts[0] += firstPartyVoters;
                newVoteCounts[1] += secondPartyVoters;
                newVoteCounts[2] += thirdPartyVoters;
                int highest = Arrays.stream(newVoteCounts).max().getAsInt();
                int payoff = 0;
                int winCount = 0;
                for (int index = 0; index < 3; index++) {
                    if (newVoteCounts[index] == highest) {
                        payoff += payoffs[index];
                        winCount++;
                    }
                }
                double v = (double)payoff / (double) winCount;
                double value = choose(votersRemaining, firstPartyVoters)*choose(votersRemaining - firstPartyVoters, secondPartyVoters)*v*Math.pow(1/3.0, votersRemaining);
                total += value;
            }
        }
        return total;
    }

    @Override
    public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs,
            int[] totalPayoffs) {

        int bestVote = 0;
        double bestScore = 0.0;
        for (int vote = 0; vote < 3; vote++) {      
            voteCounts[vote]++;
            double score = expectedPayout(voteCounts, payoffs, votersRemaining);
            if (score > bestScore) {
                bestVote = vote;
                bestScore = score;
            }
            voteCounts[vote]--;
        }
        return bestVote;

    }

    @Override
    public void receiveResults(int[] voteCounts, double result) {   
    }

}

다른 상대로부터 무거운 게임을하지 않으면이 사람을 이길 경우 놀라게 될 것입니다.
— DoctorHeckle

@DoctorHeckle, StatBot에 대한 희망이 있었지만 당신이 옳다고 생각합니다.
— Winston Ewert 2016 년

9

힙봇

HipBot은 지불금에 관심이 없습니다. 돈은 진정한 예술을 방해하는 진정 제일뿐입니다.

HipBot은 일부 기업 실링이 아닌 실제 사람에게 투표하려고합니다 . 그는 (아마도) 굴욕적인 패배 후에 캠페인 셔츠를 입기를 원하기 때문에 우승자가 무언가 잘못했을 때마다 우월감을 느낍니다.

따라서, HipBot은 가장 낮은 투표권을 가진 사람이나 동점이있는 사람에게 더 나은 대금을 지급 한 사람에게 투표합니다. 유기농만을 먹는 것은 무료가 아닙니다.

public class HipBot implements Player{

    public HipBot(int rounds){ /*Rounds are a social construct*/ }

    public String getName(){ return "HipBot"; }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs){

        int coolest = 0;
        int lowest = 100000000;
        int gains = 0;

        for( int count = 0; count < voteCounts.length; count++ ){

            if( voteCounts[count] < lowest || (voteCounts[count] == lowest && payoffs[count] > gains) ){

                lowest = voteCounts[count];
                coolest = count;
                gains = payoffs[count];

            }

        }

        return coolest;

    }

    public void receiveResults(int[] voteCounts, double result){ /*The past is dead*/ }

}

HipBot도 테스트되지 않았으므로 진행중인 문제가 있으면 알려주세요.

편집 : 경쟁이 치열하고 까다로운 의견에 추가되었습니다.


느슨한에 대한 그의 동정심은 그의 점수를 위해 많은 것을하지 않지만, 나를 위해 작동합니다 :)
— euanjt

5
그는 그의 마음에 이겼고, 그에게 중요한 것은 : D
— DoctorHeckle

8

PersonalFavoriteBot

이 봇은 단순히 다른 모든 것을 무시하고 가장 높은 개인 보수를 가진 후보자에게 투표합니다. 이 과제의 주요 요점 중 하나는 이것이 최적의 전략이 아닌 방법을 보여주는 것입니다.

import java.lang.Math;
import java.util.Random;
/**
 * This bot picks the candidate with the highest personal payoff, ignoring everyone else's actions.
 * 
 * @author PhiNotPi 
 * @version 5/27/15
 */
public class PersonalFavoriteBot implements Player
{
    Random rnd;
    String name;
    /**
     * Constructor for objects of class PersonalFavoriteBot
     */
    public PersonalFavoriteBot(int e)
    {
       rnd = new Random(); 
       name = "PersonalFavoriteBot" + rnd.nextInt(1000);
    }

    public String getName()
    {
        return name;
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        //return rnd.nextInt(3);
        int maxloc = 0;
        for(int i = 1; i< 3; i++)
        {
            if(payoffs[i] > payoffs[maxloc])
            {
                maxloc = i;
            }
        }
        return maxloc;
    }

    public void receiveResults(int[] voteCounts, double result)
    {

    }
}

랜덤 봇

이 봇은 무작위로 투표합니다. 실시 된 선거의 수에 관계없이 (100 이상과 같이 합리적으로 높은 경우)이 참가자의 정규화 된 점수는 -2와 2 사이에서 변동합니다.

import java.lang.Math;
import java.util.Random;
/**
 * This bot votes for a random candidate.
 * 
 * @author PhiNotPi 
 * @version 5/27/15
 */
public class RandomBot implements Player
{
    Random rnd;
    String name;
    /**
     * Constructor for objects of class RandomBot
     */
    public RandomBot(int e)
    {
       rnd = new Random(); 
       name = "RandomBot" + rnd.nextInt(1000);
    }

    public String getName()
    {
        return name;
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        return rnd.nextInt(3);
    }

    public void receiveResults(int[] voteCounts, double result)
    {

    }
}

7

수행원

팔로어가 적합하기를 원합니다.이를 달성하기위한 최선의 방법은 다른 모든 사람과 같은 방식으로 투표하거나 적어도 지금까지 복수로 투표하는 것입니다. 약간의 독립성을 보여주기 위해 자신의 취향에 대한 유대를 깰 것입니다. 그러나 너무 많이하지 않습니다.

public class Follower implements Player
{
    public Follower(int e) { }

    public String getName()
    {
        return "Follower";
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        int mostPopular = 0;
        int mostVotes = voteCounts[0];
        for (int i = 1; i < voteCounts.length; i++) {
            int votes = voteCounts[i];
            if (votes > mostVotes || (votes == mostVotes && payoffs[i] > payoffs[mostPopular])) {
                mostPopular = i;
                mostVotes = votes;
            }
        }
        return mostPopular;

    }

    public void receiveResults(int[] voteCounts, double result) { }
}

참고 : 나는 이것을 테스트하지 않았으므로 오류가 있는지 알려주십시오.


작동하는 것 같습니다.
— PhiNotPi

4

몬테카를로

이것은 대량의 무작위 선거를 시뮬레이트합니다. 그런 다음 자신의 이익을 극대화하는 선택을 선택합니다.

import java.util.ArrayList;
import java.util.List;

public class MonteCarlo implements Player{

    private static long runs = 0;
    private static long elections = 0;

    public MonteCarlo(int e) {
        elections = e;
    }

    @Override
    public String getName() {
        return "Monte Carlo (difficulty " + (runs / elections) + ")";
    }

    @Override
    public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs, int[] totalPayoffs) {
        elections++;
        double[] predictedPayoffs = new double[3];
        long startTime = System.nanoTime();
        while (System.nanoTime() - startTime <= 200_000){ //Let's give us 200 micro-seconds.
            runs++;
            int[] simulatedVoteCounts = voteCounts.clone();
            for (int j = 0; j < votersRemaining; j++){
                simulatedVoteCounts[((int) Math.floor(Math.random() * 3))]++;
            }
            for (int j = 0; j < 3; j++) {
                simulatedVoteCounts[j]++;
                List<Integer> winners = new ArrayList<>();
                winners.add(0);
                for (int k = 1; k < 3; k++) {
                    if (simulatedVoteCounts[k] > simulatedVoteCounts[winners.get(0)]) {
                        winners.clear();
                        winners.add(k);
                    } else if (simulatedVoteCounts[k] == simulatedVoteCounts[winners.get(0)]) {
                        winners.add(k);
                    }
                }
                for (int winner : winners) {
                    predictedPayoffs[j] += payoffs[winner] / winners.size();
                }
                simulatedVoteCounts[j]--;
            }
        }
        int best = 0;
        for (int i = 1; i < 3; i++){
            if (predictedPayoffs[i] > predictedPayoffs[best]){
                best = i;
            }
        }
        return best;
    }

    @Override
    public void receiveResults(int[] voteCounts, double result) {

    }
}

4

스탯 봇

StatBot은 ExpectantBot을 기반으로합니다. 그러나 각 투표가 똑같이 가능하다고 가정하는 대신 사람들이 투표하는 방법에 대한 통계를 수집하여 확률을 추정하는 데 사용합니다.

import java.util.Arrays;


public class StatBot implements Player {

    static private int[][][] data = new int[3][3][3];
    private int[] voteCounts;

    StatBot(int unused) {

    }

    @Override
    public String getName() {
        return "StatBot";

    }

     static double choose(int x, int y) {
            if (y < 0 || y > x) return 0;
            if (y > x/2) {
                // choose(n,k) == choose(n,n-k), 
                // so this could save a little effort
                y = x - y;
            }

            double denominator = 1.0, numerator = 1.0;
            for (int i = 1; i <= y; i++) {
                denominator *= i;
                numerator *= (x + 1 - i);
            }
            return numerator / denominator;
        }

    double expectedPayout(int[] voteCounts, int[] payoffs, int votersRemaining) {
        Integer[] indexes = {0, 1, 2};
        Arrays.sort(indexes, (i0, i1) -> voteCounts[i1] - voteCounts[i0]);
        int [] stats = data[indexes[0]][indexes[1]];
        int total_stats = Arrays.stream(stats).sum();
        double total = 0.0;
        for (int firstPartyVoters = 0; firstPartyVoters <= votersRemaining; firstPartyVoters++) {
            for (int secondPartyVoters = 0; secondPartyVoters <= votersRemaining - firstPartyVoters; secondPartyVoters++) {
                int thirdPartyVoters = votersRemaining - firstPartyVoters - secondPartyVoters;

                int [] newVoteCounts = voteCounts.clone();
                newVoteCounts[0] += firstPartyVoters;
                newVoteCounts[1] += secondPartyVoters;
                newVoteCounts[2] += thirdPartyVoters;
                int highest = 0;
                for (int h : newVoteCounts) {
                    if (h > highest) highest = h;
                }
                int payoff = 0;
                int winCount = 0;
                for (int index = 0; index < 3; index++) {
                    if (newVoteCounts[index] == highest) {
                        payoff += payoffs[index];
                        winCount++;
                    }
                }
                double v = (double)payoff / (double) winCount;
                double value = choose(votersRemaining, firstPartyVoters)*choose(votersRemaining - firstPartyVoters, secondPartyVoters)*v;
                value *= Math.pow((double)stats[0]/(double)total_stats, firstPartyVoters);
                value *= Math.pow((double)stats[1]/(double)total_stats, secondPartyVoters);
                value *= Math.pow((double)stats[2]/(double)total_stats, thirdPartyVoters);

                total += value;
            }
        }
        return total;
    }

    @Override
    public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs,
            int[] totalPayoffs) {

        int bestVote = 0;
        double bestScore = 0.0;
        for (int vote = 0; vote < 3; vote++) {      
            voteCounts[vote]++;
            double score = expectedPayout(voteCounts, payoffs, votersRemaining);
            if (score > bestScore) {
                bestVote = vote;
                bestScore = score;
            }
            voteCounts[vote]--;
        }
        voteCounts[bestVote]++;
        this.voteCounts = voteCounts;

        return bestVote;

    }

    @Override
    public void receiveResults(int[] endVoteCounts, double result) {
        Integer[] indexes = {0, 1, 2};
        Arrays.sort(indexes, (i0, i1) -> voteCounts[i1] - voteCounts[i0]);
        for(int i = 0; i < 3; i++){
            data[indexes[0]][indexes[1]][i] += endVoteCounts[i] - voteCounts[i];
        }
    }
}

4

최고의 생존 후보

원래 제출물의 버전이 상당히 많이 수정되었습니다. 이 투표는 남아있는 투표에서 주어진 투표에 이길 수없는 후보를 제거하지만 절대적인 투표 보다는 상대적인 보수 를 최적화하는 전략을 사용합니다 . 첫 번째 테스트는 각 후보자에 대한 전체 보수에 대한 개인 보수의 비율을 평가하여 최고의 가치를 찾는 것입니다. 그런 다음 최고에 매우 가까운 다른 비율을 찾고 최고보다 전체 지불금이 낮은 비율이 있으면 대신 그 비율을 선택합니다. 바라건대 이것은 다른 플레이어의 지불금을 낮추면서 내 채를 합리적으로 높이는 경향이 있습니다.

이 봇은 내 자신의 테스트에서 원본과 거의 비슷 하지만 실제로는 아닙니다. 우리는 그것이 전체 분야에 어떻게 영향을 미치는지보아야 할 것입니다.

 /**
  * This bot picks the candidate with the highest relative payoff out of those
  * candidates who are not already mathematically eliminated.
  *
  * @author Ralph Marshall
  * @version 5/28/2015
  */

import java.util.List;
import java.util.ArrayList;


public class BestViableCandidate implements Player
{
    private static int NUM_CANDIDATES = 3;
    private int relativeCount = 0;
    private int relativeCountLowerTotal = 0;
    private int totalRuns;

    public BestViableCandidate(int r) {
        totalRuns = r;
    }

    public String getName() {
        return "BestViableCandidate (" + relativeCount + " from ratio, with " + relativeCountLowerTotal + " tie-breakers of " + totalRuns + " total runs)";
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs) {

        int i, maxVoteSoFar = 0;

        // First we figure out the maximum possible number of votes each candidate would get
        // if every remaining bot voted for it
        int [] maxPossibleVotes = new int[NUM_CANDIDATES];
        for (i = 0; i < NUM_CANDIDATES; i++) {

            // The voters remaining does not include me, so we need to add one to it
            maxPossibleVotes[i] = voteCounts[i] + votersRemaining + 1;

            if (voteCounts[i] > maxVoteSoFar) {
                maxVoteSoFar = voteCounts[i];
            }
        }

        // Then we throw out anybody who cannot win even if they did get all remaining votes
        List<Integer> viableCandidates = new ArrayList<Integer>();
        for (i = 0; i < NUM_CANDIDATES; i++) {
            if (maxPossibleVotes[i] >= maxVoteSoFar) {
                viableCandidates.add(Integer.valueOf(i));
            }
        }

        // And of the remaining candidates we pick the one that has the personal highest payoff
        // relative to the payoff to the rest of the voters
        int maxCandidate = -1;
        double maxRelativePayoff = -1;
        int maxPayoff = -1;
        int minTotalPayoff = Integer.MAX_VALUE;

        int originalMaxCandidate = -1;
        double originalMaxPayoff = -1;

        double DELTA = 0.01;

        double tiebreakerCandidate = -1;

        for (Integer candidateIndex : viableCandidates) {
            double relativePayoff = (double) payoffs[candidateIndex] / (double) totalPayoffs[candidateIndex];
            if (maxRelativePayoff < 0 || relativePayoff - DELTA > maxRelativePayoff) {
                maxRelativePayoff = relativePayoff;
                maxCandidate = candidateIndex;

                maxPayoff = payoffs[candidateIndex];
                minTotalPayoff = totalPayoffs[candidateIndex];

            } else if (Math.abs(relativePayoff - maxRelativePayoff) < DELTA) {
                if (totalPayoffs[candidateIndex] < minTotalPayoff) {
                    tiebreakerCandidate = candidateIndex;

                    maxRelativePayoff = relativePayoff;
                    maxCandidate = candidateIndex;

                    maxPayoff = payoffs[candidateIndex];
                    minTotalPayoff = totalPayoffs[candidateIndex];

                }
            }

            if (payoffs[candidateIndex] > originalMaxPayoff) {
                originalMaxPayoff = payoffs[candidateIndex];
                originalMaxCandidate = candidateIndex;
            }
        }

        if (tiebreakerCandidate == maxCandidate) {
            relativeCountLowerTotal++;
        }

        if (originalMaxCandidate != maxCandidate) {
            /*                System.out.printf("%nSelecting candidate %d with relative payoff %f (%d/%d) instead of %d with relative payoff %f (%d/%d)%n",
                              maxCandidate, (double) payoffs[maxCandidate]/(double)totalPayoffs[maxCandidate], payoffs[maxCandidate], totalPayoffs[maxCandidate],
                              originalMaxCandidate, (double) payoffs[originalMaxCandidate]/(double)totalPayoffs[originalMaxCandidate], payoffs[originalMaxCandidate], totalPayoffs[originalMaxCandidate]);
            */
            relativeCount++;
        }

        return maxCandidate;
    }
}

1
이것과 같지 CircumspectBot않습니까?
— TheNumberOne

그렇습니다. 나는 주된 질문에서 그 효과에 대해 논평했다. 코딩을 시작했을 때 정확히 어떻게 작동하는지 알지 못했습니다. CircumspectBot가 먼저 작성되었으므로 아이디어에 대한 명성을 분명히 얻을 수 있습니다.
— 랄프 마샬

수업이 끝났다고 생각합니다.
— Winston Ewert

감사. 나는 마지막 버팀대를 잃었다. 거기에 있었던 후에 다른 코드가 없었습니다.
— 랄프 마샬

3

낙관론자

낙관론은 매우 낙관적이며 나머지 유권자의 절반이 자신에게 최고의 보상을주는 후보자에게 투표한다고 가정합니다.

import java.lang.Integer;
import java.lang.String;
import java.util.Arrays;
import java.util.Comparator;

public class Optimist implements Player
{
    public Optimist(int _) { }
    public String getName() { return "Optimist"; }
    public int getVote(int[] curVotes, int rem, final int[] payoffs, int[] _)
    {
        Integer[] opt = new Integer[] { 0, 1, 2 };
        Arrays.sort(opt, new Comparator<Integer>() { public int compare(Integer i1, Integer i2) { return payoffs[i1] > payoffs[i2] ? -1 : payoffs[i1] == payoffs[i2] ? 0 : 1; } });
        int a = curVotes[opt[0]], b = curVotes[opt[1]], c = curVotes[opt[2]];
        double rest = (double)rem / 4;
        if (b <= a + rest && c <= a + rest)
            return opt[0];
        else if (c <= b)
            return opt[1];
        else
            return opt[0];
    }
    public void receiveResults(int[] _, double __) { }
}

3

ABotDoNotForget

그의 목표는 간단합니다. 총 지불액을 사용하여 전체 경향을 결정하고 낮은 / 중간 / 높은 시간이이긴 횟수를 계산합니다. 그런 다음 가장 이길 가능성이 높은 사람에게 투표합니다.

import java.util.ArrayList;

public class ABotDoNotForget implements Player
{
    private int nbElec;
    private int countElec=0;
    private int[] currPayoffs=new int[3];
    private int[] lmh=new int[3];
    private int[] wins=new int[3];

    public ABotDoNotForget(int nbElec)
    {
        this.nbElec=nbElec;
    }

    public String getName() {return "ABotDoNotForget";}

    public int getVote(int[] voteCounts, 
                        int votersRemaining, 
                        int[] payoffs,
                        int[] totalPayoffs) 
    {
        countElec++;
        System.arraycopy(totalPayoffs, 0, currPayoffs, 0, totalPayoffs.length);

        if(countElec<=nbElec/20&&countElec<=20)
        {
            int best=0;
            for(int i=1;i<payoffs.length;i++)
                if(payoffs[i]>=payoffs[best])
                    best=i;
            return best;
        }

        for(int i =1;i<totalPayoffs.length;i++)
        {
            if(totalPayoffs[i]<totalPayoffs[i-1])
            {
                int tmp= totalPayoffs[i];
                totalPayoffs[i]=totalPayoffs[i-1];
                totalPayoffs[i-1]=tmp;
                if(i==2&&totalPayoffs[i-1]<totalPayoffs[i-2]){
                    tmp= totalPayoffs[i-1];
                    totalPayoffs[i-1]=totalPayoffs[i-2];
                    totalPayoffs[i-2]=tmp;
                }
            }
        }
        lmhDist(currPayoffs,totalPayoffs);
        int best=0;
        for(int i=1;i<wins.length;i++)
            if(wins[i]>=wins[best]){
                best=i;
            }
        int ownH=0;
        for(int i=1;i<payoffs.length;i++)
            if(payoffs[i]>=payoffs[ownH])
                ownH=i;
        int ownM=0;
        for(int i=1;i<payoffs.length;i++)
            if(payoffs[i]>=payoffs[ownM]&&i!=ownH)
                ownM=i;

        int persBest=(voteCounts[ownH]-voteCounts[ownM]+(votersRemaining/3)>=0
                &&voteCounts[ownH]-voteCounts[best]<(votersRemaining/3))?ownH:ownM;

        return persBest;

    }

    public void receiveResults(int[] voteCounts, double result) 
    {
        int best=0,bestV=voteCounts[best];
        for(int i=1;i<voteCounts.length;i++)
            if(voteCounts[i]>=bestV){
                best=i;
                bestV=voteCounts[i];
            }
        wins[lmh[best]]++;

    }

    private void lmhDist(int[] a,int[] s)
    {
        ArrayList<Integer> al = new ArrayList<Integer>();
        al.add(a[0]);al.add(a[1]);al.add(a[2]);
        lmh[0]=al.indexOf(s[0]);
        lmh[1]=al.indexOf(s[1]);
        lmh[2]=al.indexOf(s[2]);

    }
}

편집하다 :

의사 결정 알고리즘에서 수행 된 일부 변경 사항은 이제 자신의 최상의 보상을 고려합니다. 현재 분배가 그를 자신의 로워 투표로 만들 때 더 나은 투표를 할 수 있어야합니다.


3

프리 암

프리즘은 재귀를 싫어합니다. 총 지불액을 기준으로 남아있는 각 봇의 확률을 추정 한 다음 지불 효과를 극대화하는 가장 좋은 방법을 계산합니다.

public class Priam implements Player {
    private static double[] smallFactorials = {1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800.,87178291200.,1307674368000.,20922789888000.,355687428096000.,6402373705728000.,121645100408832000.,2432902008176640000.};
    @Override
    public String getName() {
        return "Priam";
    }

    @Override
    public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs,
            int[] totalPayoffs) {
        int totalPayoff = totalPayoffs[0] + totalPayoffs[1] + totalPayoffs[2];
        double p0 = ((double)totalPayoffs[0])/totalPayoff;
        double p1= ((double) totalPayoffs[1])/totalPayoff;
        double p2 = ((double)totalPayoffs[2])/totalPayoff;
        double[] expectedPayoffs = {0,0,0};
        for(int myChoice=0;myChoice<3;myChoice++)
        {
            for(int x0 = 0; x0 <= votersRemaining; x0++)
            {
                for(int x1 = 0; x1 <= (votersRemaining-x0); x1++)
                {
                    int x2 = votersRemaining - (x1 + x0);
                    double probability =
                            Math.pow(p0, x0)
                            * Math.pow(p1, x1)
                            * Math.pow(p2, x2)
                            * Choose(votersRemaining, x0)
                            * Choose(votersRemaining-x0, x1);
                    int votes0 = voteCounts[0];
                    int votes1 = voteCounts[1];
                    int votes2 = voteCounts[2];
                    if(myChoice == 0)
                    {
                        votes0++;
                    }
                    else if(myChoice==1)
                    {
                        votes1++;
                    }
                    else
                    {
                        votes2++;
                    }

                    votes0+=x0;
                    votes1+=x1;
                    votes2+=x2;
                    if(votes0>votes1 && votes0>votes2)
                    {
                        expectedPayoffs[myChoice]+=probability*payoffs[0];
                    }
                    else if(votes1>votes2)
                    {
                        expectedPayoffs[myChoice]+=probability*payoffs[1];
                    }
                    else
                    {
                        expectedPayoffs[myChoice]+=probability*payoffs[2];
                    }
                }
            }
        }
        if(expectedPayoffs[0]>expectedPayoffs[1] && expectedPayoffs[0]>expectedPayoffs[2])
        {
            return 0;
        }
        else if(expectedPayoffs[1]>expectedPayoffs[2])
        {
            return 1;
        }
        else
        {
            return 2;
        }
    }

    private long Choose(int source, int team) {
        return Factorial(source)/(Factorial(team)*Factorial(source-team));
    }

    private long Factorial(int n) {
        if(n<=20)
        {
            return (long)smallFactorials[n];
        }
        double d=(double)n;
        double part1 = Math.sqrt(2*Math.PI*d);
        double part2 = Math.pow(d/Math.E, d);
        return (long)Math.ceil(part1 * part2);
    }

    @Override
    public void receiveResults(int[] voteCounts, double result) {


    }
    public Priam(int i)
    {

    }
}

재귀가없고 (O (n ^ 2 시간에 실행) 약 15 초에 100 만 선거를 할 수 있기 때문에 오디세우스보다 훨씬 빠릅니다.


"이것은 자체 이익을 위해 총 지불금 매개 변수를 사용하는 최초의 봇이라고 생각합니다.)"내 봇 (ABotDoNotForget)을 봅니다. 그는 이미 사용하고 있습니다. 죄송합니다 : D
— Katenkyo

totalPayoffs를 사용하여 확률을 예측한다는 점을 제외하고는 최신 봇 ExpectantBot과 매우 유사하며 모든 투표가 똑같이 가능하다고 가정합니다. 어떤 전략이 가장 효과적인지 궁금합니다.
— Winston Ewert

@WinstonEwert 당신이 생각하는 것, 당신은 내가 한 마지막 세 번의 시험에서 이겼습니다.
— euanjt

나는 단지 유사점을 알아 차렸다. 나는 100 개의 선거를 진행하는데 10 시간이 걸리지 않은 오디세우스의 버전을 만들려고 노력했다. 그래서 나는 루프를 사용했다
— euanjt

솔직히 말해서, 나는 오디세우스의 접근 방식에 영감을 받았습니다.
— Winston Ewert

2

NoClueBot

NoClue는 실제로 Java 나 수학을 잘 모르므로이 가중치 비율이 승리하는 데 도움이 될지 전혀 모릅니다. 그러나 그는 노력하고 있습니다.

import java.lang.Math;
import java.util.*;
/**
 * Created by Admin on 5/27/2015.
 */
public class NoClueBot implements Player {

    public NoClueBot(int e) { }

    public String getName() {
        return "NoClueBot";
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs) {
        double x = 0;
        int y = 0;
        for (int i=0; i<3; i++) {
            double t = (double) voteCounts[i] * ((double) payoffs[i]/(double) totalPayoffs[i]);
            if (x<t) {
                x = t;
                y = i; 
            }
        }
        return y;
    }

    public void receiveResults(int[] voteCounts, double result) { }
}


SomeClueBot

SomeClueBot가 폐기되었습니다. 실제로 논리를 사용합니다! 비효율적 인 것으로 판명 된 논리를 사용했기 때문에 그는 자신의 것이 아니라 총 보수를 염두에 두었습니다. 다시 논리를 사용합니다! 그러나 그는이 모든 추종자들과 낙관론자들, 심지어 신경 쓰지 않는 사람들과 잘 어울리지 않습니다! :)


때로는 두 번째 dBBot

기본적으로 PersonalFavouriteBot은 개선되었습니다 (이론적으로).

import java.lang.Math;
/**
 * Created by Admin on 5/27/2015.
 */
public class SometimesSecondBestBot implements Player {
    public SometimesSecondBestBot(int e) { }

    public String getName() {
        return "SometimesSecondBestBot";
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs) {
        int m = 0;
        int n = 0;
        for(int i = 1; i< 3; i++) {
            if(payoffs[i] > payoffs[m]) { n = m; m = i; }
        }
        return (voteCounts[n]>voteCounts[m]&&totalPayoffs[n]>totalPayoffs[m])||(voteCounts[m]+votersRemaining<voteCounts[n])||voteCounts[m]+votersRemaining<voteCounts[Math.min(3-n-m, 2)] ? n : m;
    }

    public void receiveResults(int[] voteCounts, double result) { }
}

1
3 개의 가중치 중 가장 큰 숫자를 계산하고 해당 값 mod 3을 사용하여 최상의 후보를 선택하는 것 같습니다. 맞습니까? 그렇다면 기본적으로 난수가 아닌가요? 나는 당신이 이것을 "수학은 어려운 바비"라고 부르고 있다는 것을 이해합니다. 그래서 나는 개념이 확실하지 않습니다.
— Ralph Marshall

@RalphMarshall 네, 기본적으로 무작위입니다. 그러나, 나는 완전히 그렇게 할 의도가 없었고,주의를 기울이지 않았습니다. 지금 고쳤습니다.
— Kade

@PhiNotPhi 지금은 범위를 벗어난 것으로 고쳤습니다. 네, 놀라지 않았습니다.
— Kade

나의 신 이것은 나쁘다. 나의 방어 작업에서 오늘 정신적으로 매우 지쳤다.
— Kade

2

극단 주의자

항상 지불금이 가장 낮은 후보자에게 투표하십시오

public class ExtremistBot implements Player
{
    public ExtremistBot(int e){}

    public void receiveResults(int[] voteCounts, double result){}

    public String getName(){
        return "ExtremistBot";
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        int min = 0;
        for(int i = 1; i<payoffs.length; i++){
            if(payoffs[i] <payoffs[min]){
                min = i;
            }
        }
        return min;
    }
}

2

평등에 의한 스매시

목표는 모든 후보자를 평준화 한 다음 SMASH하는 것입니다! 마지막 라운드의 다른 모든 봇.
이것은 승리를 주장하기 위해 다른 모든 것들을 망치려고 시도하는 파괴적인 알고리즘입니다.

public class SmashAttemptByEquality implements Player {
    static private int elections;

    public SmashAttemptByEquality(int e) { 
        this.elections = e;
    }

    public String getName() {
        return "SmashAttemptByEquality (on " + String.valueOf(this.elections) + " elections)";
    }

    public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs, int[] totalPayoffs) {

        //if there are no votes or it is a tie
        if(voteCounts.length == 0 || (voteCounts[0] == voteCounts[1] && voteCounts[1] == voteCounts[2]))
        {
            //let the system handle the (distributed?) randomness
            return 3;
        }

        //we want to win, so, lets not mess when there are no voters left
        if( votersRemaining > 0 )
        {
            //lets bring some equality!
            if( voteCounts[0] >= voteCounts[1] )
            {
                if(voteCounts[0] > voteCounts[2])
                {
                    return 2;
                }
                else
                {
                    return 0;
                }
            }
            else if( voteCounts[1] >= voteCounts[2] )
            {
                if(voteCounts[1] > voteCounts[0])
                {
                    return 0;
                }
                else
                {
                    return 1;
                }
            }
            else
            {
                return 0;
            }
        }
        else
        {
            //just play for the winner!
            if( voteCounts[0] >= voteCounts[1] )
            {
                if(voteCounts[0] > voteCounts[2])
                {
                    return 0;
                }
                else
                {
                    return 2;
                }
            }
            else if( voteCounts[1] >= voteCounts[2] )
            {
                if(voteCounts[1] > voteCounts[0])
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
            else
            {
                return 0;
            }
        }
    }

    public void receiveResults(int[] voteCounts, double result) { }
}

이것은 테스트되지 않았습니다 !


2

기본 봇

기본 봇은 제거되지 않은 후보자에 대해서만 투표하고 해당 후보자로부터 최대 지불액을 얻습니다.

public class BasicBot implements Player {
    public BasicBot(int e) { }
    public String getName()
    {
        return "BasicBot";
    }
    public static int getMax(int[] inputArray){ 
    int maxValue = inputArray[0]; 
    for(int i=1;i < inputArray.length;i++){ 
      if(inputArray[i] > maxValue){ 
         maxValue = inputArray[i]; 
      } 
    } 
    return maxValue; 
   }
    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        // Check for Eliminated Candidates
        int eliminated0 = 0;
        int eliminated1 = 0;
        int eliminated2 = 0;
        if( ((voteCounts[0] + votersRemaining) < voteCounts[1]) || ((voteCounts[0] + votersRemaining) < voteCounts[2]))
        {
            eliminated0 = 1;
        }
        if( ((voteCounts[1] + votersRemaining) < voteCounts[0]) || ((voteCounts[1] + votersRemaining) < voteCounts[2]))
        {
            eliminated1 = 1;
        }
        if( ((voteCounts[2] + votersRemaining) < voteCounts[0]) || ((voteCounts[2] + votersRemaining) < voteCounts[1]))
        {
            eliminated2 = 1;
        }
        // Choose the Candidates that is not elimated with the largest payoff
        if ((payoffs[0] == getMax(payoffs)) && eliminated0 == 0)
            return 0
        else if ((payoffs[1] == getMax(payoffs)) && eliminated1 == 0)
            return 1
        else
            return 2

    }

    public void receiveResults(int[] voteCounts, double result)
    {
    }

}

2

켈리의 마음에 드는 것

CircumspectBot로 시작했지만 그다지 남지 않았습니다. 나머지 투표의 확률 분포에 대해 일종의 지루한 추측을 한 다음 자체 로그 유틸리티 (Kelly Criterion)를 최대화하는 선택을합니다. 가장 빠르지는 않지만 다른 사람들의 볼 파크 내에서. 또한 필드와 경쟁이 치열합니다 (이 작업을 시작하고 다른 봇을 다운로드했을 때 섰습니다).

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

public class KellysFavorite implements Player {
    private ArrayList<Double> cache = new ArrayList<Double>();

    public KellysFavorite(int elections) {
        cache.add(0.0);
        double v = 0.0;
        for(int i=1; i<1000; i++) {
            v += Math.log(i);
            cache.add(v);
        }
    }

    @Override
    public String getName() {
        return "Kelly's Favorite";
    }

    private double factln(int n) {
        return cache.get(n);
    }

    private  double binll(int x, int n, double p)
    {
        double ll = 0.0;
        ll += ((double)x)*Math.log(p);
        ll += ((double)(n - x))*Math.log(1.0 - p);
        ll += factln(n) - factln(x) - factln(n-x);
        return ll;
    }

    public  double logAdd(double logX, double logY) {
        // 1. make X the max
        if (logY > logX) {
            double temp = logX;
            logX = logY;
            logY = temp;
        }
        // 2. now X is bigger
        if (logX == Double.NEGATIVE_INFINITY) {
            return logX;
        }
        // 3. how far "down" (think decibels) is logY from logX?
        //    if it's really small (20 orders of magnitude smaller), then ignore
        double negDiff = logY - logX;
        if (negDiff < -20) {
            return logX;
        }
        // 4. otherwise use some nice algebra to stay in the log domain
        //    (except for negDiff)
        return logX + java.lang.Math.log(1.0 + java.lang.Math.exp(negDiff));
    }

    @Override
    public int getVote(int[] voteCounts,
                       int votersRemaining,
                       int[] payoffs,
                       int[] totalPayoffs) {
        int totalviable = 0;
        boolean[] viable = { false, false, false };
        int topVote = Arrays.stream(voteCounts).max().getAsInt();
        for (int index = 0; index < 3; index++) {
            if (voteCounts[index] + votersRemaining + 1 >= topVote) {
                viable[index] = true;
                totalviable += 1;
            }
        }

        // if only one candidate remains viable, vote for them
        if(totalviable == 1) {
            for(int index = 0; index < 3; index++)
                if(viable[index])
                    return index;
        } else {
            double votelikelihoods[] = { 0.0, 0.0, 0.0 };
            double totalweight = 0.0;
            for(int index=0; index<3; index++) {
                if(!viable[index])
                    votelikelihoods[index] -= 10.0;
                else if(voteCounts[index] < topVote)
                    votelikelihoods[index] -= 0.1;

                totalweight += Math.exp(votelikelihoods[index]);
            }

            double probs[] = new double[3];
            for(int index=0; index<3; index++) {
                probs[index] = Math.exp(votelikelihoods[index]) / totalweight;
            }

            double[] utilities = {0,0,0};
            for(int mychoice=0; mychoice<3; mychoice++) {
                boolean seen[] = { false, false, false };
                double likelihoods[] = { Double.NEGATIVE_INFINITY,
                                         Double.NEGATIVE_INFINITY,
                                         Double.NEGATIVE_INFINITY };
                int[] localVoteCounts = { voteCounts[0] + (mychoice==0?1:0),
                                          voteCounts[1] + (mychoice==1?1:0),
                                          voteCounts[2] + (mychoice==2?1:0) };
                for(int iVotes=0; iVotes<=votersRemaining; iVotes++)
                    for(int jVotes=0; jVotes<=(votersRemaining-iVotes); jVotes++) {
                        int kVotes = votersRemaining - iVotes - jVotes;

                        int a = localVoteCounts[0] + iVotes;
                        int b = localVoteCounts[1] + jVotes;
                        int c = localVoteCounts[2] + kVotes;
                        int wincount = Math.max(a, Math.max(b, c));
                        int winners = 0;
                        if(a>=wincount) { winners += 1; }
                        if(b>=wincount) { winners += 1; }
                        if(c>=wincount) { winners += 1; }

                        double likelihood =
                            binll(iVotes, votersRemaining, probs[0])
                            + binll(jVotes, votersRemaining-iVotes, probs[1] / (probs[1] + probs[2]));

                        likelihood += Math.log(1.0/winners);

                        if(a>=wincount) {
                            if(seen[0])
                                likelihoods[0] = logAdd(likelihoods[0],
                                                        likelihood);
                            else
                                likelihoods[0] = likelihood;
                            seen[0] = true;
                        }
                        if(b>=wincount) {
                            if(seen[1])
                                likelihoods[1] = logAdd(likelihoods[1],
                                                        likelihood);
                            else
                                likelihoods[1] = likelihood;
                            seen[1] = true;
                        }
                        if(c>=wincount) {
                            if(seen[2])
                                likelihoods[2] = logAdd(likelihoods[2],
                                                        likelihood);
                            else
                                likelihoods[2] = likelihood;
                            seen[2] = true;
                        }

                    }

                for(int index=0; index<3; index++)
                    utilities[mychoice] += Math.exp(likelihoods[index]) * Math.log((double)payoffs[index]);
            }

            double maxutility = Math.max(utilities[0], Math.max(utilities[1], utilities[2]));
            int choice = 0;
            for(int index=0; index<3; index++)
                if(utilities[index]>=maxutility)
                    choice = index;
            return choice;
        }

        throw new InternalError();
    }

    @Override
    public void receiveResults(int[] voteCounts, double result) {

    }

}

더 간단한 경우 https://gist.github.com/jkominek/dae0b3158dcd253e09e5 에서도 사용할 수 있습니다 .


2

공산주의

CommunismBot은 우리 모두가 잘 지내고 모두에게 가장 적합한 후보자를 뽑아야한다고 생각합니다.

public class CommunismBot implements Player
{
    Random rnd;
    String name;
    public CommunismBot(int e) {
        rnd = new Random(); 
        name = "CommunismBot" + rnd.nextInt(1000);
    }

    public String getName()
    {
        return name;
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        int maxloc = 0;
        for(int i = 1; i< 3; i++)
        {
            if(totalPayoffs[i] > totalPayoffs[maxloc])
            {
                maxloc = i;
            }
        }
        return maxloc;
    }

    public void receiveResults(int[] voteCounts, double result) { }
}

증오 봇

Hatebot은 항상 최고의 후보를 선택합니다. 그들이 더러운 파티를하지 않는 한 1. 그 사람들은 끔찍합니다.

import java.util.Random;


public class HateBot implements Player
{
    Random rnd;
    String name;
    public HateBot(int e) {
        rnd = new Random(); 
        name = "HateBot" + rnd.nextInt(1000); }

    public String getName()
    {
        return name;
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        if(payoffs[0]>payoffs[2])
            return 0;
        else
            return 2;
    }

    public void receiveResults(int[] voteCounts, double result) { }
}

전략적 봇

StrategicBot은 남은 유권자 수를 고려하여 최고 후보에 대한 다음 표결의 표준 편차 내에있는 경우 최고 후보에 투표합니다.

import java.util.Random;

public class StrategicBot implements Player
{
    Random rnd;
    String name;
    public StrategicBot(int e) {
        rnd = new Random(); 
        name = "StrategicBot" + rnd.nextInt(1000);

    }

    public String getName()
    {
        return name;
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        double margin = 9.0*votersRemaining/9;
        int maxloc = 0;
        boolean noLead=false;
        for(int i = 1; i< 3; i++)
        {
            for(int j = 1; j < 3; j++)
            {
                if(payoffs[j] + margin > payoffs[i])
                    noLead=true;
            }
            if(payoffs[i] > payoffs[maxloc] && noLead)
            {
                maxloc = i;
            }
            noLead=false;
        }
        return maxloc;
    }

    public void receiveResults(int[] voteCounts, double result) { }
}

2

ExpectorBot

다른 모든 봇이 다른 사람에 대한 평균 지불금을 계산하여 투표하는 방법을 예측하려고합니다. 기본은 최고 보수에 대한 투표이지만, 최고 투표가 예상보다 많으면 나에게 평균 지급보다 더 나은 투표를하고 최악의 배당금이 이길 가능성이 있습니다.

import java.util.Arrays;

public class ExpectorBot implements Player
{
    class Votee
    {
        int index;
        int payoff;
        float avgPayoff;
        float expectedVotes;
    }

    public ExpectorBot( final int e )
    {

    }

    @Override
    public String getName()
    {
        return "ExpectorBot";
    }

    @Override
    public int getVote( final int[] voteCounts, final int votersRemaining, final int[] payoffs, final int[] totalPayoffs )
    {
        final int otherVoters = Arrays.stream( voteCounts ).sum() + votersRemaining;
        final Votee[] v = createVotees( voteCounts, otherVoters, votersRemaining, payoffs, totalPayoffs );

        final Votee best = v[ 0 ]; // Most Payoff
        final Votee second = v[ 1 ];
        final Votee worst = v[ 2 ];

        int voteFor = best.index;

        if( ( second.expectedVotes >= best.expectedVotes + 1 ) // Second has more votes than Best even after I vote
                && ( second.payoff >= second.avgPayoff ) // Second payoff better than average for the others
                && ( worst.expectedVotes >= best.expectedVotes + 0.5f ) ) // Worst has a chance to win
        {
            voteFor = second.index;
        }

        return voteFor;
    }

    private Votee[] createVotees( final int[] voteCounts, final int otherVoters, final int votersRemaining, final int[] payoffs, final int[] totalPayoffs )
    {
        final Votee[] v = new Votee[ 3 ];

        for( int i = 0; i < 3; ++i )
        {
            v[ i ] = new Votee();
            v[ i ].index = i;
            v[ i ].payoff = payoffs[ i ];

            // This is the average payoff for other Players from this Votee
            v[ i ].avgPayoff = (float)( totalPayoffs[ i ] - payoffs[ i ] ) / otherVoters;

            // The expected number of Votes he will get if everyone votes for biggest payoff
            v[ i ].expectedVotes = voteCounts[ i ] + ( votersRemaining * v[ i ].avgPayoff / 100.0f );
        }

        Arrays.sort( v, ( o1, o2 ) -> o2.payoff - o1.payoff );

        return v;
    }

    @Override
    public void receiveResults( final int[] voteCounts, final double result )
    {

    }
}

1

LockBot

"e"를 찾는 외로운 철학자 ...

//He thinks he's the father of democracy, but something's missing....
public class LockBot implements Player {

public LockBot(int i) {
    //One election, 10000000, what's the difference?
}

@Override
public String getName() {
    return "LockBot";
}

@Override
public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs,
        int[] totalPayoffs) {

    double totalPlayers = voteCounts.length + votersRemaining;
    double totalPayoff = totalPlayers * 100;

    //adjust total payoffs to ignore my own
    for( int i = 0; i < totalPayoffs.length; i++){
        totalPayoffs[i] -= payoffs[i];
    }

    //Votes are probably proportional to payoffs
    //So lets just find the highest weight
    double[] expectedOutcome = new double[3];
    for(int i = 0; i< expectedOutcome.length; i++){
        expectedOutcome[i] = (totalPayoffs[i] / totalPayoff) * payoffs[i];
    }

    //Find the highest
    int choice = 0;
    if(expectedOutcome[1] > expectedOutcome[choice]){
        choice = 1;
    }
    if(expectedOutcome[2] > expectedOutcome[choice]){
        choice = 2;
    }




    return choice;
}

@Override
public void receiveResults(int[] voteCounts, double result) {
    // TODO Auto-generated method stub

}

}

0

윈 로즈

당신이 이기면, 나는진다! 간단합니다. 그래서이 봇은 그가 좋아하는 것과 다른 사람들이 싫어하는 것에 투표합니다.

public class WinLose implements Player
{
    public WinLose(int e) { }

    public String getName()
    {
        return "WinLose";
    }
    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        int max = 0;
        for(int i = 1; i< 3; i++)
        {
            if(10*payoffs[i]-totalPayoffs[i] > 10*payoffs[max]-totalPayoffs[max])
            {
                max = i;
            }
        }
        return max;
    }

    public void receiveResults(int[] voteCounts, double result)
    {

    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.