Debido a la naturaleza de la pregunta, tengo que incluir mucha información de fondo (porque mi pregunta es: ¿cómo puedo reducir esto?) Dicho esto, se puede resumir (según mi leal saber y entender) como:
¿Qué métodos existen para encontrar óptimos locales en espacios de búsqueda combinatoria extremadamente grandes?
Antecedentes
En la comunidad de superjuego asistido por herramientas, buscamos proporcionar una entrada especialmente diseñada (no generada en tiempo real) a una consola o emulador de videojuegos para minimizar algunos costos (generalmente el tiempo de finalización). La forma en que esto se hace actualmente es jugando el juego cuadro por cuadro y especificando la entrada para cada cuadro, a menudo rehaciendo partes de la carrera muchas veces (por ejemplo, la carrera recientemente publicada para The Legend of Zelda: Ocarina of Time ha un total de 198,590 reintentos).
Hacer que estas carreras obtengan su objetivo generalmente se reduce a dos factores principales: planificación de rutas y recorrido. El primero es mucho más "creativo" que el segundo.
La planificación de rutas determina la forma en que el jugador debe navegar en general para completar el juego, y es a menudo la parte más importante de la carrera. Esto es análogo a elegir qué método de clasificación usar, por ejemplo. La mejor clasificación de burbujas en el mundo simplemente no va a superar a una clasificación rápida en 1 millón de elementos.
Sin embargo, en el deseo de perfección, el recorrido (cómo se realiza la ruta) también es un factor importante. Continuando con la analogía, así es como se implementa el algoritmo de clasificación. Algunas rutas ni siquiera pueden realizarse sin marcos de entrada muy específicos. Este es el proceso más tedioso de asistencia de herramientas y es lo que hace que la producción de una ejecución completa lleve meses o incluso años. No es un proceso difícil (para un humano) porque se trata de probar diferentes variaciones de la misma idea hasta que se considere mejor, pero los humanos solo pueden probar tantas variaciones en su capacidad de atención. La aplicación de máquinas a esta tarea parece adecuada aquí.
Mi objetivo ahora es intentar automatizar el proceso transversal en general para la consola Nintendo 64 . El espacio de búsqueda para este problema es ahora demasiado grande para atacar con un enfoque de fuerza bruta. Un segmento de n cuadros de una ejecución N64 tiene 2 30n entradas posibles, lo que significa que solo 30 cuadros de entrada (un segundo a 30FPS) tiene 2 900 entradas posibles; Sería imposible probar estas posibles soluciones, y mucho menos aquellas para una carrera completa de dos horas.
Sin embargo, no estoy interesado en intentar (o más bien, ni siquiera intentaré) la optimización global total de una ejecución completa. Más bien, me gustaría, dada una entrada inicial, aproximar el óptimo local para un segmento particular de una ejecución (o los n óptimos locales más cercanos, para una especie de optimización semi-global) . Es decir, dada una ruta y un recorrido inicial de esa ruta: busque en los vecinos de ese recorrido para minimizar el costo, pero no degenere en probar todos los casos que podrían resolver el problema.
Por lo tanto, mi programa debe tomar un estado inicial, una secuencia de entrada, una función de evaluación y generar el óptimo local al minimizar el resultado de la evaluación.
Estado actual
Actualmente tengo todo el marco cuidado. Esto incluye evaluar un flujo de entrada a través de la manipulación del emulador, instalación y desmontaje, configuración, etc. Y como marcador de posición, el optimizador es un algoritmo genético muy básico. Simplemente evalúa una población de flujos de entrada, almacena / reemplaza al ganador y genera una nueva población al mutar el flujo ganador. Este proceso continúa hasta que se cumplan algunos criterios arbitrarios, como el tiempo o el número de generación.
Tenga en cuenta que la parte más lenta de este programa será, con mucho, la evaluación de una secuencia de entrada . Esto se debe a que esto implica emular el juego para n cuadros. (Si tuviera tiempo, escribiría mi propio emulador que proporcionara ganchos en este tipo de cosas, pero por ahora me queda sintetizar mensajes y modificar la memoria para un emulador existente de otro proceso). En mi computadora principal, que es bastante moderno, evaluar 200 cuadros lleva aproximadamente 14 segundos. Como tal, preferiría un algoritmo (dada la opción) que minimiza el número de evaluaciones de funciones.
Creé un sistema en el marco que administra los emuladores al mismo tiempo. Como tal , puedo evaluar una serie de transmisiones a la vez con una escala de rendimiento lineal, pero prácticamente hablando, la cantidad de emuladores en ejecución solo puede ser de 8 a 32 (y 32 realmente lo empuja) antes de que el rendimiento del sistema se deteriore. Esto significa (dada la opción), un algoritmo que puede procesar mientras se realiza una evaluación sería muy beneficioso, porque el optimizador puede hacer un poco de trabajo pesado mientras espera una evaluación.
Como prueba, mi función de evaluación (para el juego Banjo Kazooie ) era sumar, por cuadro, la distancia desde el jugador hasta un punto de gol. Esto significaba que la solución óptima era acercarse lo más rápido posible a ese punto. Limitando la mutación solo al stick analógico, tardó un día en obtener una solución correcta . (Esto fue antes de implementar la concurrencia).
Después de agregar concurrencia, habilité la mutación de presionar un botón e hice la misma función de evaluación en un área que requería saltar. Con 24 emuladores en ejecución, tardó aproximadamente 1 hora en alcanzar el objetivo desde una secuencia de entrada inicialmente en blanco, pero probablemente necesitaría ejecutarse durante días para llegar a algo cercano a lo óptimo.
Problema
¡El problema que enfrento es que no sé lo suficiente sobre el campo de optimización matemática para saber cómo modelar adecuadamente mi problema de optimización ! Puedo seguir aproximadamente la idea conceptual de muchos algoritmos como se describe en Wikipedia, por ejemplo, pero no sé cómo clasificar mi problema o seleccionar el algoritmo más avanzado para esa categoría.
Por lo que puedo decir, tengo un problema combinatorio con un vecindario extremadamente grande . Además de eso, la función de evaluación es extremadamente discontinua, no tiene gradiente y tiene muchas mesetas . Además, no hay muchas restricciones, aunque con mucho gusto agregaré la capacidad de expresarlas si esto ayuda a resolver el problema; Me gustaría permitir especificar que el botón Inicio no se debe utilizar, por ejemplo, pero este no es el caso general.
Pregunta
Entonces mi pregunta es: ¿cómo modelo esto? ¿Qué tipo de problema de optimización estoy tratando de resolver? ¿Qué algoritmo se supone que debo usar? No tengo miedo de leer trabajos de investigación, ¡así que hágame saber lo que debería leer!
Intuitivamente, un algoritmo genético no podría ser el mejor, porque realmente no parece aprender. Por ejemplo, si presionar Inicio parece empeorar siempre la evaluación (porque detiene el juego), debería haber algún tipo de diseñador o cerebro que aprenda: "presionar Inicio en cualquier momento es inútil". ¡Pero incluso este objetivo no es tan trivial como parece, porque a veces presionar inicio es óptimo, como en la llamada "pausa hacia atrás-saltos largos" en Super Mario 64 ! Aquí el cerebro tendría que aprender un patrón mucho más complejo: "presionar Start es inútil excepto cuando el jugador está en este estado muy específico y continuará con alguna combinación de presionar botones ".
Parece que debería (o la máquina podría aprender a) representar la entrada de alguna otra manera más adecuada para la modificación. La entrada por cuadro parece demasiado granular, porque lo que realmente se necesitan son "acciones", que pueden abarcar varios cuadros ... sin embargo, muchos descubrimientos se hacen cuadro por cuadro, por lo que no puedo descartarlo por completo (el la pausa antes mencionada, salto hacia atrás-largo requiere precisión a nivel de cuadro). También parece que el hecho de que la entrada se procesa en serie debería ser algo que se pueda capitalizar, pero no estoy seguro de cómo.
Actualmente estoy leyendo sobre la búsqueda de tabú (reactiva), la búsqueda de vecindario a muy gran escala, la optimización basada en la enseñanza y el aprendizaje y la optimización de colonias de hormigas.
¿Es este problema simplemente demasiado difícil de abordar con algo más que algoritmos genéticos aleatorios? ¿O es realmente un problema trivial que se resolvió hace mucho tiempo? Gracias por leer y gracias de antemano por cualquier respuesta.