Neste desafio, você jogará o dilema do prisioneiro ruidoso e iterado.
O dilema do prisioneiro é um cenário na teoria dos jogos em que existem dois jogadores, cada um com duas opções: cooperar ou defeito. Cada jogador se sai melhor se desertar do que cooperar, mas ambos preferem o resultado em que os dois cooperam com aquele em que os dois desertam.
O dilema do prisioneiro iterado é o mesmo jogo, exceto que você joga contra o mesmo oponente repetidamente e sabe o que o seu oponente jogou no passado. Seu objetivo é sempre acumular a maior pontuação para si mesmo, independentemente de como o seu oponente o faz.
O dilema ruidoso do prisioneiro iterado introduz algum ruído na comunicação. Seu conhecimento do que seu oponente jogou no passado terá algum ruído introduzido. Você também saberá quais movimentos você fez no passado. A taxa de ruído é constante durante uma rodada contra o mesmo oponente, mas diferente entre rodadas diferentes.
Desafio
Neste desafio, você escreverá um programa Python 3 para reproduzir o dilema ruidoso do prisioneiro iterado.
Seu programa receberá três entradas:
Seus próprios movimentos, sem movimentos aleatórios aplicados.
Os movimentos do seu oponente, com movimentos aleatórios aplicados.
Uma variável de estado, que começa como uma lista vazia a cada rodada e que você pode modificar se desejar. Você pode ignorar isso se não quiser usá-lo.
Seu programa deve produzir 'c'
para cooperar ou 'd'
desertar.
Por exemplo, aqui está um programa que coopera se o oponente cooperou pelo menos 60% do tempo no passado, após a aplicação de movimentos aleatórios e nos 10 primeiros movimentos:
def threshold(my_plays, their_flipped_plays, state):
if len(their_flipped_plays) < 10:
return 'c'
opp_c_freq = their_flipped_plays.count('c')/len(their_flipped_plays)
if opp_c_freq > 0.6:
return 'c'
else:
return 'd'
Se você não conhece o Python, escreva sua submissão em pseudocódigo, e alguém (eu ou outro membro do site) pode criar o programa Python correspondente.
Jogabilidade
O corredor do torneio pode ser encontrado aqui: jogo barulhento . Corra noisy-game.py
para executar o torneio. Manterei esse repositório atualizado com novos envios. Programas de exemplo podem ser encontrados em basic.py
.
A pontuação geral de um programa é o total de sua pontuação em mais de 100 jogadas.
Um jogo consiste em confrontos round-robin de cada jogador contra cada jogador, incluindo ele próprio. Uma partida consiste em 100 rodadas. Uma rodada consiste em 300 jogadas, cada uma das quais envolve saída 'c'
ou 'd'
.
Seu envio fará uma comparação com todos os envios, incluindo o seu. Cada confronto será composto de 100 rodadas. Durante cada rodada, uma probabilidade de inversão será escolhida uniformemente aleatoriamente [0, 0.5]
.
Cada rodada consistirá em 300 jogadas. Em cada movimento, os dois programas receberão todas as reproduções anteriores que tentaram e todas as reproduções anteriores que o outro programa fez, após a aplicação dos lançamentos, e uma variável de estado, que é uma lista mutável que o programa pode modificar, se desejar. Os programas produzirão seus movimentos.
Os movimentos são pontuados da seguinte forma: Se um programa toca a 'c'
, o programa adversário recebe 2 pontos. Se um programa toca a 'd'
, esse programa recebe 1 ponto.
Então, cada movimento é invertido independentemente, com probabilidade igual à probabilidade de inverter, e armazenado para exibição ao oponente.
Depois que todas as rodadas foram disputadas, somamos o número de pontos que cada jogador obteve em cada partida. Em seguida, usamos o seguinte sistema de pontuação para calcular a pontuação de cada jogador para o jogo. Essa pontuação é realizada após a conclusão de todos os confrontos.
Pontuação
Usaremos a pontuação evolutiva. Cada programa começa com o mesmo peso. Em seguida, os pesos são atualizados da seguinte forma, para 100 iterações, usando os totais de pontos do jogo:
O novo peso de cada programa é proporcional ao produto do seu peso anterior e ao seu total médio de pontos, ponderado pelos pesos de seus oponentes.
São aplicadas 100 atualizações desse tipo e os pesos finais são a pontuação de cada programa para a execução do jogo.
A pontuação geral será a soma de mais de 100 corridas do jogo.
Os jogadores terão todas as respostas válidas para esse desafio, além de seis programas básicos para começar.
Ressalvas
Não modifique as entradas. Não tente afetar a execução de nenhum outro programa, exceto através da cooperação ou defeito. Não faça uma submissão sacrificial que tente reconhecer outra submissão e beneficiar esse oponente às suas próprias custas. As brechas padrão são proibidas.
EDIT: Os envios não podem duplicar exatamente nenhum dos programas básicos ou envios anteriores.
Se você tiver alguma dúvida não hesite em perguntar.
Resultados atuais
nicht_genug: 40.6311
stealer: 37.1416
enough: 14.4443
wait_for_50: 6.947
threshold: 0.406784
buckets: 0.202875
change_of_heart: 0.0996783
exploit_threshold: 0.0670485
kickback: 0.0313357
tit_for_stat: 0.0141368
decaying_memory: 0.00907645
tit_for_whoops: 0.00211803
slider: 0.00167053
trickster: 0.000654875
sounder: 0.000427348
tit_for_tat: 9.12471e-05
stubborn_stumbler: 6.92879e-05
tit_for_time: 2.82541e-05
jedi2sith: 2.0768e-05
cooperate: 1.86291e-05
everyThree: 1.04843e-05
somewhat_naive: 4.46701e-06
just_noise: 1.41564e-06
growing_distrust: 5.32521e-08
goldfish: 4.28982e-09
vengeful: 2.74267e-09
defect: 3.71295e-10
alternate: 2.09372e-20
random_player: 6.74361e-21
Resultados com apenas respostas a esta pergunta e programas básicos que ignoram a jogada do oponente:
nicht_genug: 39.3907
stealer: 33.7864
enough: 20.9032
wait_for_50: 5.60007
buckets: 0.174457
kickback: 0.0686975
change_of_heart: 0.027396
tit_for_stat: 0.024522
decaying_memory: 0.0193272
tit_for_whoops: 0.00284842
slider: 0.00153227
sounder: 0.000472289
trickster: 0.000297515
stubborn_stumbler: 3.76073e-05
cooperate: 3.46865e-05
tit_for_time: 2.42263e-05
everyThree: 2.06095e-05
jedi2sith: 1.62591e-05
somewhat_naive: 4.20785e-06
just_noise: 1.18372e-06
growing_distrust: 6.17619e-08
vengeful: 3.61213e-09
goldfish: 3.5746e-09
defect: 4.92581e-10
alternate: 6.96497e-20
random_player: 1.49879e-20
Ganhando
A competição permanecerá aberta indefinidamente, à medida que novos envios forem publicados. No entanto, declararei um vencedor (aceite uma resposta) com base nos resultados 1 mês após a postagem desta pergunta.
fonte
exploit_threshold()
várias vezes comoexploit_threshold1()
, etc e os adicionei àplayers
lista. Por que obtenho resultados muito diferentes para estratégias idênticas?Respostas:
Genug ist nicht genug
(também pode ser chamado
enough2
oustealback
)Aprendi que o tit original para duas tatuagens esperava duas tatuagens consecutivas, como
tit_for_whoops
parece, e de fato parece que devemos perdoar e esquecer (bem, quase ...) as tatuagens únicas anteriores. E muitos jogadores desertam nas últimas rodadas. Eu ainda prefiro ser legal quando tudo está bem até agora, mas a barra de tolerância do bot continua diminuindo.fonte
Chapim-para-Ops
Inspirado por uma estratégia do ncase.me/trust
Defeitos somente se o outro jogador desertou duas vezes seguidas, para evitar mal-entendidos.
fonte
Mudança de Coração
Tem uma mudança de coração no meio. Surpreendentemente bem.
fonte
Ladrão de estratégia
Inspirado pelo suficiente, change_of_heart e tit-for-whoops. Deveria ser um pouco mais perdoador. Tentei ajustar os números para obter melhores resultados, mas eles não queriam mudar muito.
fonte
Peitos-Por-Tempo
Se você passou a maior parte do tempo me machucando, eu vou te machucar de volta. Provavelmente.
fonte
Desconfiança crescente
Quanto mais o oponente me trai, menos posso confiar que era apenas barulho.
fonte
state
argumento de que, por padrão, é uma lista? As listas são mutáveis, portanto o estado pode ser modificado facilmente.Jedi2Sith
Começa de maneira agradável e altruísta, mas com o tempo a influência do lado sombrio aumenta cada vez mais, até o ponto sem retorno. Não há como parar essa influência, mas todas as coisas ruins que vê acontecendo contribuem para o poder do lado sombrio ...
Experimente online!
fonte
Slider
Começa com 'c' e desliza gradualmente na direção ou fora de 'd'.
fonte
Tropeço Teimoso
Com base na sua estratégia de limite de exploração, com apenas jogadas consistentes, acompanhadas para alternar entre defeito e principalmente cooperar
UPDATE: Mantém o controle de duas jogadas consecutivas e três consecutivas, punindo apenas sob condições mais severas e adicionando uma escolha aleatória quando não tiver certeza
ATUALIZAÇÃO 2: condição removida e função de distribuição adicionada
fonte
Noise Bot
Estou definitivamente cooperar bot. Isso é apenas barulho.
fonte
Já é suficiente
Começa como tit para duas tatuagens em que as duas tatuagens não precisam ser consecutivas (ao contrário
tit_for_whoops
). Se tiver que jogar comd
muita frequência, ele serád
total.fonte
Goldfish Bot
Um peixe dourado nunca perdoa, mas esquece rapidamente.
fonte
fonte
Memória deteriorada
Pesa mais a história recente. Lentamente esquece o passado.
fonte
Kickback
Algumas idéias vagas ...
fonte
Realmente não recebe toda a coisa do "ruído"
Nunca perdoa um traidor.
fonte
sirene:
editar: retaliação adicionada em cenários provavelmente com pouco ruído
basicamente, se todos os quatro primeiros movimentos forem cooperados, isso significa que devemos esperar menos ruído do que o habitual. desertar um pouco de vez em quando para compensar os menos pontos que obteríamos por nunca desertar, e poder ser responsabilizado pelo ruído. também retaliamos se eles desertarem contra nós
se o nosso oponente faz muita deserção nesses turnos (2 ou mais), nós apenas desaprovamos. se fosse apenas barulho, o barulho afetaria nossos movimentos de qualquer maneira.
caso contrário, se apenas um movimento tiver sido defeituoso, nós apenas fazemos uma análise simples pelo resto do jogo.
fonte
Alternar
Escolhe aleatoriamente no primeiro turno e depois alterna. Sempre defeitos nas últimas 10 rodadas.
fonte
Aguarde 50
Após 50 defeitos, vamos tê-lo!
fonte
Somehwat ingênuo
Eu assumirei que, se você desertou menos do que a probabilidade de virar (aproximadamente) nas últimas n voltas, era ruído e não que você seja malvado!
Ainda não descobriu o melhor n , pode se aprofundar nisso.
fonte
A cada três
Defeitos a cada três turnos, independentemente. Também falha nos últimos 50 turnos. Também desertará se o seu oponente tiver desertado em 4 dos 5 dos últimos rounds.
fonte
Baldes
É bom começar. Observa os últimos 20, se <25% d, retorna c,> 75% d, retorna d e entre escolhe aleatoriamente ao longo de uma função de probabilidade linear. Últimos 50, defeitos. Teve isso no último 10, mas viu muitos dos últimos 50 defeitos.
Primeira vez aqui, então deixe-me saber se algo precisa ser corrigido (ou como posso testar isso).
fonte
players
para fazer iterações rápidas.Tit-For-Stat
Defeitos se o oponente desertou mais da metade do tempo.
fonte