Questa è la Sfida quindicinale n. 3. Tema: algoritmi genetici
Questa sfida è un po 'un esperimento. Volevamo vedere cosa potevamo fare, in termini di sfida, con algoritmi genetici. Non tutto può essere ottimale, ma abbiamo fatto del nostro meglio per renderlo accessibile. Se questo funziona, chissà cosa potremmo vedere in futuro. Forse un re genetico della collina?
Le specifiche sono piuttosto lunghe! Abbiamo provato a separare le specifiche in The Basics - il minimo indispensabile che devi sapere per iniziare a giocare con il framework e inviare una risposta - e The Gory Details - le specifiche complete, con tutti i dettagli sul controller, in base alle quali potrebbe scrivere il tuo.
Se hai qualche domanda, sentiti libero di unirti a noi in chat!
Sei un ricercatore in psicologia comportamentale. È venerdì sera e tu e i tuoi colleghi decidete di divertirvi e usare i topi di laboratorio per una piccola corsa di topi. In effetti, prima di attaccarci troppo emotivamente a loro, chiamiamoli esemplari .
Hai allestito una piccola pista per gli esemplari e, per renderlo più interessante, hai messo alcuni muri, trappole e teletrasporto lungo il percorso. Ora, i tuoi esemplari sono ancora topi ... non hanno idea di cosa sia una trappola o un teletrasporto. Tutto ciò che vedono sono alcune cose in diversi colori. Inoltre non hanno alcun tipo di memoria - tutto ciò che possono fare è prendere decisioni in base al loro ambiente attuale. Immagino che la selezione naturale selezionerà gli esemplari che sanno come evitare una trappola da quelli che non lo fanno (questa razza richiederà del tempo ...). Date inizio alle danze! †
† 84.465 esemplari sono stati danneggiati nel fare questa sfida.
Le basi
Questo è un gioco per giocatore singolo (tu e i tuoi colleghi non volevate confondere le popolazioni, quindi ognuna ha costruito la propria pista). La pista di gara è una griglia rettangolare, alta 15 celle e larga 50 celle. Si inizia con 15 campioni su cellule casuali (non necessariamente distinte) sul bordo sinistro (dove x = 0 ). I tuoi campioni dovrebbero cercare di raggiungere l'obiettivo che è qualsiasi cella a x ≥ 49 e 0 ≤ y ≤ 14 (i campioni possono superare il binario a destra). Ogni volta che succede, ottieni un punto. Inizi anche il gioco con 1 punto. Dovresti cercare di massimizzare i tuoi punti dopo 10.000 turni.
I campioni multipli possono occupare la stessa cellula e non interagiranno.
Ad ogni turno, ogni esemplare vede una griglia 5x5 dell'ambiente circostante (con se stesso al centro). Ogni cella di quella griglia conterrà un colore -1
per 15
. -1
rappresenta celle fuori limite. Il tuo esemplare muore se esce dai limiti. Per quanto riguarda gli altri colori, rappresentano celle vuote, trappole, pareti e teletrasporto. Ma il tuo esemplare non sa quale colore rappresenta cosa e nemmeno tu. Ci sono alcuni vincoli però:
- 8 colori rappresenteranno le celle vuote.
- 4 colori rappresenteranno un teletrasporto. Un teletrasporto invierà il campione in una determinata cella all'interno del suo vicinato 9x9. Questo offset sarà lo stesso per tutti i teletrasporto dello stesso colore.
- 2 colori rappresenteranno le pareti. Entrare in un muro è come stare fermi.
- 2 colori rappresenteranno una trappola. Una trappola indica che una delle 9 celle nelle sue immediate vicinanze è letale (non necessariamente la stessa cellula trap). Questo offset sarà lo stesso per tutte le trappole dello stesso colore.
Ora, riguardo a quella selezione naturale ... ogni esemplare ha un genoma, che è un numero con 100 bit. Verranno creati nuovi esemplari riproducendo due esemplari esistenti e quindi mutando leggermente il genoma. Più un esemplare ha successo, maggiori sono le possibilità di riproduzione.
Quindi ecco il tuo compito: scriverai una singola funzione, che riceve come input la griglia di colori 5x5 che un campione vede, così come il suo genoma. La tua funzione restituirà una mossa (Δx, Δy) per il campione, dove Δx e Δy saranno ciascuno uno {-1, 0, 1}
. Non è necessario conservare i dati tra le chiamate di funzione. Ciò include l'uso di generatori di numeri casuali personalizzati. La tua funzione ti verrà fornita con un RNG seminato che sei libero di usare come desideri.
Il punteggio della tua presentazione sarà la media geometrica del numero di punti su 50 tracce casuali. Abbiamo scoperto che questo punteggio è soggetto a una discreta variazione. Pertanto, questi punteggi saranno preliminari . Una volta che questa sfida si esaurirà, verrà annunciata una scadenza. Alla fine della scadenza, verranno scelte casualmente 100 schede e tutte le comunicazioni verranno salvate su queste 100 schede. Sentiti libero di mettere un punteggio stimato nella tua risposta, ma valuteremo noi stessi ogni invio per garantire che nessuno trucchi.
Abbiamo fornito programmi di controllo in una manciata di lingue. Attualmente, puoi scrivere la tua proposta in Python (2 o 3), Ruby , C ++ , C # o Java . Il controller genera le schede, esegue il gioco e fornisce un framework per l'algoritmo genetico. Tutto quello che devi fare è fornire la funzione di spostamento.
Aspetta, quindi cosa faccio esattamente con il genoma?
La sfida è di capirlo!
Dato che gli esemplari non hanno memoria, tutto ciò che hai in un dato turno è una griglia di colori 5x5 che non significa nulla per te. Quindi dovrai usare il genoma per raggiungere l'obiettivo. L'idea generale è che usi parti del genoma per memorizzare informazioni sui colori o sul layout della griglia e il tuo bot basa le sue decisioni sulle informazioni aggiuntive memorizzate nel genoma.
Ora, ovviamente, non è possibile archiviare nulla manualmente. Quindi le informazioni effettivamente memorizzate saranno inizialmente completamente casuali. Ma l'algoritmo genetico selezionerà presto quegli esemplari il cui genoma contiene le informazioni giuste mentre uccide quelli che hanno le informazioni sbagliate. Il tuo obiettivo è trovare una mappatura dai bit del genoma e dal tuo campo visivo a una mossa, che ti permetta di trovare rapidamente un percorso verso l'obiettivo e che si evolva costantemente in una strategia vincente.
Dovrebbero essere sufficienti informazioni per iniziare. Se lo desideri, puoi saltare la sezione successiva e selezionare il tuo controller preferito dall'elenco dei controller in basso (che contiene anche informazioni su come utilizzare quel controller specifico).
Continua a leggere se vuoi tutto ...
I dettagli di Gory
Questa specifica è completa. Tutti i controller devono implementare queste regole.
Tutta la casualità utilizza una distribuzione uniforme, se non diversamente indicato.
Traccia generazione:
- La traccia è una griglia rettangolare, X = 53 celle di larghezza e Y = 15 celle di altezza. Le celle con x ≥ 49 sono celle obiettivo (dove x è a base zero).
- Ogni cellula ha un singolo colore e può essere letale o meno - le cellule non sono letali se non specificato da uno dei tipi di cellule sottostanti.
- Esistono 16 diversi colori di celle, etichettati da
0
a15
, il cui significato cambierà da gioco a gioco. Inoltre,-1
rappresenta le cellule fuori limite - queste sono letali . - Scegli 8 colori casuali . Queste saranno celle vuote (che non hanno alcun effetto).
- Scegli altri 4 colori casuali . Questi sono teletrasporto. Per due di questi colori, scegliere un offset diverso da zero nel vicinato 9x9 (da (-4, -4) a (4,4) tranne (0,0)). Per gli altri due colori, invertire tali offset. Se un campione calpesta un teletrasporto, viene immediatamente spostato da quell'offset.
- Scegli altri 2 colori casuali . Queste sono trappole. Per ciascuno di questi colori, scegli un offset nel vicinato 3x3 (da (-1, -1) a (1,1)). Una trappola indica che la cella a quell'offset è letale . Nota: la stessa cella trap non è necessariamente letale.
- I 2 colori rimanenti sono le pareti, che impediscono il movimento. Il tentativo di spostarsi su una cella a muro trasformerà la mossa in fermo. Le stesse cellule del muro sono letali .
- Per ogni cella non obiettivo della griglia, scegli un colore casuale. Per ogni cella obiettivo scegliere un colore vuoto casuale .
- Per ogni cella sul bordo sinistro della traccia, determinare se l'obiettivo può essere raggiunto entro 100 turni (in base alle regole di ordine dei turni di seguito). In tal caso, questa cella è una cella iniziale ammissibile . Se ci sono meno di 10 celle iniziali, scarta la traccia e generane una nuova.
- Crea 15 esemplari, ognuno con un genoma casuale e un'età di 0 anni . Posizionare ciascun campione su una cella iniziale casuale.
Ordine di svolta:
- I seguenti passaggi verranno eseguiti, in ordine, per ciascun campione. I campioni non interagiscono né si vedono e possono occupare la stessa cellula.
- Se l'età del campione è 100 , muore. Altrimenti, aumenta la sua età di 1.
- Al campione viene assegnato il suo campo visivo - una griglia di colori 5x5, centrata sul campione - e restituisce una mossa nel suo vicinato 3x3. Lo spostamento al di fuori di questo intervallo provoca l'arresto del controller.
- Se la cella di destinazione è un muro, lo spostamento viene modificato in (0,0).
- Se la cella target è un teletrasporto, il campione viene spostato dall'offset del teletrasporto. Nota: questo passaggio viene eseguito una volta , non iterativamente.
- Se la cellula attualmente occupata dal campione (potenzialmente dopo aver usato un teletrasporto) è letale, il campione muore. Questa è l' unica volta in cui i campioni muoiono (a parte il passaggio 1.1 sopra). In particolare, un nuovo esemplare che si genera su una cellula letale non morirà immediatamente, ma ha la possibilità di spostarsi prima dalla cellula pericolosa.
- Se il campione occupa una cella obiettivo, segna un punto, sposta il campione in una cella iniziale casuale e resetta la sua età a 0.
- Se sul tabellone rimangono meno di due esemplari, il gioco termina.
- Crea 10 nuovi esemplari con età 0 . Ogni genoma è determinato (individualmente) dalle seguenti regole di riproduzione. Posizionare ciascun campione su una cella iniziale casuale.
Allevamento:
Quando viene creato un nuovo campione, scegliere due genitori distinti a caso, con una propensione per i campioni che sono progrediti ulteriormente verso destra. La probabilità di scegliere un campione è proporzionale al suo punteggio di fitness corrente . Il punteggio di fitness di un campione è
1 + x + 50 * numero di volte in cui ha raggiunto l'obiettivo
dove x è l'indice orizzontale basato su 0. Gli esemplari creati nello stesso turno non possono essere scelti come genitori.
Dei due genitori, scegline uno casuale da cui prendere il primo bit del genoma.
- Ora mentre cammini lungo il genoma, cambia i genitori con una probabilità di 0,05 e continua a prendere i pezzi dal genitore risultante.
- Muta il genoma completamente assemblato: per ogni bit, capovolgilo con probabilità 0,01 .
punteggio:
- Una partita dura 10.000 turni.
- I giocatori iniziano il gioco con 1 punto (per consentire l'uso della media geometrica).
- Ogni volta che un campione raggiunge l'obiettivo, il giocatore segna un punto.
- Per ora, l'invio di ciascun giocatore verrà eseguito per 50 partite, ognuna con una traccia casuale diversa.
- L'approccio sopra riportato comporta una varianza maggiore di quanto sia desiderabile. Una volta che questa sfida si esaurirà, verrà annunciata una scadenza. Alla fine della scadenza, verranno scelte casualmente 100 schede e tutte le comunicazioni verranno salvate su queste 100 schede.
- Il punteggio complessivo di un giocatore è la media geometrica dei punteggi di questi singoli giochi.
I controller
È possibile scegliere uno dei seguenti controller (poiché sono funzionalmente equivalenti). Li abbiamo testati tutti, ma se trovi un bug, vuoi migliorare il codice o le prestazioni o aggiungere una funzionalità come l'output grafico, invia un problema o invia una richiesta pull su GitHub! Puoi anche aggiungere un nuovo controller in un'altra lingua!
Fare clic sul nome della lingua per ciascun controller per accedere alla directory corretta su GitHub, che contiene una README.md
con istruzioni d'uso esatte.
Se non hai familiarità con git e / o GitHub, puoi scaricare l'intero repository come ZIP dalla prima pagina (vedi il pulsante nella barra laterale).
Pitone
- Più accuratamente testato. Questa è la nostra implementazione di riferimento.
- Funziona con Python 2.6+ e Python 3.2+!
- È molto lento. Si consiglia di eseguirlo con PyPy per un notevole aumento di velocità.
- Supporta l'output grafico usando
pygame
otkinter
.
Rubino
- Testato con Ruby 2.0.0. Dovrebbe funzionare con le versioni più recenti.
- È anche abbastanza lento, ma Ruby può essere utile per la prototipazione di un'idea per una presentazione.
C ++
- Richiede C ++ 11.
- Opzionalmente supporta il multithreading.
- Di gran lunga il controller più veloce del gruppo.
C #
- Utilizza LINQ, quindi richiede .NET 3.5.
- Piuttosto lento.
Giava
- Non particolarmente lento. Non particolarmente veloce.
Classifica preliminare
Tutti i punteggi sono preliminari. Tuttavia, se qualcosa è chiaramente sbagliato o obsoleto, per favore fatemi sapere. Il nostro esempio di presentazione è elencato per il confronto, ma non in contesa.
Score | # Games | User | Language | Bot
===================================================================================
2914.13 | 2000 | kuroi neko | C++ | Hard Believers
1817.05097| 1000 | TheBestOne | Java | Running Star
1009.72 | 2000 | kuroi neko | C++ | Blind faith
782.18 | 2000 | MT0 | C++ | Cautious Specimens
428.38 | | user2487951 | Python | NeighborsOfNeighbors
145.35 | 2000 | Wouter ibens | C++ | Triple Score
133.2 | | Anton | C++ | StarPlayer
122.92 | | Dominik Müller | Python | SkyWalker
89.90 | | aschmack | C++ | LookAheadPlayer
74.7 | | bitpwner | C++ | ColorFarSeeker
70.98 | 2000 | Ceribia | C++ | WallGuesser
50.35 | | feersum | C++ | Run-Bonus Player
35.85 | | Zgarb | C++ | Pathfinder
(34.45) | 5000 | Martin Büttner | <all> | ColorScorePlayer
9.77 | | DenDenDo | C++ | SlowAndSteady
3.7 | | flawr | Java | IAmARobotPlayer
1.9 | | trichoplax | Python | Bishop
1.04 | 2000 | fluffy | C++ | Gray-Color Lookahead
Crediti
Questa sfida è stata un enorme sforzo di collaborazione:
- Nathan Merril: ha scritto controller Python e Java. Trasformato il concetto di sfida da King of the Hill a Rat Race.
- trichoplax: Playtesting. Ha funzionato sul controller Python.
- feersum: ha scritto controller C ++.
- VisualMelon: ha scritto il controller C #.
- Martin Büttner: Concept. Ha scritto controller Ruby. Playtesting. Ha funzionato sul controller Python.
- T Abraham: Playtest. Testato Python e rivisto C # e controller C ++.
Tutti gli utenti di cui sopra (e probabilmente un altro paio che ho dimenticato) hanno contribuito alla progettazione complessiva della sfida.
Aggiornamento controller C ++
Se si utilizza C ++ con Visual Studio e il multithreading, è necessario ottenere l' ultimo aggiornamento a causa di un bug con il seeding del generatore di numeri casuali che consente la produzione di schede duplicate.
'In particular, a new specimen which spawns on a lethal cell will not die immediately, but has a chance to move off the dangerous cell first.'