def opciones(tablero, ): rangos = rango_por_letra(FORMAS) rango = rangos[tablero.pentominos[0]] opciones = [] # print("Rango "+str(rango)) for r in range(rango[0], rango[1] + 1): pent = tablero.fichas[r - 1] pentomino = Pentomino(pent[0], int(pent[1]), int(pent[2])) # print("Pentomino "+str(pentomino)) x, y = tablero.comprobar_pentomino(pentomino) # print("("+str(x)+","+str(y)+")") if x != -1: opciones.append([pentomino, x, y]) return opciones
def get_max(siguiente_letra, solucion): rangos = rango_por_letra(Formas) print("Siguiente letra " + str(siguiente_letra)) zona = rangos[siguiente_letra] print("Zona " + str(zona)) solucion_cortado = solucion[zona[0]:zona[1] + 1] print("Cortado " + str(solucion_cortado)) solucion_maximo = np.where(solucion_cortado == np.amax( solucion_cortado)) #cogemos los indices que tengan el valor maximo print("Maximo " + str(solucion_maximo)) solucion_relativo = solucion_maximo[0][0] action = posicion_real(solucion_relativo, siguiente_letra, Formas) print("Action " + str(action)) return action
def crear_conjunto_entrenamiento( ): #Darle solo los valores maximos, las que son mas prometedoras rangos = rango_por_letra(Formas) # pentominos = cargar_pentominos(Formas) if os.path.isfile('../Pentominos/csv/entrenamiento-v4.csv') == False: print( "Fichero de entrenamiento no encontrado, procedemos a su creación") with open('../Pentominos/csv/entrenamiento-v4.csv', 'w') as csvfile: filewriter = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL) if os.path.isfile('../Pentominos/learning/alfabetico.txt') == True: print("Fichero qlearning encontrado") qtable = np.loadtxt('../Pentominos/learning/alfabetico.txt', dtype=float32) letra_i = 0 for row in range(len(qtable)): # print("Fila "+str(row)) letra = Formas[letra_i] zona = rangos[letra] row_plano = np.squeeze(np.asarray(qtable[row])) row_cortado = row_plano[zona[0]:zona[1] + 1] row_maximo = np.where(row_cortado == np.amax(row_cortado)) for index in row_maximo[0]: action = posicion_real(index, letra[0], Formas) filewriter.writerow([row, action]) filewriter.writerow([row, action]) if row == zona[0] - 1 or letra == 'F': letra_i += 1 if letra == 'Z': break print("Completada la creacion de entrenamiento-v4.csv") else: print("Fichero encontrado")
def game2(gameDisplay, modo): pulsadas = [] descartadas = [] pygame.display.set_caption('Q-Learning') turno = piedra_papel_tijeras(gameDisplay) TURNOS.append(turno) clock = pygame.time.Clock() gameDisplay.fill(BLACK) logo = pygame.image.load('images/logo.png') logo = pygame.transform.scale(logo, (250, 57)) gameDisplay.blit(logo, (10, 0)) tablero = Tablero(8, 8, FORMAS) tablero.seleccion_modo(modo) qtable = qlearning(tablero.copy(), modo) tablero.seleccion_modo_real() board(tablero, gameDisplay) out = False replay = False p1, p2 = 0, 0 print("COMIENZA EL JUEGO") while not out: i, _ = tablero.siguiente_zero() p1, p2 = get_puntuacion(tablero) pygame.draw.rect(gameDisplay, BLACK, [0, display_height * 0.85 - 60, display_width, 100]) display_text("P1:" + str(p1), display_width * 0.2, display_height * 0.85, 85, WHITE, gameDisplay) display_text("P2:" + str(p2), display_width * 0.8, display_height * 0.85, 85, WHITE, gameDisplay) for event in pygame.event.get(): if event.type is pygame.QUIT: out = True if i != -1: panel_letras(pulsadas, descartadas, gameDisplay) if TURNOS[-1] == 1: print("Turno jugador 1") op = opciones(tablero) while not op: # print("Descartamos la "+tablero.pentominos[0]) descartadas.append(tablero.pentominos[0]) tablero.pentominos.pop(0) op = opciones(tablero) ficha_colocada, replay, out = colocar_letra( tablero, op, gameDisplay) aux_pent = [ ficha_colocada.letra, str(ficha_colocada.rotacion), str(ficha_colocada.invertido) ] action = tablero.fichas.index(aux_pent) tablero.piezas.append(action) pulsadas.append(ficha_colocada.letra) TURNOS.append(2) pygame.display.update() # print("Ficha: "+str(tablero.movimientos[-1][0])) print(tablero) else: print("Turno jugador 2") op = opciones(tablero) while not op: print("Descartamos la " + tablero.pentominos[0]) descartadas.append(tablero.pentominos[0]) tablero.pentominos.pop(0) op = opciones(tablero) valida = False if not tablero.movimientos: state = 0 else: ultimo_movimiento = tablero.movimientos[-1][0] state = tablero.fichas.index(ultimo_movimiento) + 1 rangos = rango_por_letra(FORMAS) key = get_key(tablero) # print("Piezas "+str(tablero.piezas)) action_completo = np.copy(qtable[state]) action_plano = np.squeeze(np.asarray(action_completo)) zona = rangos[tablero.pentominos[0]] action_cortado_diccionario = action_plano[zona[0]:zona[1] + 1] # print("Action Diccionario "+str(action_cortado_diccionario)) action_cortado = [] for dic in action_cortado_diccionario: # print("Key "+str(key)) if key in dic: action_cortado.append(dic[key]) else: action_cortado.append(0.0) action_cortado = np.copy(action_cortado) while not valida: # print("Zona "+str(action_cortado)) action_maximo = np.where( action_cortado == np.amax(action_cortado) ) #cogemos los indices que tengan el valor maximo # print("Maximos "+str(action_maximo)) rand = random.randint(0, len(action_maximo[0]) - 1) action_relativo = action_maximo[0][ rand] #nos quedamos con el primero ya que todos serian iguales (se podria aleatorizar con epsilon) action = posicion_real( action_relativo, tablero.pentominos[0], FORMAS ) #obtenemos el indice real ya que le anterior era el indice ralivo al array cortado action += 1 print("Ficha(numero) " + str(action)) pent = tablero.fichas[ action - 1] #Comprobar que entra, si no entra ponemos a -1000 esa posicion en la qtable y elegimos otro de los maximos print("Ficha: " + str(pent)) pentomino = Pentomino(pent[0], int(pent[1]), int(pent[2])) x, y = tablero.comprobar_pentomino(pentomino) if x == -1: print("No es valida") action_cortado[action_relativo] = -1000 else: print("Es valida") valida = True tablero.colocar_pentomino_2p(pentomino, x, y, TURNOS[-1]) aux_pent = [ pentomino.letra, str(pentomino.rotacion), str(pentomino.invertido) ] action = tablero.fichas.index(aux_pent) tablero.piezas.append(action) teclas_escR(gameDisplay) pulsadas.append(pentomino.letra) tablero.buscar_huecos(TURNOS[-1]) print(tablero) board(tablero, gameDisplay) TURNOS.append(1) pygame.display.update() elif i == -1: panel_letras(pulsadas, descartadas, gameDisplay) win(p1, p2, gameDisplay) teclas_escR(gameDisplay) pr = parar_reiniciar() if pr == "Replay": tablero.reset(FORMAS, modo) tablero.seleccion_modo_real() pulsadas = [] descartadas = [] board(tablero, gameDisplay) turno = random.randint(1, 2) TURNOS.append(turno) elif pr == "Stop": out = True if replay: replay = False tablero.reset(FORMAS, modo) tablero.seleccion_modo_real() pulsadas = [] board(tablero, gameDisplay) turno = random.randint(1, 2) TURNOS.append(turno) pygame.display.update() clock.tick(30)
def qlearning(tablero, modo=0, epochs=40000, gamma=0.4, epsilon=0.95, decay=0.001, limit=200): fichero = '../Pentominos/learning/alfabetico.txt' if modo == 2: fichero = '../Pentominos/learning/esquinas.txt' elif modo == 3: fichero = '../Pentominos/learning/centro.txt' if os.path.isfile(fichero) == True: qtable = [[{} for i in range(64)] for _ in range(64)] with open(fichero) as file: i = 0 for line in file: split1 = line.split("}]") split = split1[0].split("}, ") j = 0 for trozo in split: trozo = trozo.strip('[{') trozo = trozo.strip('\n') if trozo != '': posibles = trozo.split(', ') for p in posibles: real = p.split(': ') # print(real) dic = {real[0].strip("'"): float(real[1])} qtable[i][j].update(dic) j += 1 i += 1 print("Fichero qlearning encontrado") # qtable = np.loadtxt('../Pentominos/learning/alfabetico.txt', dtype=float32) else: print( "Fichero no encontrado, pasamos a hacer el proceso de aprendizaje, esto llevara unos segundos" ) modo_aux = modo orden = tablero.pentominos pentominos = cargar_pentominos(orden) no_colocadas = [] rangos = rango_por_letra(orden) qtable = [[{} for i in range(len(pentominos) + 1)] for _ in range(len(pentominos) + 1)] for i in range(epochs): state, penalty, done = tablero.reset(orden, modo) steps = 0 no_colocadas = [] fila_aux = [] last_state = state while not done: letra_actual = tablero.pentominos[0] if last_state != state or not np.any(fila_aux): fila_aux = np.copy(qtable[state]) last_state = state key = get_key(tablero) action_completo = fila_aux action_plano = np.squeeze(np.asarray(action_completo)) zona = rangos[tablero.pentominos[0]] action_cortado_diccionario = action_plano[zona[0]:zona[1] + 1] action_cortado = [] for dic in action_cortado_diccionario: if key in dic: action_cortado.append(dic[key]) else: action_cortado.append(0.0) action_cortado = np.copy(action_cortado) if np.random.uniform() < epsilon: if np.count_nonzero(action_cortado) != len(action_cortado): action_minimo = np.where( action_cortado == 0) #cogemos los indices que tengan el valor maximo rand = random.randint(0, len(action_minimo[0]) - 1) action_relativo = action_minimo[0][ rand] #nos quedamos con el primero ya que todos serian iguales (se podria aleatorizar con epsilon) action = posicion_real(action_relativo, tablero.pentominos[0], orden) else: action = tablero.ficha_aleatoria( ) #Usamos colocar random para poner una ficha aleatoria else: action_maximo = np.where( action_cortado == np.amax(action_cortado) ) #cogemos los indices que tengan el valor maximo rand = random.randint(0, len(action_maximo[0]) - 1) action_relativo = action_maximo[0][ rand] #nos quedamos con el primero ya que todos serian iguales (se podria aleatorizar con epsilon) action = posicion_real( action_relativo, tablero.pentominos[0], orden ) #obtenemos el indice real ya que le anterior era el indice ralivo al array cortado action += 1 #Sumamos uno para contar en la tabla el hueco para la posicion 0 next_state, penalty, done = tablero.colocar_siguiente( action, state ) #Importante comprobar que la letra no este ya usada y que no quedan huecos para el reward if done or not tablero.pentominos: faltantes = len(tablero.pentominos) + len(no_colocadas) qtable[state][action].update( {key: 50 + penalty - 10 * faltantes}) if faltantes <= modo: if modo_aux == 0: epsilon -= decay * epsilon modo_aux = modo else: modo_aux -= 1 else: if penalty == -1000: fila_aux[action].update({get_key(tablero): penalty}) reward_completo = fila_aux #Buscamos en el estado zona = rangos[ letra_actual] #Obtenemos la zona de la table que afecta a la letra actual #Convertimos en array "aplaanamos" reward_plano = np.squeeze( np.asarray(reward_completo )) #Convertimos en array "aplaanamos" reward_cortado_diccionario = reward_plano[ zona[0]:zona[1] + 1] #cortamos el array para quedarnos solo con la zona de siguietes acciones reward_cortado = [] for dic in reward_cortado_diccionario: if key in dic: reward_cortado.append(dic[key]) else: reward_cortado.append(0.0) reward_maximo = np.amax(reward_cortado) if reward_maximo == -1000: no_colocadas.append( letra_actual ) #La ficha se ha probado en todas direcciones y no cabe en el tablero, asi que se pasa turno tablero.pentominos.pop(0) else: reward_maximo = valor_maximo(qtable, rangos, tablero.pentominos[0], next_state, tablero) qtable[state][action].update( {key: penalty + gamma * reward_maximo}) state = next_state steps += 1 if steps > limit or not tablero.pentominos: done = True print(" ") print("epoch #", i + 1, "/", epochs, " .Step: ", steps) print(tablero) no_colocadas.append(tablero.pentominos) print(no_colocadas) print(tablero.piezas) print("Epsilon " + str(epsilon)) print("\nDone in", steps, "steps".format(steps)) with open(fichero, 'w+') as f: for item in qtable: f.write(str(item)) f.write("\n") return qtable