¿Se pueden escribir algoritmos que evolucionen por si mismos? (Algoritmos genéticos/evolutivos)
Introducción
En este apasionante juego, vas a poder ver como una serie de monos evolutivos, cada uno con habilidades y características únicas, se enfrentan en una pelea a muerte. Pero, ¿cómo se logra esta sorprendente evolución de los personajes? La respuesta radica en la implementación de algoritmos genéticos, un concepto científico que encuentra su inspiración en la teoría de la evolución de Darwin.
Al igual que Darwin describió en su famosa teoría de la evolución, solo los más aptos sobreviven. Los monos más prometedores son sometidos a procesos de reproducción, mutación y selección artificial. Con cada enfrentamiento, los monos aprenden, se adaptan y evolucionan, mejorando sus habilidades de combate y convirtiéndose en guerreros imparables.
El espíritu de Darwin vive a través de los monos luchadores y nos recuerda que en la batalla por la supervivencia, solo los más fuertes y adaptados pueden triunfar.
*Imagenes solo a modo ilustrativo, no se decepcione después
Luego de esta emocionante introducción, procederemos a mostrar paso a paso como logramos esto.
Darwin y los algoritmos genéticos
¿Y nuestro juego como será?
- Generaremos muchos monos al azar.
- Los haremos pelear entre si.
- Los que mueren en las peleas, se descartan, a los que la ganan los guardamos
- Luego, creamos monos parecidos a los ganadores, los cuales pelarán contra ellos para sacar la "segunda generación" y así sucesivamente.
- Mientras van pasando las generaciones, quedaran monos cada vez mas fuertes.
def Evolucion(iniciales):
Monos_Mutados = []
Monos_Aleatorios = []
nuevos_monos = []
nuevos_monos.append(iniciales[0])
# Un cuarto de los monos seran un poco mutados, otro cuarto seran mutados mucho
for i in iniciales:
monito = Mono("Mutuado_poco",Mutacion_Mono(i))
Monos_Mutados.append(monito)
monito = Mono("Mutuado_mucho",Mutacion_Mono(i,True))
Monos_Mutados.append(monito)
# El resto de de los monos seran completamente aleatorios
Monos_Aleatorios = Creacion_Aleatoria(31-len(iniciales)-len(Monos_Mutados))
# Agregamos monos a las listas
nuevos_monos.extend(iniciales)
nuevos_monos.extend(Monos_Mutados)
nuevos_monos.extend(Monos_Aleatorios)
# Re-ordenamos aleatoriamente la lista, ya que en caso contrario no podrian pelear entre todos los monos
ran.shuffle(nuevos_monos)
return nuevos_monos
Definición de monos y peleas
- Parámetros de identidad:
- Nombre
- DNI
- Generación
- Nombre completo
- Parámetros de lucha:
- Fuerza
- Agilidad
- Inteligencia
- Salud
- Resistencia
class Mono():
# En un principio genera sus stats aleatoriamente
def __init__(self,name="titi",stats = [0,0,0,0,0]):
global semilla
global DNI
global Generacion
self.name = name
self.DNI = DNI
DNI +=1
self.generacion = Generacion
self.nombre_Completo = name + "_" + str(Generacion) +"_" + str(DNI)
if stats == [0,0,0,0,0]:
for i in stats:
stats[i] = ran.randint(1,100)
# Nos aseguramos de que no hayan numeros negativos (pueden aparecer en las mutaciones)
for i in range(0,5):
if stats[i] < 0 : stats[i] = 0
# Dividiendo por el total nos aseguramos de la suma de todos los stats de el mismo numero
total = (stats[0] + stats[1] + stats[2] + stats[3] + stats[4])/100
self.Fuerza = stats[0] / total
self.Agilidad = stats[1] / total
self.Inteligencia = stats[2] / total
self.Salud = stats[3] / total
self.Resistencia = stats[4] / total
def golpe(Mono_Golpeador, Mono_Golpeado, turno, multiplicador = 1):
# El daño que un mono le hace al otro depende tanto de las estadisticas de uno como las del otro
Ataque_Mono_golpeador=(Mono_Golpeador.Fuerza*(Mono_Golpeador.Agilidad/100)*Multiplicador_Golpe(Mono_Golpeador)*(cansancio(Mono_Golpeador,turno,ataque="ataque"))-(Mono_Golpeado.Resistencia*(Mono_Golpeado.Inteligencia/100)))
Defensa_Mono_golpeado=(Mono_Golpeado.Resistencia*(0.8*pow(Mono_Golpeado.Salud,1.8)/100))+(Mono_Golpeado.Inteligencia*(Mono_Golpeado.Agilidad/100))
Daño = Ataque_Mono_golpeador - Defensa_Mono_golpeado
# Necesitamos que los golpes sean positivos mayores a cero.
if Daño < 7 : Daño = ran.randint(4,10)
return Daño * multiplicador
def Peleas(mono_1 , mono_2,jugable=False,Titulo = " "):
# Definimos la salud al principio de la pelea
Vida_mono_1 = 100
Vida_mono_2 = 100
Turno = 1
# Hacemos que se peguen hasta que alguno pierda toda la salud o se completen una cantidad de golpes maximos
while Turno < Maximos_Turnos_por_pelea :
Turno += 1
# print(Turno)
Vida_mono_1 = Vida_mono_1 - golpe(mono_2 , mono_1 , Turno)
Vida_mono_2 = Vida_mono_2 - golpe(mono_1 , mono_2 , Turno)
# Si es "jugable" le hacemos la animacion
if jugable:On_Game(mono_1,mono_2,Vida_mono_1,Vida_mono_2,Titulo)
# Una vez que uno pierde toda la salud, el ganador es el que mas salud tiene
if (Vida_mono_1 <= 0 or Vida_mono_2 <= 0): break
# Revisamos quien gano la pelea
if Vida_mono_1 >= Vida_mono_2:
return mono_1
else:
return mono_2
Evaluación de resultados
Podiamos decir que en esta ocación, el algoritmo está buscando su óptimo para sobrevivir a generaciones futuras .
Los monos viven en la misma generación pero, no significa que en ellos se encuentren los mismos stats. Como podemos ver las gráficas, existen dos tipos de monos dentro de la misma generación, aquel que fue mutado poco y otro mutado mucho, significa que el porcentaje de variación de mutación de uno con el otro difiere.¿Final?
Fuentes
¿Necesitas ayuda?
Podes hacer preguntas aca abajo en los comentarios o en nuestros perfiles de linkedin que puedes encontrar en este link.
Si estas buscando ayuda en proyectos grandes, nos podes contratar por medio de nuestra consultora haciendo click en este link
. Hacemos ingenieria electromecanica, civil, desarrollo de software y varias cosas mas.
Comentarios
Publicar un comentario