Este es el desafío quincenal # 3. Tema: Algoritmos Genéticos
Este desafío es un poco un experimento. Queríamos ver qué podíamos hacer, a nivel de desafío, con algoritmos genéticos. Puede que no todo sea óptimo, pero hicimos todo lo posible para que fuera accesible. Si esto funciona, quién sabe lo que podríamos ver en el futuro. ¿Quizás un genético Rey de la colina?
¡La especificación es bastante larga! Hemos tratado de separar la especificación en The Basics, lo mínimo que necesita saber para comenzar a jugar con el marco y enviar una respuesta, y The Gory Details, la especificación completa, con todos los detalles sobre el controlador, según los cuales usted podría escribir el tuyo
Si tiene alguna pregunta, ¡no dude en unirse a nosotros en el chat!
Eres investigador en psicología del comportamiento. Es viernes por la noche y usted y sus colegas deciden divertirse y usar sus ratas de laboratorio para una pequeña carrera de ratas. De hecho, antes de que nos apeguemos demasiado a ellos, llamémosles especímenes .
Has configurado una pequeña pista de carreras para los especímenes, y para hacerlo más interesante, has puesto algunas paredes, trampas y teletransportadores en la pista. Ahora, tus especímenes siguen siendo ratas ... no tienen idea de qué es una trampa o un teletransportador. Todo lo que ven es algunas cosas en diferentes colores. Tampoco tienen ningún tipo de memoria: todo lo que pueden hacer es tomar decisiones basadas en su entorno actual. Supongo que la selección natural seleccionará los especímenes que saben cómo evitar una trampa de los que no lo hacen (esta carrera llevará un tiempo ...). ¡Que empiecen los juegos! †
† 84,465 especímenes fueron dañados en la realización de este desafío.
Los basicos
Este es un juego para un solo jugador (usted y sus colegas no querían mezclar las poblaciones, por lo que cada uno construyó su propia pista de carreras). La pista de carreras es una cuadrícula rectangular, 15 celdas de alto y 50 celdas de ancho. Comienza con 15 muestras en celdas aleatorias (no necesariamente distintas) en el borde izquierdo (donde x = 0 ). Sus muestras deben tratar de alcanzar la meta que es cualquier celda en x ≥ 49 y 0 ≤ y ≤ 14 (las muestras pueden sobrepasar la pista a la derecha). Cada vez que esto sucede, obtienes un punto. También comienzas el juego con 1 punto. Debes intentar maximizar tus puntos después de 10,000 turnos.
Varias muestras pueden ocupar la misma celda y no interactuarán.
En cada turno, cada espécimen ve una cuadrícula de 5x5 de su entorno (consigo mismo en el centro). Cada celda de esa cuadrícula contendrá un color -1
para 15
. -1
representa celdas que están fuera de los límites. Su espécimen muere si se sale de los límites. En cuanto a los otros colores, representan celdas vacías, trampas, paredes y teletransportadores. Pero su espécimen no sabe qué color representa qué y usted tampoco. Sin embargo, hay algunas limitaciones:
- 8 colores representarán celdas vacías.
- 4 colores representarán un teletransportador. Un teletransportador enviará el espécimen a cierta celda dentro de su vecindario 9x9. Este desplazamiento será el mismo para todos los teletransportadores del mismo color.
- 2 colores representarán las paredes. Entrar en una pared es lo mismo que quedarse quieto.
- 2 colores representarán una trampa. Una trampa indica que una de las 9 celdas en su vecindad inmediata es letal (no necesariamente la celda de trampa en sí). Este desplazamiento será el mismo para todas las trampas del mismo color.
Ahora, sobre esa selección natural ... cada espécimen tiene un genoma, que es un número con 100 bits. Se crearán nuevos especímenes cruzando dos especímenes existentes y luego mutando ligeramente el genoma. Cuanto más exitoso es un espécimen, mayor es la posibilidad de reproducción.
Así que aquí está tu tarea: escribirás una sola función, que recibe como entrada la cuadrícula de colores de 5x5 que ve un espécimen, así como su genoma. Su función devolverá un movimiento (Δx, Δy) para la muestra, donde Δx y Δy serán cada uno de ellos {-1, 0, 1}
. No debe persistir ningún dato entre llamadas a funciones. Esto incluye el uso de sus propios generadores de números aleatorios. Su función se proporcionará con un RNG sembrado que puede usar libremente como desee.
La puntuación de su envío será la media geométrica del número de puntos en 50 pistas aleatorias. Hemos encontrado que este puntaje está sujeto a un poco de variación. Por lo tanto, estos puntajes serán preliminares . Una vez que este desafío desaparezca, se anunciará una fecha límite. Al final de la fecha límite, se elegirán 100 tableros al azar, y todas las presentaciones se volverán a calificar en estos 100 tableros. Siéntase libre de poner un puntaje estimado en su respuesta, pero nosotros calificaremos cada envío para asegurarnos de que nadie haga trampa.
Hemos proporcionado programas de controlador en un puñado de idiomas. Actualmente, puede escribir su envío en Python (2 o 3), Ruby , C ++ , C # o Java . El controlador genera los tableros, ejecuta el juego y proporciona un marco para el algoritmo genético. Todo lo que tiene que hacer es proporcionar la función de movimiento.
Espera, ¿qué hago exactamente con el genoma?
¡El desafío es resolver eso!
Como los especímenes no tienen memoria, todo lo que tienes en un turno dado es una cuadrícula de colores 5x5 que no significa nada para ti. Entonces tendrás que usar el genoma para alcanzar la meta. La idea general es que use partes del genoma para almacenar información sobre los colores o el diseño de la cuadrícula, y su bot basa sus decisiones en la información adicional almacenada en el genoma.
Ahora, por supuesto, no puedes almacenar nada allí manualmente. Entonces, la información real almacenada allí inicialmente será completamente aleatoria. Pero el algoritmo genético pronto seleccionará aquellos especímenes cuyo genoma contenga la información correcta y eliminará aquellos que tengan la información incorrecta. Su objetivo es encontrar un mapeo de los bits del genoma y su campo de visión a un movimiento, lo que le permite encontrar un camino hacia la meta rápidamente y que evoluciona constantemente hacia una estrategia ganadora.
Esto debería ser suficiente información para comenzar. Si lo desea, puede omitir la siguiente sección y seleccionar su controlador de elección de la lista de controladores en la parte inferior (que también contiene información sobre cómo usar ese controlador en particular).
Sigue leyendo si quieres todo ...
Los detalles sangrientos
Esta especificación está completa. Todos los controladores tienen que implementar estas reglas.
Toda aleatoriedad utiliza una distribución uniforme, a menos que se indique lo contrario.
Generación de pistas:
- La pista es una cuadrícula rectangular, X = 53 celdas de ancho e Y = 15 celdas de alto. Las celdas con x ≥ 49 son celdas objetivo (donde x está basado en cero).
- Cada celda tiene un solo color y puede o no ser letal : las celdas no son letales a menos que se especifique por uno de los tipos de celdas a continuación.
- Hay 16 colores de celda diferentes, etiquetados de
0
a15
, cuyo significado cambiará de un juego a otro. Además,-1
representa celdas que están fuera de los límites: estas son letales . - Elige 8 colores al azar . Estas serán celdas vacías (que no tienen efecto).
- Elige 4 colores más al azar . Estos son teletransportadores. Para dos de estos colores, elija un desplazamiento distinto de cero en la vecindad 9x9 (de (-4, -4) a (4,4) excepto (0,0)). Para los otros dos colores, invierta esos desplazamientos. Si un espécimen pisa un teletransportador, ese desplazamiento lo mueve inmediatamente.
- Elige 2 colores más al azar . Estas son trampas. Para cada uno de estos colores, elija un desplazamiento en el vecindario 3x3 (de (-1, -1) a (1,1)). Una trampa indica que la celda en ese desplazamiento es letal . Nota: La celda trampa no es necesariamente letal.
- Los 2 colores restantes son paredes, que impiden el movimiento. Intentar pasar a una celda de pared convertirá el movimiento en quedarse quieto. Las células de la pared son letales .
- Para cada celda sin objetivo de la cuadrícula, elija un color aleatorio. Para cada celda objetivo, elija un color vacío aleatorio .
- Para cada celda en el borde izquierdo de la pista, determine si se puede alcanzar el objetivo dentro de los 100 turnos (de acuerdo con las reglas de orden de turno a continuación). Si es así, esta celda es una celda inicial admisible . Si hay menos de 10 celdas iniciales, descarte la pista y genere una nueva.
- Cree 15 especímenes, cada uno con un genoma aleatorio y edad 0 . Coloque cada muestra en una celda inicial aleatoria.
Orden de giro:
- Se realizarán los siguientes pasos, en orden, para cada muestra. Las muestras no interactúan ni se ven, y pueden ocupar la misma celda.
- Si la edad del espécimen es de 100 años , muere. De lo contrario, incremente su antigüedad en 1.
- Al espécimen se le da su campo de visión, una cuadrícula de colores de 5x5, centrada en el espécimen, y devuelve un movimiento en su vecindario de 3x3. Los movimientos fuera de este rango harán que el controlador termine.
- Si la celda objetivo es un muro, entonces el movimiento se cambia a (0,0).
- Si la celda objetivo es un teletransportador, la muestra se mueve por el desplazamiento del teletransportador. Nota: Este paso se realiza una vez , no de forma iterativa.
- Si la celda actualmente ocupada por la muestra (potencialmente después de usar un teletransportador) es letal, la muestra muere. Este es el único momento en que mueren las muestras (aparte del paso 1.1. Anterior). En particular, un nuevo espécimen que se genera en una célula letal no morirá de inmediato, pero tiene la oportunidad de salir de la célula peligrosa primero.
- Si el espécimen ocupa una celda objetivo, anote un punto, mueva el espécimen a una celda inicial aleatoria y restablezca su edad a 0.
- Si quedan menos de dos especímenes en el tablero, el juego termina.
- Crea 10 nuevos especímenes con edad 0 . Cada genoma está determinado (individualmente) por las siguientes reglas de reproducción. Coloque cada muestra en una celda inicial aleatoria.
Cría:
Cuando se crea un nuevo espécimen, elija dos padres distintos al azar, con un sesgo hacia los especímenes que han progresado más hacia la derecha. La probabilidad de que se elija un espécimen es proporcional a su puntaje actual de aptitud . El puntaje de aptitud física de un espécimen es
1 + x + 50 * número de veces que alcanzó la meta
donde x es el índice horizontal basado en 0. Las muestras creadas en el mismo turno no se pueden elegir como padres.
De los dos padres, elija uno aleatorio para tomar el primer bit del genoma.
- Ahora, a medida que camina por el genoma, cambie de padres con una probabilidad de 0.05 y continúe tomando fragmentos del padre resultante.
- Muta el genoma completamente ensamblado: para cada bit, voltéalo con probabilidad 0.01 .
Puntuación:
- Un juego dura 10,000 turnos.
- Los jugadores comienzan el juego con 1 punto (para permitir el uso de la media geométrica).
- Cada vez que un espécimen alcanza la meta, el jugador anota un punto.
- Por ahora, la presentación de cada jugador se ejecutará durante 50 juegos, cada uno con una pista aleatoria diferente.
- El enfoque anterior da como resultado más varianza de la que es deseable. Una vez que este desafío desaparezca, se anunciará una fecha límite. Al final de la fecha límite, se elegirán 100 tableros al azar, y todas las presentaciones se volverán a calificar en estos 100 tableros.
- El puntaje general de un jugador es la media geométrica de los puntajes de estos juegos individuales.
Los controladores
Puede elegir cualquiera de los siguientes controladores (ya que son funcionalmente equivalentes). Los hemos probado todos, pero si detecta un error, desea mejorar el código o el rendimiento, o agregar una característica como salida gráfica, envíe un problema o envíe una solicitud de extracción en GitHub. ¡También puedes agregar un nuevo controlador en otro idioma!
Haga clic en el nombre del idioma de cada controlador para acceder al directorio correcto en GitHub, que contiene README.md
instrucciones de uso exactas.
Si no está familiarizado con git y / o GitHub, puede descargar todo el repositorio como un ZIP desde la página principal (vea el botón en la barra lateral).
Pitón
- Más a fondo probado. Esta es nuestra implementación de referencia.
- ¡Funciona con Python 2.6+ y Python 3.2+!
- Es muy lento. Recomendamos ejecutarlo con PyPy para una aceleración sustancial.
- Admite salida gráfica usando
pygame
otkinter
.
Rubí
- Probado con Ruby 2.0.0. Debería funcionar con versiones más nuevas.
- También es bastante lento, pero Ruby puede ser conveniente para crear prototipos de una idea para una presentación.
C ++
- Requiere C ++ 11.
- Opcionalmente admite subprocesos múltiples.
- De lejos, el controlador más rápido del grupo.
C#
- Utiliza LINQ, por lo que requiere .NET 3.5.
- Bastante lento.
Java
- No particularmente lento. No particularmente rápido.
Tabla de clasificación preliminar
Todos los puntajes son preliminares. Sin embargo, si algo está simplemente mal o desactualizado, avíseme. Nuestro envío de ejemplo está en la lista para comparación, pero no en contienda.
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
Créditos
Este desafío fue un gran esfuerzo de colaboración:
- Nathan Merril: Escribió controladores de Python y Java. Convirtió el concepto de desafío de un rey de la colina en una carrera de ratas.
- trichoplax: Playtesting . Trabajó en el controlador Python.
- feersum: escribió el controlador C ++.
- VisualMelon: escribió el controlador C #.
- Martin Büttner: Concepto. Escribió el controlador Ruby. Pruebas de juego. Trabajó en el controlador Python.
- T Abraham: Pruebas de juego. Probé Python y revisé el controlador C # y C ++.
Todos los usuarios anteriores (y probablemente un par más que olvidé) han contribuido al diseño general del desafío.
Actualización del controlador C ++
Si está utilizando C ++ con Visual Studio y subprocesos múltiples, debería obtener la última actualización debido a un error con su generación de generador de números aleatorios que permite la producción de tableros duplicados.
'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.'