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.
fuente
'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.'
Respuestas:
La fe ciega - C ++ - parece anotar por encima de 800 (!) En 2000 carreras
Genoma de codificación de colores con una misteriosa respuesta de pista y un disuasivo eficaz para golpear la pared
Resultados de muestra:
Basado en la prueba involuntariamente larga de feersum, creo que 2000 carreras son suficientes para producir un resultado aceptablemente estable.
Como mi controlador modificado muestra la media geométrica actual después de cada ejecución, confirme visualmente que la variación en las últimas 50 ejecuciones fue relativamente pequeña (+ - 10 puntos).
Lo que hace que estos bichos funcionen
En lugar de dar prioridades iguales a cada color, considero estos valores posibles:
Aunque soy demasiado vago para cambiarle el nombre, esto es más bien un "detector de peligro" que indica la ubicación (supuesta) de una trampa real, una pared, un teletransportador esperando enviar al vagabundo desprevenido a un lugar desagradable o incluso la entrada de un muerto -fin. En resumen, un lugar donde una rata sabia preferiría no ir.
Los genes buenos o malos solo requieren 2 bits para almacenar (por ejemplo
11
y10
), pero las trampas requieren 4 bits (0ttt
dondettt
representa una de las 8 posibles ubicaciones "peligrosas").Para mantener cada gen consistente (es decir, que conserva su significado después sido mezclados en un genoma completamente diferente, que requiere que cada gen de codificación por colores para estar en una ubicación fija), todos los valores se codifican en 4 bits (por lo bueno se codifica como
11xx
y mala como10xx
), para un total de 16 * 4 = 64 bits.Los 36 bits restantes se usan como "anti-wall-bangers" (más sobre eso más adelante). Los 25 colores circundantes se combinan en un índice de estos 36 bits. Cada bit indica una dirección vertical preferida (arriba o abajo), que se utiliza cuando hay una posible elección entre dos celdas.
La estrategia es la siguiente:
Roedores, he aquí los enemigos de tu clase.
Lo peor que le puede pasar a una población es no haber producido ningún ganador todavía, pero muchas ratas se pegaron contra una pared o dentro de un bucle infinito de teletransportación lo suficientemente cerca del objetivo para tener una oportunidad dominante de ser seleccionado para la cría .
A diferencia de las ratas que son aplastadas en una trampa o teletransportadas a las paredes, estos roedores solo serán asesinados por la vejez.
No tienen una ventaja competitiva sobre sus primos atascados en 3 células desde el principio, pero tendrán tiempo suficiente para reproducirse generación tras generación de cretinas hasta que su genoma se vuelva dominante, dañando así la diversidad genética sin ninguna buena razón.
Para mitigar este fenómeno, la idea es hacer que los descendientes de estas ratas malas y malas tengan más probabilidades de evitar seguir los pasos de su ascendencia.
La indicación de dirección vertical es de solo 1 bit de largo (básicamente diciendo "intente subir o bajar primero en este entorno"), y es probable que bastantes bits tengan un efecto en el camino seguido, por lo que las mutaciones y / o cruces deberían tener un Impacto significativo.
Muchas de las crías tendrán un comportamiento diferente y no terminarán golpeándose la cabeza contra la misma pared (entre los cadáveres de sus ancestros hambrientos).
Lo importante aquí es que esta indicación no es el factor dominante en el comportamiento de la rata. La interpretación del color seguirá prevaleciendo en la mayoría de los casos (la opción arriba / abajo solo importará si de hecho hay dos "buenas"y lo que la rata ve como un color inofensivo no es un teletransportador esperando para lanzarlo a la pared).
¿Por qué (parece) funcionar?
Todavía no sé exactamente por qué.
El golpe de suerte absoluto que sigue siendo un misterio sin resolver es la lógica de mapeo de trampas. Es sin duda la piedra angular del éxito, pero funciona de manera misteriosa.
Con la codificación utilizada, un genoma aleatorio producirá 25% de identificadores de color "buenos", 25% "malos" y 50% "trampa".
los identificadores de "trampa" a su vez producirán estimaciones "buenas" y "malas" en correlación con el entorno 5x5.
Como resultado, una rata en un lugar determinado "verá" el mundo como una mezcla de colores estables y contextuales "ir / no ir".
Como parece indicar el mecanismo anti-golpes bastante exitoso, el peor tipo de elemento en la pista es el muro temido (y su primo el bucle de teletransportación, pero supongo que estos son mucho menos comunes).
La conclusión es que un programa exitoso debe, sobre todo, lograr evolucionar ratas capaces de detectar posiciones que conduzcan a una inanición lenta sin alcanzar la meta.
Incluso sin "adivinar" los dos colores que representan las paredes, los colores de la "trampa" parecen contribuir a evitar la pared al permitir que una rata evite algunos obstáculos no porque "vio" las paredes, sino porque la estimación de la "trampa" descartó estos células de pared particulares en estos entornos particulares.
Aunque la rata intenta moverse hacia la meta (lo que podría llevar a pensar que los indicadores de trampa más "útiles" son los que indican un peligro en el frente), creo que todas las direcciones de la trampa tienen aproximadamente la misma influencia: una trampa que indica "peligro detrás" "2 celdas ubicadas frente a una rata tienen la misma influencia que una que indica" peligro por delante "cuando la rata se encuentra justo encima de ella.
Desafortunadamente, por qué esta mezcla tiene la propiedad de hacer que el genoma converja tan exitosamente está más allá de mis matemáticas.
Me siento más cómodo con el disuasivo para golpear la pared. Esto funcionó según lo planeado, aunque muy por encima de mis expectativas (el puntaje se multiplicó básicamente por cuatro).
Pirateé el controlador fuertemente para mostrar algunos datos. Aquí hay un par de carreras:
Aquí apareció una raza de súper rata temprano (la pista probablemente permitió correr en línea recta y alguna rata afortunada en las primeras generaciones tenía el ADN correcto para aprovecharla). El número de especímenes al final es aproximadamente la mitad del máximo teórico de unas 100.000 ratas, lo que significa que casi la mitad de las criaturas adquirieron la capacidad de sobrevivir a esta pista en particular indefinidamente (!).
Por supuesto, la puntuación resultante es simplemente obscena, por cierto, al igual que el tiempo de cálculo.
Aquí podemos ver el refinamiento del genoma en el trabajo. El linaje entre los dos últimos genomas aparece claramente. Las buenas y malas evaluaciones son las más significativas. Las indicaciones de la trampa parecen oscilar hasta que se estabilizan en una trampa "útil" o mutan en buenas o malas .
Parece que los genes de color tienen algunas características útiles:
(un color específico debe ser manejado de una manera específica)
Cada codificación de color puede ser arrojada a un genoma completamente diferente sin cambiar drásticamente el comportamiento, a menos que el color sea realmente decisivo (típicamente una pared o un teletransportador que conduce a un bucle infinito).
Este es menos el caso con una codificación de prioridad básica, ya que el color más prioritario es la única información utilizada para decidir dónde moverse. Aquí todos los colores "buenos" son iguales, por lo que un color dado agregado a la lista "buena" tendrá menos impacto.
la codificación buena / mala tiene solo 2 bits significativos de 4, y la ubicación de la trampa puede cambiarse la mayor parte del tiempo sin alterar significativamente el comportamiento de la rata.
Un gen que muta a "bueno" tendrá poco efecto (si, por ejemplo, corresponde a una célula vacía, podría permitir encontrar un camino nuevo y más corto, pero eso también podría llevar a la rata directamente a una trampa), o una dramática (si el color representa una pared, es muy probable que la nueva rata se atasque en algún lugar).
Un gen que cambia a "trampa" privará a la rata de un color esencial o no tendrá un efecto notable.
Una mutación de una ubicación de trampa solo importará si de hecho hay una trampa (o algo dañino) por delante, lo que tiene una probabilidad relativamente pequeña (diría algo así como 1/3).
Por último, supongo que los últimos 36 bits contribuyen no solo a evitar que las ratas se atasquen, sino también a propagar las ratas de manera más uniforme en la pista, preservando así la diversidad genética hasta que emerge un genoma ganador y se vuelve dominante a través de la parte de codificación de colores.
Más trabajo
Debo decir que encuentro estos pequeños bichos fascinantes.
Gracias nuevamente a todos los contribuyentes a este excelente desafío.
Estoy pensando en cortar aún más el controlador para mostrar datos más significativos, como la ascendencia de una rata exitosa.
También me gustaría mucho ver a estas ratas en acción, pero este lenguaje C ++ b ** ch hace que crear, y mucho menos animar, imágenes (entre muchas otras cosas) sea una tarea desordenada.
Al final, me gustaría producir al menos una explicación del sistema de trampa y posiblemente mejorarlo.
Hack de controlador
Si alguien está interesado, puedo publicar las modificaciones que hice en el controlador.
Son sucios y baratos, pero hacen el trabajo.
No soy un experto en GitHub, por lo que tendría que pasar por una simple publicación.
fuente
^^v^vvv^^^vv^^v^vvv^v^^vvvv^^^^^^^^^
significas? El resto lo puedo adivinar, pero ¿estoy teniendo problemas con esa parte?Duros creyentes - C ++ - (teletransportadores mejorados): 10.000+ para 2000 carreras
(esta es una evolución de la fe ciega , por lo que es posible que desee escalar otro muro de texto antes de este)
Episodio IV: orientarse en la red
Resultados
Cambié a g ++ / MinGW y 3 hilos.
El código generado por GNU es más del doble de rápido que el de Microsoft.
No es de extrañar, ¿qué pasa con su terrible implementación de STL?
Teletransportadores
El efecto de teletransportador depende en gran medida de la posición. Hasta ahora, estaba feliz de considerar un teletransportador como siempre bueno (visto como un espacio vacío) o siempre malo (visto como una pared para que ningún roedor lo tomara).
Este es un modelo demasiado grueso.
Un teletransportador determinado puede impulsar a una rata hacia adelante hasta unas pocas celdas de la meta, pero una vez allí, el mismo teletransportador puede arrojar a la rata fuera del tablero.
Es muy probable que este teletransportador sea reconocido como aceptable (ya que aumenta la aptitud física más rápido que cuando "camina" hacia la misma ubicación x), se convierte en parte del genoma dominante y mata a casi todas las ratas que confían en él como "siempre seguro".
Dado que las ratas no tienen forma de conocer su posición X, la única solución para detectar estos teletransportadores traicioneros es decidir si pisarlos en función de los únicos datos contextuales disponibles, es decir, la cuadrícula de color 5x5.
Para hacerlo, definí 4 tipos de genes de color:
La idea es tratar de distinguir un teletransportador mirando a sus 8 vecinos inmediatos. Dado que la probabilidad de tener 8 vecinos idénticos en una ubicación dada es muy baja, eso debería permitir identificar una instancia única de cada teletransportador.
Los 8 colores vecinos se pueden combinar para formar una firma local, que es invariable según la posición en el laberinto. Desafortunadamente, los 8 vecinos solo son visibles para las células ubicadas dentro del cuadrado interno del campo de visión 3x3, por lo que las firmas serán inexactas en el borde del campo de visión.
Sin embargo, esto nos dará una información contextual constante en el vecindario inmediato, que es suficiente para aumentar la probabilidad de navegar teletransportadores con éxito.
Los genes del haz tienen un campo variable de 2 bits.
Para una firma local de teletransportador dada, hay una posibilidad entre cuatro de que la celda de haz se considere intransitable. Cada valor del campo selecciona una de estas cuatro posibilidades.
Como resultado, una mutación del gen del haz en estos 2 bits recorrerá 4 posibles significaciones contextuales del color.
Además, los colores más importantes para adivinar todavía son paredes y trampas. Esto significa que deberíamos permitir la detección de teletransportadores solo después de que las ratas supieran dónde están las paredes y las trampas.
Esto se lleva a cabo actualizando las firmas locales solo con moderación. El criterio actual para actualizar una firma local es estar en la vinculación de un color identificado como un posible teletransportador.
La codificación utiliza 5 bits por gen de color y tipos de grupos para liberar los 3 bits menos significativos para codificar un valor 0..7:
Cada gen de haz tiene 1/4 de probabilidad de ser considerado como un bloque y 3/4 de posibilidades de ser considerado vacío, por lo que 4 haces representan en promedio 1 bloque y 3 vacíos.
La proporción promedio representada por una distribución aleatoria de 16 colores es así:
Esta mezcla parece dar los mejores resultados hasta ahora, pero no he terminado de ajustarla.
Mutabilidad genética
Una cosa es segura: los valores de código elegidos para representar los tipos de genes son críticos. Invertir dos valores puede costar 2000 puntos o más.
Aquí, nuevamente, la razón por la cual está más allá de mis matemáticas.
Supongo que las probabilidades de mutación de un tipo a otro deben ser equilibradas, o de lo contrario, como en una matriz de Markow, las probabilidades acumulativas tienden a restringir los valores al subconjunto que tiene las mayores probabilidades de transición entrante.
Camino al rescate
La ruta reducirá drásticamente la cantidad de celdas visitadas, lo que permite probar solo las que tienen más probabilidades de llegar a la meta. Por lo tanto, no solo se evitan algunos callejones sin salida frecuentes, sino que también es mucho más probable que se descubran códigos de color incorrectos antes.
Como resultado, el tiempo de convergencia disminuye fuertemente.
Sin embargo, esto no ayuda a resolver los mapas donde el genoma no puede producir una representación adecuada de la pista.
¿Qué hacer con los imbéciles?
Después de mirar visualmente la pista, entendí por qué una estrategia predeterminada que trata de avanzar incluso cuando parece que no hay más que paredes al frente es realmente mejor que contenerse.
Los "muros" pueden ser en realidad teletransportadores que producen tantos resultados desafortunados que el genoma los mapea como obstáculos que nunca deben pisarse, pero en raras ocasiones una instancia particular de este travieso teletransportador puede tener un efecto positivo (o al menos no letal) , así que tomarlo en lugar de retroceder aumenta las posibilidades de encontrar un camino hacia la victoria.
Convergencia temprana
Me parece que la tasa de mutación es un poco demasiado baja (al menos para mis roedores).
La configuración actual de 0.01 le da al ADN un 37% de posibilidades de sobrevivir al proceso de mutación intacto. Cambiar el parámetro a 0.0227 reduce esta probabilidad a aproximadamente 10%
Volví a ejecutar exactamente la misma prueba (usando una secuencia fija de semillas aleatorias) con una probabilidad del 10%.
En muchos mapas, las fallas anteriores se convirtieron en éxitos (limitados). Por otro lado, las enormes explosiones de población fueron menores (lo que tuvo el interesante efecto secundario de acelerar mucho el cálculo).
A pesar de que los puntajes muy altos (más de un millón) fueron menos comunes, el número de carreras más exitosas fue más que suficiente para compensar.
Al final, la media aumentó de 1400+ a aproximadamente 2000.
Establecer P al 5%, por el contrario, produjo una media de aproximadamente 600.
Supongo que la tasa de mutación fue tan alta que el genoma de las ratas ganadoras se convirtió con demasiada frecuencia en variantes menos eficientes.
Como funciona este
Con los detectores de teletransportador agregados, el número de juegos fallidos (puntaje <10) disminuyó significativamente.
En una prueba de 2000 ejecuciones, solo hubo 1/3 de fallas.
La media geométrica solo aumentó de 2900 a 3300, pero este número no refleja la mejora.
Los colores vacíos se adivinan con frecuencia como vigas y peligros (generalmente de 2 a 5). El genoma "usa" estos colores para bloquear caminos que podrían causar problemas a las ratas.
El genoma es bastante bueno para adivinar trampas (es decir, una vez que las ratas pueden alcanzar la meta, los colores que representan detectores de trampas reales se adivinan aproximadamente el 90% del tiempo).
También hace uso de los nuevos códigos de haz para los teletransportadores, aunque más raramente (probablemente porque los teletransportadores "traicioneros" son menos comunes que las trampas, y otros colores de haz / peligro evolucionan para bloquear el camino a las últimas instancias de estos traidores).
A juzgar por la cantidad de juegos en los que emerge un genoma ganador después de 5000 turnos o más, creo que esta nueva raza se beneficiaría enormemente de una mayor tasa de mutación.
fuente
ColorScorePlayer, puntaje preliminar ≈ 22
Este es el bot que ves en el trabajo en el GIF en el desafío.
Este fue nuestro robot de prueba durante toda la fase de desarrollo. Utiliza el genoma para almacenar una puntuación de calidad para cada uno de los 16 colores. Luego realiza el movimiento hacia adelante que lo mueve al color con la mejor puntuación (y nunca se mueve hacia
-1
). En caso de empate, se elige un movimiento aleatorio entre las celdas de unión.Hemos trasladado este reproductor a todos los idiomas del controlador, por lo que actúa como ejemplo de cómo usarlos:
Pitón
Rubí
C ++
C#
Java
El jugador anota con bastante inconsistencia. Aquí hay 50 carreras aleatorias:
fuente
ColorFarSeeker, C ++ ≈ 74.7
Este desafío es realmente muy divertido y simple si lo intentas.
No te dejes desanimar por la larga descripción.
Simplemente visite el GitHub y vea las cosas ... ¡todo será mucho más claro! :)
El simulador C ++ es muy recomendable por su velocidad. Incluso después de haber terminado de traducir mi programa de Python a C ++, la simulación de Python todavía no se ha detenido.
Esta es una variante mejorada de ColorScorePlayer. Para hacer un buen uso de su vista de 5x5, considera movimientos de 2 pasos con una función ponderada. Los movimientos de 1 paso por delante tienen un mayor peso, ya que tienen un efecto más inmediato en la supervivencia. Mover 2 pasos hacia adelante se les da menor peso.
Intenta avanzar, pero si no se ve ningún movimiento seguro ... luego intenta de lado ... y si todo lo demás falla, retrocede al azar.
Puntuación:
Hay bastantes 1's ... que pueden ser un poco deprimentes cuando ves que la consola arroja 1 uno detrás del otro. Como un planeta con todas las necesidades para la vida, pero sin signos de civilizaciones de ratas avanzadas ...
Luego, espigas ocasionales. :)
Hmm ... aparentemente tuve la suerte de mi primer lote de carreras, obteniendo un geométrico de más de 300. Las puntuaciones realmente fluctúan bastante. Pero de todos modos, con más ejecuciones del simulador, probablemente esté más cerca de ≈ 74. (Thx feersum por ayudarme a simular y su programa ultrarrápido)
fuente
Obispo - Python, puntaje preliminar 1.901
El Obispo siempre se mueve en diagonal, por lo que la mitad del tablero es inaccesible en una caminata dada a través del tablero, pero esto significa menos movimientos potenciales para codificar, por lo que cada parte individual del genoma puede representar un movimiento (el Obispo nunca se retira). A qué bit referirse se decide en función del bloque de cuadrados 3x3 delante (a la derecha) de la muestra. El mejor movimiento para una situación dada es solo una mutación de distancia.
Al principio, este bot aprende rápidamente, pero luego a menudo alcanza un techo antes de llegar al final, presumiblemente donde ocurre uno de los siguientes dos problemas:
Código
A pesar de estas limitaciones, en raras ocasiones el Obispo lo hace bien, con especímenes individuales que completan varias vueltas del tablero cada uno. Pensé que en una vuelta dada, un espécimen solo puede moverse en la mitad del tablero (equivalente a solo los cuadrados negros o solo los cuadrados blancos en un tablero de ajedrez). Sin embargo, como señaló Martin Büttner, un teletransportador puede mover una muestra de un cuadrado negro a un cuadrado blanco o viceversa, por lo que en la mayoría de los tableros no estarán restringidos.
(Hay dos pares de tipos de teletransportadores coincidentes y cada uno tiene una probabilidad de 0.5 de tener un desplazamiento que mueve un espécimen a la otra mitad de los cuadrados en blanco y negro. Entonces, la probabilidad de que un tablero tenga solo teletransportadores que restrinjan el espécimen a uno la mitad del tablero por vuelta es solo 0.25.)
Los puntajes muestran que los triunfos ocasionales se entremezclan con largos períodos de falta del final:
fuente
Jugador de bonificación de carrera: media geométrica 50.35 (prueba de 5000 juegos)
Este bot puntúa cuadrados por sus colores individuales basados en una sección de ADN de 6 bits como el jugador de puntuación de color, pero con un sistema de números diferente. Este bot fue motivado por la idea de que es bastante arbitrario que uno de los bits cambie el valor de la puntuación en 32, mientras que otro lo hace solo en 1. Asigna el valor n (n + 1) / 2 a una serie de n 1 bits consecutivos. Además, agrega un mecanismo de aleatorización en un intento de evitar quedarse atascado. Hará un movimiento aleatorio hacia adelante con una probabilidad de 1 en 30.
A modo de comparación, el jugador con puntaje de color obtuvo 30 a 35 en un par de pruebas de 1000 juegos. Curiosamente, el puntaje máximo del jugador con puntaje de color estaba en el rango de 3-5 millones, mientras que el máximo de bonificación de carrera fue de solo 200 mil. Run-bonus se beneficia del sistema de puntuación promedio logarítmico al obtener un puntaje distinto de cero de manera más consistente.
Ejecutar 5000 juegos tomó aproximadamente 20 minutos con 6 hilos en el controlador C ++.
fuente
StarPlayer | C ++ | Puntuación: 162 (basado en 500 carreras ejecutadas)
Este jugador intenta usar A * para encontrar la mejor manera de avanzar. Asigna pesos de la misma manera que ColorScorePlayer e intenta encontrar el camino hacia el borde derecho de la vista. La implementación no es la más bonita que he hecho, pero al menos no es demasiado lenta.
Puntajes de muestra:
fuente
WallGuesser: obtuvo 113.266 en una prueba de 1000 juegos
Codificación
Hice una codificación de 6 bits / color realmente simple. Para decodificar el color [n]
Al difundir los bits para un color en todo el genoma, estoy aumentando la posibilidad de que se usen bits de ambos padres para cada color.
Movimiento
Utilizo una búsqueda basada en A * (estoy seguro de que no es muy eficiente) para buscar la ruta de menor costo a cualquiera de los cuadrados del borde derecho. Si un color se asigna a "bloqueado", la búsqueda nunca lo ingresará. Si la búsqueda no puede encontrar una ruta, se supone que esta rata no está en condiciones de reproducirse e intenta terminar moviéndola hacia la izquierda.
Reducir el número de ratas no aptas
Dado que mi genoma está adivinando efectivamente qué cuadrados son teletransportadores de pared o hacia atrás, las ratas que no tienen adivinanzas (no hay colores que se mapeen como bloqueados) no son muy adecuadas. Para tratar de eliminar estas ratas si ningún color se marcaría como bloqueado, CADA color se marcará como bloqueado y la rata siempre se moverá una hacia la izquierda.
QUE HACER
Actualmente no hay aleatoriedad en el comportamiento, por lo que es fácil que las ratas se atasquen.
fuente
g++ -std=c++11 .\wallguesser.cpp -O2 -o .\wallguesser.exe
. Recibo muchos errores, pero el primero es.\wallguesser.cpp:47:19: error: 'dna_t' has no member named 'at' if (d.at(i) == true){
at
para[]
solucionarlo.The FITTEST - Puntuación media geométrica: ~ 922 (2K carreras)
Mi enfoque es:
Probé más de 2000 conjuntos de parámetros con las mismas 50 semillas. Se seleccionaron los conjuntos más prometedores y se puntuaron utilizando 250 semillas idénticas y los que obtuvieron el rango más alto fueron la entrada para la siguiente ronda de prueba. Así que logré crear un algoritmo genético para encontrar el algoritmo genético óptimo para este problema, según lo sugerido por el usuario mbomb007 .
El comportamiento deseado:
Métodos de almacenamiento de datos:
Queremos que la especie aprenda cosas, se adapte a su entorno, se convierta en el más apto. Inevitablemente, esto solo funciona si el aprendizaje se puede almacenar de alguna manera. El aprendizaje se 'almacenará' en los 100 bits de ADN. Es una forma extraña de almacenar, porque no podemos cambiar el valor de nuestro ADN. Por lo tanto, suponemos que el ADN ya almacena información de movimientos malos y buenos. Si para cierta especie se almacena la información correcta en su ADN, avanzará rápidamente y producirá muchas especies nuevas con su ADN.
Descubrí que la puntuación media geométrica es sensible a cómo se almacena la información. Supongamos que leemos los primeros 4 bits de los 100 bits de ADN y queremos almacenar esto en una variable entera. Podemos hacer esto de varias maneras:
dnarange
, ejemplo: 4 bits1011
se convertirán en `1x2 ^ 3 + 0x2 ^ 2 + 1x2 ^ 1 + 1x2 ^ 0 = 15. Valores posibles (para 4 bits): [0, 1 , 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]dnaStreakRange
función (definida a continuación), ejemplo: 4 bits 1011 se convertirá1x1 + 0x1 + 1x1+ 1x2 = 4
. Valores posibles (para 4 bits): [0, 1, 2, 3, 6, 10]dnaCountRange
función (definida a continuación), por ejemplo: 4 bits 1011 se convertirá1x1 + 0x1 + 1x1 + 1x1 = 3
. Valores posibles (para 4 bits): [0, 1, 2, 3, 4]Las diferencias entre los métodos de almacenamiento son:
Priorizar soluciones.
Cuando ColorScorePlayer ha identificado dos movimientos hacia adelante con puntajes idénticos, se realiza una elección arbitraria. En mi humilde opinión, nunca debe utilizar la función de
v.rng.rint()
función aleatoria . En su lugar, debe usar esta oportunidad de puntajes iguales como un gancho para evaluar soluciones para efectos de segundo orden.El efecto de primer orden obtiene la máxima prioridad. Si se alcanzan puntajes iguales, prevalece la solución con la prioridad 2 y así sucesivamente. Al ajustar los parámetros de una solución, puede influir en la posibilidad de que se obtengan puntajes iguales y de ese modo cambiar el peso de las soluciones de prioridad 1 y prioridad 2.
Implementación del comportamiento deseado
Aprenda qué colores son seguros:
threshold = 63/3=21
, donde 63 es el puntaje máximo para 6 bits y 33% = 1/3 (puede consultarse en el gráfico anterior).Si no hay movimientos buenos disponibles, muévase vertical o hacia atrás:
weightMove
variable.Mira lo que hay más allá:
x2
yy2
bucles) cuál es la mejor opción (a través de lamainSubScore
variable). La columna más a la derecha en ese cuadro de 3x3 es líder.Identificar trampas:
Examiné el ADN de la especie con la puntuación más alta cuando un juego arbitrario terminó usando un almacenamiento de bitsum4 (por lo que la puntuación de color tiene un rango [0,4]):
De esto se puede concluir que las paredes y los teletransportes obtienen una puntuación correcta. Las trampas no se identifican ya que dependen de la dirección y del color de origen, mientras que la puntuación se realiza según el color de destino. Por lo tanto, también es necesario almacenar datos sobre el color de origen
v(0,0)
. En un mundo ideal, nos gustaría almacenar información para 16 colores x 8 direcciones x 3 bits = 384 bits.Desafortunadamente, solo hay 100 bits disponibles y no podemos usarlo todo, ya que también necesitamos algo de memoria para la solución explicada anteriormente. Por lo tanto, haremos 4 contenedores de colores:
y 4 contenedores de dirección de movimiento
Cuando el puntaje decimal es 4 o superior (100,101,110,111), se supone que hay una trampa asociada con esta celda, como resultado, este movimiento no se seleccionará cuando surjan puntajes iguales. Por lo tanto, la identificación de trampas es un efecto de segundo orden y el "mirar lo que está más allá" será una solución de tercera prioridad.
Supuestos erróneos sobre el muro se duplican muchas veces en recién nacidos por imbéciles:
Algunas especies suponen incorrectamente que las paredes son buenas y tratan de moverse hacia ellas todo el tiempo y, por lo tanto, se atascan frente a las paredes. También pueden quedar atrapados en bucles infinitos de teletransportadores. El efecto es el mismo en ambos casos.
El principal problema es que después de unos cientos de iteraciones, algunos genes se vuelven muy dominantes . Si estos son los genes 'correctos', puede obtener puntajes muy altos (> 1 millón de puntos). Si esto está mal, estás atrapado, ya que necesitas la diversidad para encontrar los genes 'correctos'.
Peleas de imbéciles: Solución 1: inversión de color
La primera solución que probé fue un esfuerzo por utilizar una parte de la memoria no utilizada que todavía es muy diversa. Supongamos que ha asignado 84 bits a su memoria de color y atrape la memoria de búsqueda. Los 16 bits restantes serán muy diversos. Podemos llenar 2 variables decimal8 que tienen valores en el intervalo [0,255] y son homogéneas, lo que significa que cada valor tiene una probabilidad de 1/256. Las variables se llamarán
inInverse
yinReverse
.Si
inInverse
es igual a 255 (una probabilidad de 1/256), invertiremos la interpretación de las puntuaciones de color . Por lo tanto, el muro que el imbécil supone que es seguro debido a su alto puntaje, obtendrá un puntaje bajo y, por lo tanto, se convertirá en un mal movimiento. La desventaja es que esto también afectará a los genes de 'derechos', por lo que tendremos puntuaciones menos altas. Además, estainInverse
especie tendrá que reproducirse y sus hijos también obtendrán partes del ADN dominante. La parte más importante es que recupera la diversidad.Si
inReverse
es igual a 255 (una probabilidad de 1/256), invertiremos el orden de las posiciones de almacenamiento de las puntuaciones de color . Entonces, antes del color 0 se almacenaba en los bits 0-3. Ahora el color 15 se almacenará en esa posición. La diferencia con elinInverse
enfoque es queinReverse
deshacerá el trabajo realizado hasta ahora. Estamos de vuelta en el punto de partida. Hemos creado una especie que tiene genes similares a cuando comenzó el juego (a excepción de la trampa para encontrar memoria)A través de la optimización, se prueba si es aconsejable utilizar
inInverse
yinReverse
al mismo tiempo. Después de la optimización, se concluyó que la puntuación no aumentó. El problema es que tenemos una población de gen más diversa, pero esto también afecta el 'ADN correcto'. Necesitamos otra solución.Peleas de imbéciles: Solución 2: código hash
La especie tiene 15 posiciones iniciales posibles y actualmente hay una posibilidad demasiado grande de que siga exactamente el mismo camino si comienza en la misma posición inicial. Si es un imbécil que ama las paredes, se quedará atrapado en la misma pared una y otra vez. Si por suerte logra llegar a un muro más adelante, comenzará a dominar el conjunto de ADN con sus suposiciones equivocadas. Lo que necesitamos es que su descendencia siga un camino ligeramente diferente (ya que para él es demasiado tarde de todos modos), y no se quedará atrapado en el muro más adelante, sino en un muro más cercano . Esto se puede lograr mediante la introducción de un código hash .
Un código hash debe tener el propósito de identificar y etiquetar de manera única la posición actual en el tablero. El propósito no es averiguar cuál es la posición (x, y), sino responder las preguntas que han tenido mis antepasados en este lugar.
Supongamos que tendría el tablero completo frente a usted y haría un jpg de cada cuadrado posible de 5 por 5 celdas. Terminarías con (53-5) x (15-5) = 380 imágenes. Démosle a esas imágenes números del 1 al 380. Nuestro código hash debe verse como una ID, con esa diferencia de que no se ejecuta del 1 al 330, pero le faltan IDS, por ejemplo, 563, 3424, 9424, 21245, etc.
Los números primos
17
y31
están ahí para evitar que la información agregada al principio en el ciclo desaparezca. Más adelante sobre cómo integrar nuestro hashcode en el resto del programa.Vamos a reemplazar el mecanismo de grabación de "mirar lo que está más allá" con otro mecanismo de grabación. Cuando dos o tres celdas tienen puntajes principales iguales, habrá un 50% de posibilidades de que se escoja el superior, un 50% de posibilidades de que se elijan las celdas inferiores y un 0% de posibilidades de que se escoja el medio. La posibilidad no estará determinada por el generador aleatorio, sino por bits de la memoria , ya que de esa manera nos aseguramos de que en la misma situación se haga la misma elección.
En un mundo ideal (donde tenemos una cantidad infinita de memoria), calcularíamos un código hash único para nuestra situación actual, por ejemplo, 25881, iríamos a la ubicación de memoria 25881 y leeríamos allí si debemos elegir la celda superior o inferior (cuando hay es un puntaje igual) De esa manera, estaríamos exactamente en la misma situación (cuando, por ejemplo, viajamos por el tablero por segunda vez y comenzamos en la misma posición), tomaremos las mismas decisiones. Como no tenemos memoria infinita, aplicaremos un módulo del tamaño de la memoria disponible al código hash . El hashcode actual es bueno en el sentido de que la distribución después de la operación del módulo es homogénea.
Cuando la descendencia viaja por el mismo tablero con ADN ligeramente modificado, en la mayoría de los casos (> 99%) tomará exactamente la misma decisión. Pero cuanto más se acerca, mayor es la posibilidad de que su camino sea diferente de sus antepasados. Por lo tanto, la posibilidad de que se quede atrapado en este muro muy por delante es pequeña. Mientras se atasca en la misma pared cercana que su antepasado es relativamente grande, pero esto no es tan malo, ya que no generará mucha descendencia. Sin el enfoque de código hash , la posibilidad de quedar atrapado en la pared cercana y lejana es casi la misma.
Mejoramiento
Después de la optimización, se concluyó que la tabla de identificación de trampas no es necesaria y que 2 bits por color son suficientes. El resto de la memoria 100-2x16 = 68 bits se usa para almacenar el código hash. Parece que el mecanismo del código hash puede evitar trampas.
He optimizado para 15 parámetros. Este código incluye el mejor conjunto de parámetros modificados (hasta ahora):
Este es mi primer programa C ++. Como la mayoría de ustedes ahora tengo experiencia en análisis de gnomos. Quiero agradecer a los organizadores, ya que realmente disfruté trabajando en esto.
Si tiene algún comentario, deje un comentario a continuación. Disculpas por los largos textos.
fuente
Pathfinder, C ++, puntaje preliminar 35.8504 (50 rondas)
¡Una revisión completa! Porté mi algoritmo a C ++ y lo ajusté un poco, pero el puntaje aún no es muy alto, probablemente porque las ratas siguen golpeando sus cabezas contra las paredes. Estoy cansado de tratar de mejorar esto, así que lo dejaré por ahora.
Explicación
La idea general es clasificar cada color como una trampa o no, luego asignar direcciones a las trampas y pesos a las no trampas, e intentar seguir la ruta de peso mínimo hasta el borde derecho de la cuadrícula de visión.
En los primeros 80 bits del genoma, cada color se clasifica utilizando 5 bits
abcde
. Siab = 01
, el color es una trampa ycde
codifica su dirección (ocho posibilidades). Siab ≠ 01
, el color no es una trampa, y su peso sía + b + 2*(c + d + e)
.A continuación, inicializamos una cuadrícula de 3x7, que representa el campo de visión de la rata a su derecha, rellenada con colores "desconocidos". Los bits 80-84 codifican el peso de las celdas desconocidas de manera similar a los colores sin trampa, y los bits 85-89 codifican un peso común para las trampas. Llenamos la cuadrícula con los pesos, calculamos las rutas más cortas y agregamos un poco de peso adicional (codificado en los bits 90-95) a las celdas directamente encima y debajo de la rata para desalentar el paso lateral. Los bits 95-99 codifican un peso objetivo. Si el peso mínimo de un camino está debajo de él, la rata probablemente esté atrapada en algún lugar y proceda a moverse al azar (pero nunca retrocede). De lo contrario, sigue la ruta de peso mínimo. Con una pequeña probabilidad dependiendo del peso que evita el paso lateral, la rata elige la ruta de peso del segundo al mínimo. Esto es para evitar quedarse atascado en las paredes (pero parece que no funciona muy bien en este momento).
fuente
LookAheadPlayer C ++ ≈ 89.904
Mi idea original era buscar 4 bits que coincidieran con el color que estaba buscando, y usar los siguientes bits como puntaje. Esto resultó ser una idea terrible, probablemente debido a mutaciones.
Así que pensé en formas de protección contra mutaciones y cruces, y me recordó sobre el trabajo que he realizado en la decodificación de códigos QR. En los códigos QR, los datos se dividen en bloques y se cortan para evitar que los errores destruyan demasiada parte de los datos.
Por lo tanto, al igual que ColorScorePlayer, corté el ADN en 16 fragmentos y los utilicé como la puntuación dada. Sin embargo, las puntuaciones están divididas de manera que los bits individuales de cada puntuación no sean adyacentes. Luego sumo el puntaje de los movimientos posibles actuales y los próximos movimientos potenciales y elijo el mejor movimiento para hacer.
Nota: esto fue codificado / probado en MinGW. No se compilaría con optimizaciones o con subprocesos múltiples. No tengo una instalación real de Linux o Visual Studio a mano para usar un compilador donde estos funcionen. Lo probaré rápidamente mañana por la mañana, pero avíseme si tiene algún problema.
fuente
SlowAndSteady C ++ (puntaje 9.7)
No podemos confiar en interpretar fragmentos del genoma como números porque un solo cambio de bit puede tener efectos radicalmente diferentes dependiendo de su posición. Es por eso que simplemente uso 16 segmentos de 6 bits y los califico en el número de
1
s. Inicialmente111111
era bueno y000000
malo, y aunque no importa a largo plazo (una vez que el genoma está completamente evolucionado) en la configuración inicial del ADN, la mayoría de los segmentos tienen de 2 a 4, así que cambié a usar9 - (#1 - 3)^2
para puntuación, esto permite mucha más libertad de movimiento en las primeras rondas y una evolución más rápida.En este momento solo miro a los 7 vecinos más cercanos, agrego un sesgo de dirección a la puntuación de color y me muevo en una de las direcciones más altas al azar.
Aunque el puntaje en sí no es muy alto, mis bichos alcanzan la línea de meta y obtienen un puntaje> 1 en 3/4 de los casos.
Y una muestra de puntuación en 100 tableros
Puntuación media geométrica: 9.76557
fuente
WeightChooser | C # | Puntajes: 220.8262 en 1520 juegos
Calcula el peso para el posible próximo movimiento (azul) en función del peso promedio de los posibles movimientos seguidos (amarillo)
fuente
RATAS EN ACCIÓN (no es una respuesta, sino una herramienta gráfica para bots de C ++)
Desde el comienzo de este desafío, tuve dificultades para descubrir a qué se enfrentaban realmente las ratas en la pista.
Al final, pirateé el controlador y escribí una herramienta lateral para obtener una representación gráfica de una pista.
Eventualmente hice algo más de pirateo y agregué una visualización de los posibles caminos del ADN de una rata dada.
El mapa está extremadamente abarrotado y requiere un poco de tiempo para acostumbrarse, pero me pareció bastante útil comprender cómo funcionaban mis bots.
Aquí hay un ejemplo:
Probablemente necesitará hacer zoom para ver algo, así que aquí está solo la primera mitad:
Al principio, veamos los caminos de la rata. Hay una ruta para cada posible ubicación de inicio (generalmente 15, a veces un poco menos). Por lo general, tienden a fusionarse, lo que idealmente conduce a un solo lugar de victoria.
Los caminos están representados por grandes flechas rectas. El color describe el resultado:
En el ejemplo, tenemos 12 posiciones de inicio ganadoras, una que lleva a un bucle infinito y dos a una muerte agotadora (como parece ser teletransportado).
Las discontinuidades de la ruta se deben a teletransportaciones, que puede seguir con las flechas curvas correspondientes.
Ahora para los símbolos de colores. Representan el significado de los 16 colores (los grises representan lo que ve una rata).
los colores vacíos están ... bueno ... vacíos.
Los teletransportadores tienen flechas salientes que apuntan a su destino.
Los detectores de trampa también tienen flechas que indican la trampa, que se representa como un círculo rojo.
En un caso de 9, la trampa se encuentra en la misma celda que su detector, en cuyo caso verá el pequeño octógono en la parte superior del círculo rojo.
Es el caso de la trampa de color amarillo pálido en este ejemplo.
También puede ver los detectores de trampa de color malva apuntando hacia su trampa indicada.
Tenga en cuenta que a veces el círculo rojo de una trampa estará oculto debajo de una pared. Ambos son letales, por lo que el resultado es el mismo en caso de teletransportación.
Observe también que una trampa podría estar ubicada en un teletransportador, en cuyo caso el teletransportador tiene prioridad (es decir, la rata se teletransporta antes de caer en la trampa, en efecto neutralizando la trampa).
Por último, los símbolos grises representan lo que ven mis ratas (es decir, el significado de sus atributos genómicos para los colores).
Básicamente, todas las celdas que se sientan en un cuadrado gris son consideradas paredes por la rata.
Las X grandes representan células consideradas trampas, con los octógonos correspondientes que indican el detector que las reportó.
En este ejemplo, ambas paredes se identifican como tales, al igual que la trampa de color amarillo pálido (indicando de hecho una celda mortal, por lo que representarla como una pared es correcta).
El detector de trampa de color malva se ha identificado como tal (se encuentra en un octógono gris), pero la ubicación de la trampa es incorrecta (puede ver que algunos círculos rojos no tienen cruces debajo de ellos).
De 4 teletransportadores, 2 se consideran paredes (turquesa y tostado) y 2 como celdas vacías (rojizas y amarillentas).
Algunas celdas vacías se consideran detectores de trampa o paredes. Si observa de cerca, puede ver que estos "detectores defectuosos" de hecho están prohibiendo la entrada a las celdas que podrían causar problemas a la rata, por lo que a pesar de que no coinciden con los colores reales, tienen un propósito definido.
El código
Bueno, es un desastre, pero funciona bastante bien.
Visto desde el código del jugador, solo agregué una interfaz: una función de rastreo utilizada para informar el significado de un ADN dado. En mi caso, utilicé 3 tipos (pared, detector de trampa y vacío), pero básicamente puede generar cualquier cosa relacionada con el color (o nada en absoluto si no desea gráficos relacionados con el genoma).
Pirateé el controlador para generar una gran cadena de caracteres que coteja la descripción de la pista y los colores con una "prueba en seco" del ADN de la rata desde todas las ubicaciones posibles.
Significa que los resultados serán realmente significativos solo si el bot no usa valores aleatorios. De lo contrario, las rutas que se muestran solo representarán un resultado posible.
Por último, todos estos rastros se colocan en un archivo de texto grande que luego es leído por una utilidad PHP que produce la salida gráfica.
En la versión actual, tomo una instantánea cada vez que una rata muere después de haber alcanzado un nuevo estado físico máximo (que muestra bastante bien el refinamiento progresivo del genoma sin requerir demasiadas instantáneas) y una instantánea final al final del juego (que muestra El ADN más exitoso).
Si alguien está interesado, puedo publicar el código.
Claramente, esto funciona solo para los bots de C ++, y necesitará escribir una función de rastreo y posiblemente modificar el código PHP si desea mostrar algunos datos específicos del genoma (las cifras grises en mi caso).
Incluso sin información específica de ADN, puede ver los caminos seguidos por su ADN en un mapa dado con muy poco esfuerzo.
¿Por qué una salida intermedia?
En primer lugar, C ++ no tiene una biblioteca gráfica portátil decente para hablar, especialmente cuando se usa MSVC. Incluso si las compilaciones de Win32 generalmente están disponibles, a menudo vienen como una ocurrencia tardía, y la cantidad de bibliotecas externas, paquetes y otras sutilezas similares a Unix necesarias hacen que escribir una aplicación gráfica rápida y simple sea un dolor terrible en una parte del cuerpo que la decencia impide yo de nombrar.
Pensé en usar Qt (casi el único entorno que hace que el desarrollo gráfico / GUI portátil en C ++ sea una tarea simple e incluso placentera, en mi humilde opinión, probablemente porque agrega un sistema de mensajería al objetivo C que C ++ carece y hace un trabajo increíble de limitar la memoria administración al mínimo posible), pero esto parecía una exageración para la tarea en cuestión (y cualquiera que quiera usar el código tendría que instalar el SDK grande, supongo que no vale la pena el esfuerzo).
Incluso suponiendo una biblioteca portátil, no hay requisitos de velocidad para hablar (un segundo más o menos para producir una imagen es en gran medida suficiente), y con su rigidez proverbial y desorden inherente, C ++ ciertamente no es la mejor herramienta para el trabajo.
Además, tener una salida de texto intermedia agrega mucha flexibilidad. Una vez que los datos están allí, puede usarlos para otros fines (analizando el rendimiento de los bots, por ejemplo).
¿Por qué PHP?
El lenguaje me parece extremadamente simple y adaptable, muy conveniente para la creación de prototipos. Lo convertí en mi lenguaje favorito para desafíos de código que no requieren desempeños extremos.
Sin embargo, es un lenguaje terrible para el golf, pero el golf nunca fue mi taza de té de todos modos.
Supongo que Python o Ruby serían igual de agradables de usar con el mismo propósito, pero nunca tuve la oportunidad de hacer un trabajo serio con ellos, y últimamente estaba trabajando en sitios web, así que PHP lo es.
Incluso si no conoce el idioma, no debería ser demasiado difícil modificar el código para satisfacer sus necesidades. Simplemente no olvides la
$
s antes de las variables, al igual que los buenos viejos días básicos :).fuente
SkyWalker - Python - anota menos de 231 en 50 juegos
Entonces codifique primero y luego algunas explicaciones. Espero que nada se haya roto al copiar.
Alguna explicación
En mi opinión, la principal diferencia es que no codifico todos los colores. En cambio, trato de guardar la cantidad de colores que son importantes. En mi opinión, esos colores son las trampas, paredes y teletransportadores. El espécimen no necesita saber el color de una buena célula. Por lo tanto, mi genoma está estructurado de la siguiente manera.
Esto hace un total de 52 bits utilizados. Sin embargo, utilizo solo el primer bit de los 3 decisores teletransportadores (verifico si el número es mayor 3). Por lo tanto, los otros 2 podrían eliminarse, dejándome en 44 bits utilizados.
En cada turno verifico cada campo de mi visión si es uno de los colores malos (+ fuera del tablero -1) y lo agrego a una lista de campos a los que el espécimen no quiere moverse. En el caso de una trampa, agrego el campo que está en el desplazamiento guardado para ese color de trampa.
Según la lista de esos campos defectuosos, se calcula el siguiente movimiento. El orden de los campos preferidos es:
Si dos campos de una categoría son aplicables, uno se elige al azar.
Resultados
Pensamientos
No tengo idea, si tuve suerte con las 50 carreras o si realmente hay algo de sabiduría en mi estrategia.
Mis carreras nunca parecen despegar y obtener puntajes súper altos, pero también tienden a encontrar al menos algunas veces el objetivo
Una pequeña aleatoriedad es buena para no quedar atrapado en una trampa en algún lugar cerca del final de la carrera.
Creo que los colores no especiales nunca son malos. Sin embargo, las instancias de ellos pueden ser malas, cuando están en el desplazamiento de una trampa. Por lo tanto, etiquetar un color como malo si no es trampa, pared o teletransportador incorrecto no tiene sentido.
Las paredes son los mayores enemigos.
Mejoras
Primero, aunque extrañaré ver los cuadrados negros acercándose cada vez más a la meta, es necesario un puerto C ++ para realizar más pruebas y obtener un resultado más significativo.
Uno de los principales problemas es que si hay células malas (o aquellas que el espécimen piensa mal) frente a la rata, fácilmente comienza a moverse hacia arriba y hacia abajo en círculos. Esto podría detenerse o reducirse mirando 2 movimientos hacia adelante en esos casos y evitar que se mueva a un campo donde simplemente retroceda nuevamente.
A menudo, lleva bastante tiempo hasta que una rata con buenos genes llega a la meta y comienza a propagar sus genes. Tal vez necesito alguna estrategia para aumentar la diversidad en esos casos.
Dado que los teletransportadores son difíciles de calcular, tal vez debería dividir la población entre aquellos que son riesgosos y siempre tomar buenos teletransportadores y aquellos que están más preocupados y solo tomarlos si no hay otra opción.
Debería usar la segunda mitad de mi genoma de alguna manera.
fuente
self.bit_chunk(16, 4)
yself.bit_chunk(20, 4)
tiene el valor0010
, efectivamente solo ha almacenado información sobre una de las dos trampas.itervalues
avalues
.Python, NeighboursOfNeighbours, Puntuación = 259.84395 más de 100 juegos
Esta es una variación de ColorScorePlayer. Cada 6 bits almacena un puntaje de calidad para un cuadrado. Cuando el bot está haciendo un movimiento, puntúa cada uno de los 3 cuadrados hacia adelante: diagonal hacia arriba, hacia adelante y diagonal hacia abajo. El puntaje es la calidad del cuadrado más la mitad de la calidad promedio de los siguientes 3 cuadrados. Esto le da al bot un poco de anticipación, sin abrumar la calidad del primer cuadro. El algoritmo es similar a LookAheadPlayer, que no vi antes de escribir esta solución.
fuente
else None
aelse 0
la línea anterior para calcular su puntaje. Espero que eso deje su lógica sin cambios (no he realizado cambios en su código aquí en SE, aparte de agregar la sangría perdida).ROUS (Roedor de tamaño inusual), Java, Puntuación = 0
Esto mezcla los alrededores para decidir a dónde ir.
Debido a que el controlador Java no funciona, no tengo puntajes para esto. Esto solo llegará muy lejos si encuentra algunos teletransportadores para ayudarlo.Esto tiende a extinguirse y bloquea el controlador de vez en cuando. Esto probablemente se deba al hecho de que su entorno natural es el Pantano de Fuego.fuente
Lookahead de color gris (C ++, ~ 1.35)
A este no le está yendo muy bien en promedio, pero en raras ocasiones se desempeña de manera brillante. Desafortunadamente, se nos califica en promedio geométrico (1.35) y no en puntaje máximo (20077).
Este algoritmo funciona simplemente usando códigos grises de 4 bits para asignar el puntaje de cada color en algún lugar de -2 a 2 (con un sesgo hacia el rango [-1..1]), y calcula el puntaje de la casilla de cada movimiento y sus próximos movimientos . También utiliza un código gris de 2 bits para determinar el multiplicador para el mosaico en sí, así como el factor de polarización para moverse hacia la derecha. (Los códigos grises son mucho menos susceptibles a grandes saltos debido a mutaciones, aunque en realidad no hacen ningún favor para el cruce de punto de código medio ...)
Tampoco hace absolutamente nada para tratar de manejar trampas especialmente, y sospecho que podría ser la caída (aunque no he agregado ninguna instrumentación al controlador para probar esta teoría).
Para cada movimiento posible, determina un puntaje y, de entre todos los movimientos con el puntaje más alto, elige al azar.
En mi carrera más reciente, obtuve puntajes: 1 1 1 1 1 1 1 46 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 20077 1 1 1 2 1 1 1 1 1
Ojalá pudiera obtener más de los 20077 y menos de los 1. :)
fuente
C ++, TripleScore, Puntuación: 100 ~ 400
En primer lugar, mi puntaje varía mucho en varias ejecuciones (principalmente debido al número de 1).
El núcleo calcula la puntuación de 5 direcciones: arriba, abajo, adelante-arriba, adelante y adelante-abajo. Primero se calcula la puntuación de arriba y abajo, que los resultados se comparan con el valor de permanecer en el lugar. Si permanecer en el lugar es mejor que moverse hacia arriba o hacia abajo, no se elegirán estas direcciones (por lo tanto, debe avanzar). Esto es para evitar rebotes (arriba, abajo, arriba, abajo, ...) entre 2 puntos.
Ahora se puntúan las otras 3 direcciones: hacia arriba, hacia adelante y hacia abajo. De todas las direcciones investigadas, se mantienen las que tienen la puntuación más alta y 1 de ellas se elige al azar.
Puntuación de una dirección: TripleScore calcula la puntuación de un movimiento utilizando 3 subpuntos:
Al igual que con otras respuestas, el puntaje depende en gran medida del número de puntajes 1 que se devuelven.
fuente
Ruby - ProbabilisticScorePlayer
Esta rata altamente no determinista calcula la probabilidad de ir a un espacio por su vecindario. Las primeras 16 ranuras en el genoma representan los 16 colores. 1 en una ranura significa que el color es bueno para pisar, 0 significa malo. Los siguientes 16 sostienen lo mismo para el espacio frente a su objetivo, y así sucesivamente.
La principal ventaja del enfoque probabilístico es que es casi imposible quedarse atrapado detrás de una pared por mucho tiempo. La desventaja es que casi nunca obtendrás una rata casi perfecta.
fuente
c
un valor inicial? No parece estar definido cuando lo usas en el primeroif
.coords
no es una lista, se usa en&&
lugar deand
paréntesis y se olvidó, e incluso después de arreglar todo esto, no está limitando los valores RNG, por lo que obtiene una dirección vacía. ¿Es este pseudocódigo o algo destinado a ejecutarse con algún tipo de dialecto de Ruby?Java, RunningStar, Puntuación = 1817.050970291959 más de 1000 juegos
Este bot utiliza la codificación de colores de Run-Bonus con la técnica de StarPlayer .
Actualización: controlador java fijo.
fuente
LeapForward, Python 2
No es particularmente innovador, pero es mi único intento que funcionó bien.
Básicamente, codifica cuatro colores (cada uno de 4 bits) para evitar, en el genoma. Luego pasa a un color que no está en esa lista. Si todos los colores son malos, todavía salta hacia lo desconocido.
fuente
Java - IAmARobotPlayer - Puntuación 3.7
Acabo de crear esta rata robot para compararla con otro programa (no muy interesante hasta ahora) que hice. En general, no obtiene un buen puntaje, pero si anota en algún lugar, obtendrá muchas ratas a través de él. La idea es que solo mirará las tres celdas frente a ella, cada celda es buena o mala. Esto le da un número binario. Luego buscará este número en su genoma, tomará los tres bits consecutivos, también los convertirá en un número y tomará la acción que se almacena bajo este número. Por lo tanto, actúa siempre igual cuando se encuentra con la misma situación.
Resultado:
fuente
Especímenes cautelosos - C ++ - puntajes de aproximadamente 2030 en 200 ejecuciones
Utiliza la parte de color (16x4 bits) de la codificación de ADN de Blind Faith pero deja el resto (36 bits) del ADN completamente sin usar.
La codificación de un color es:
Donde X indica bits no utilizados. Dado que solo 2 de 16 colores son trampas que usarán los 4 bits (y solo si la trampa está compensada, que será el caso 8 de 9 veces), normalmente habrá 64 bits no utilizados - la teoría es que las mutaciones que afectan a cualquiera de estos bits no utilizados no van a destruir el genoma y la estabilidad es mejor que cualquier solución elegante que pueda usar esos bits restantes.
Los especímenes luego usan esto para planificar una ruta segura dentro de una cuadrícula de 7x7 centrada en sí mismos (el 5x5 que su visión permite más 1 cuadrado en cada lado para permitir trampas de desplazamiento) priorizando mover la mayor distancia hacia adelante después de 3 movimientos.
Inicialmente comencé a realizar algunas comprobaciones para asegurarme de que el hecho de que el color en el que se encuentra el espécimen no sea letal se corresponda con el genoma y marque cualquier color erróneo como cuadrados de seguridad INSEGURO (y sus cuadrados adyacentes), sin embargo, agregó una cantidad significativa complicación para ganar poco o nada en comparación con marcar esos cuadrados como SEGUROS y matar algunos especímenes adicionales. Volveré a esto si tengo tiempo.
Puntajes de muestra:
Puntuación máxima durante la prueba: 8.150.817 muestras guardadas.
fuente