전략적 투표, 게임


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.