class Agent: """""" counter = -1 # Contador de passos no plano, usado na deliberação def __init__(self, model): """Construtor do agente. @param model: Referência do ambiente onde o agente atuará.""" self.model = model self.prob = Problem() # @TODO T_AAFP - criar crencas sobre as paredes do labirinto self.prob.createMaze(9, 9) self.prob.mazeBelief.putVerticalWall(0,1,0) self.prob.mazeBelief.putVerticalWall(0,0,1) self.prob.mazeBelief.putVerticalWall(5,8,1) self.prob.mazeBelief.putVerticalWall(5,5,2) self.prob.mazeBelief.putVerticalWall(8,8,2) self.prob.mazeBelief.putHorizontalWall(4,7,0) self.prob.mazeBelief.putHorizontalWall(7,7,1) self.prob.mazeBelief.putHorizontalWall(3,5,2) self.prob.mazeBelief.putHorizontalWall(3,5,3) self.prob.mazeBelief.putHorizontalWall(7,7,3) self.prob.mazeBelief.putVerticalWall(6,7,4) self.prob.mazeBelief.putVerticalWall(5,6,5) self.prob.mazeBelief.putVerticalWall(5,7,7) # Posiciona fisicamente o agente no estado inicial initial = self.positionSensor() self.prob.defInitialState(initial.row, initial.col) self.cost = 0 self.nextState = self.prob.initialState # Define o estado atual do agente = estado inicial self.currentState = self.prob.initialState # @TODO T_AAFP - defina estado objetivo # Define o estado objetivo # self.prob.defGoalState(?, ?) self.prob.defGoalState(0,8) # o metodo abaixo serve apenas para a view desenhar a pos objetivo # self.model.setGoalPos(2,8) self.model.setGoalPos(0,8) # Plano de busca - inicialmente vazio (equivale a solucao) self.plan = None def printPlan(self): """Apresenta o plano de busca.""" print("--- PLANO ---") # @TODO: Implementação do aluno for plannedAction in self.plan: print("{} > ".format(action[plannedAction]),end='') print("FIM\n\n") def deliberate(self): # Primeira chamada, realiza busca para elaborar um plano # @TODO T_AAFP: Implementação do aluno if self.counter == -1: # @TODO T_AAFP: dar um plano fixo ao agente (preh-programado) - ver cardinal.py # @TODO T_AAFP: plano = solucao: contem acoes que levam o agente ateh o estado objetivo self.plan = [0,0,0,1,2,2,2,2,1,1,2,0,0] if self.plan != None: self.printPlan() else: print("SOLUÇÃO NÃO ENCONTRADA") return -1 # Nas demais chamadas, executa o plano já calculado self.counter += 1 # @TODO T_AAFP - testar se atingiu o estado objetivo ou se chegou ao final do plano sem alcancar o objetivo if(self.prob.goalTest(self.positionSensor())): #colocar print final aqui print("*************** ultimo ciclo ***********************") print("estado atual:" + str(self.currentState)) print("ct = "+ str(self.counter) +" de "+str(len(self.plan))) print("custo ate o momento (com a acao escolhida):"+str(self.cost)) print("Objetivo conquistado!!!") print("****************************************************\n") return -1 elif(self.counter == len(self.plan)): #colocar um print aqui depois print("*************** ultimo ciclo ***********************") print("estado atual:" + str(self.currentState)) print("ct = "+ str(self.counter) +" de "+str(len(self.plan))) print("custo ate o momento (com a acao escolhida):"+str(self.cost)) print("Objetivo nao conquistado!!") print("****************************************************\n") return -1 possibleAction = self.prob.possibleActions(self.positionSensor()) currentAction = self.plan[self.counter] self.nextState = self.prob.suc(self.currentState,currentAction) # @TODO T_AAFP - fazer prints solicitados print("*************** inicio do ciclo ***********************") print("estado atual:" + str(self.currentState)) print("proximo estado:" + str(self.nextState)) print("açoes possiveis:{ ", end= '') for i in range(len(action)): if(possibleAction[i]==1): print("{} ".format(action[i]),end='') print("}") print("ct = "+ str(self.counter) +" de "+str(len(self.plan))+ ". Ação escolhida=" +action[currentAction]) print("custo ate o momento (com a acao escolhida):" + str(self.cost)) print("****************************************************\n") # @TODO T_AAFP - o agente deve executar a acao e atualizar seu estado atual self.executeGo(currentAction) self.cost += self.prob.getActionCost(currentAction) self.currentState = self.positionSensor() return 1 def executeGo(self, direction): """Atuador: solicita ao agente física para executar a ação. @param direction: Direção da ação do agente @return 1 caso movimentação tenha sido executada corretamente.""" self.model.go(direction) return 1 def positionSensor(self): """Simula um sensor que realiza a leitura do posição atual no ambiente e traduz para uma instância da classe Estado. @return estado que representa a posição atual do agente no labirinto.""" pos = self.model.agentPos return State(pos[0],pos[1])
class Agent: """""" counter = -1 # Contador de passos no plano, usado na deliberação def __init__(self, model): """Construtor do agente. @param model: Referência do ambiente onde o agente atuará.""" self.model = model self.prob = Problem() self.prob.createMaze(6, 6) self.prob.mazeBelief.putVerticalWall(2, 4, 3) self.prob.mazeBelief.putHorizontalWall(0, 1, 2) # Posiciona fisicamente o agente no estado inicial initial = self.positionSensor() self.prob.defInitialState(initial.row, initial.col, initial.boxes) # Define o estado atual do agente = estado inicial self.currentState = self.prob.initialState # Define o estado objetivo self.prob.defGoalState(0, 0, [(5, 1), (5, 4), (5, 5)]) self.model.addGoalPos(5, 5) self.model.addGoalPos(5, 4) #self.model.addGoalPos(5,3) #self.model.addGoalPos(5,2) self.model.addGoalPos(5, 1) #self.model.addGoalPos(5,0) # Plano de busca self.plan = None def deliberate(self): # Primeira chamada, realiza busca para elaborar um plano if self.counter == -1: self.plan = self.cheapestFirstSearch( H_OPT ) # 0 = custo uniforme, 1 = A* com colunas, 2 = A* com dist Euclidiana if self.plan != None: self.printPlan() else: print("SOLUÇÃO NÃO ENCONTRADA") return -1 # Nas demais chamadas, executa o plano já calculado self.counter += 1 # Atingiu o estado objetivo if self.prob.goalTest(self.currentState): print("!!! ATINGIU O ESTADO OBJETIVO !!!") return -1 # Algo deu errado, chegou ao final do plano sem atingir o objetivo if self.counter >= len(self.plan): print( "### ERRO: plano chegou ao fim, mas objetivo não foi atingido." ) return -1 currentAction = self.plan[self.counter] print("--- Mente do Agente ---") print("{0:<20}{1}".format("Estado atual :", self.currentState)) print("{0:<20}{1} de {2}. Ação= {3}\n".format("Passo do plano :", self.counter + 1, len(self.plan), action[currentAction])) self.executeGo(currentAction) # Atualiza o estado atual baseando-se apenas nas suas crenças e na função sucessora # Não faz leitura do sensor de posição self.currentState = self.prob.suc(self.currentState, currentAction) return 1 def executeGo(self, direction): """Atuador: solicita ao agente física para executar a ação. @param direction: Direção da ação do agente @return 1 caso movimentação tenha sido executada corretamente.""" self.model.go(direction) return 1 def positionSensor(self): """Simula um sensor que realiza a leitura do posição atual no ambiente e traduz para uma instância da classe Estado. @return estado que representa a posição atual do agente no labirinto.""" pos = self.model.agentPos return State(pos[0], pos[1], self.model.boxPos, 0) def hn(self, state): goalBoxes = self.prob.goalState.boxes h = 0 distsToAgent = [] for i in range(len(goalBoxes)): box = goalBoxes[i] sBox = state.boxes[i] distsToAgent.append( (abs(sBox[0] - state.row), abs(sBox[1] - state.col))) h += abs(box[0] - sBox[0]) + abs(box[1] - sBox[1]) minDist = min(distsToAgent) h += minDist[0] + minDist[ 1] # menor distancia entre o agente e as caixas return h def hnmeans(self, state): goalBoxes = self.prob.goalState.boxes h = 0 for gbox in goalBoxes: m = 0 for sbox in state.boxes: m += abs(gbox[0] - sbox[0]) + abs(gbox[1] - sbox[1]) h += (m / len(state.boxes)) + (abs(sbox[0] - state.row) + abs(sbox[1] - state.col)) return h def hnwall(self, state): goalBoxes = self.prob.goalState.boxes h = 0 distsToAgent = [] for i in range(len(goalBoxes)): box = goalBoxes[i] sBox = state.boxes[i] distsToAgent.append( abs(sBox[0] - state.row) + abs(sBox[1] - state.col) + self.prob.checkWall(sBox, (state.row, state.col))) h += abs(box[0] - sBox[0]) + abs(box[1] - sBox[1]) + self.prob.checkWall( sBox, box) minDist = min(distsToAgent) h += minDist # menor distancia entre o agente e as caixas return h def hnOptm(self, state): distsg = [(state.row, state.col)] distsg += [box for box in self.prob.goalState.boxes] dists = [box for box in state.boxes] distsg.sort() dists.sort() h = 0 for i in range(len(dists)): h += abs(dists[i][0] - distsg[i][0]) + abs(dists[i][1] - distsg[i][1]) h += abs(dists[i][0] - distsg[i + 1][0]) + abs(dists[i][1] - distsg[i + 1][1]) return h def hnOptmWall(self, state): distsg = [(state.row, state.col)] distsg += [box for box in self.prob.goalState.boxes] dists = [box for box in state.boxes] distsg.sort() dists.sort() h = 0 for i in range(len(dists)): h += abs(dists[i][0] - distsg[i][0]) + abs(dists[i][1] - distsg[i][1]) h += abs(dists[i][0] - distsg[i + 1][0]) + abs(dists[i][1] - distsg[i + 1][1]) h += self.prob.checkWall(dists[i], distsg[i]) + self.prob.checkWall( dists[i], distsg[i + 1]) return h def hnOptmEucl(self, state): distsg = [(state.row, state.col)] distsg += [box for box in self.prob.goalState.boxes] dists = [box for box in state.boxes] distsg.sort() dists.sort() h = 0 for i in range(len(dists)): h += abs(dists[i][0] - distsg[i][0])**2 h += abs(dists[i][1] - distsg[i][1])**2 h += abs(dists[i][0] - distsg[i + 1][0])**2 h += abs(dists[i][1] - distsg[i + 1][1])**2 return h**0.5 def cheapestFirstSearch(self, searchType): """Realiza busca com a estratégia de custo uniforme ou A* conforme escolha realizada na chamada. @param searchType: 0=custo uniforme, 1=A* com heurística hn1; 2=A* com hn2 @return plano encontrado""" # Atributos para análise de desempenho treeNodesCt = 0 # contador de nós gerados incluídos na árvore # nós inseridos na árvore, mas que não necessitariam porque o estado # já foi explorado ou por já estar na fronteira exploredDicardedNodesCt = 0 frontierDiscardedNodesCt = 0 # Algoritmo de busca solution = None root = TreeNode(parent=None) root.state = self.prob.initialState root.gn = 0 root.hn = 0 root.action = -1 treeNodesCt += 1 # cria FRONTEIRA com estado inicial frontier = [] frontier.append(root) # cria EXPLORADOS - inicialmente vazia explored = {} print("\n*****\n***** INICIALIZAÇÃO ÁRVORE DE BUSCA\n*****\n") print("\n{0:<30}{1}".format("Nós na árvore: ", treeNodesCt)) print("{0:<30}{1}".format("Descartados já na fronteira: ", frontierDiscardedNodesCt)) print("{0:<30}{1}".format("Descartados já explorados: ", exploredDicardedNodesCt)) print("{0:<30}{1}".format( "Total de nós gerados: ", treeNodesCt + frontierDiscardedNodesCt + exploredDicardedNodesCt)) while len(frontier): # Fronteira não vazia print("\n*****\n***** Início iteração\n*****\n") #printFrontier(frontier) selNode = frontier.pop(0) # retira nó da fronteira selState = selNode.state print("Selecionado para expansão: {}\n".format(selNode)) # Teste de objetivo if selState == self.prob.goalState: solution = selNode break explored[str(selState.row) + str(selState.col) + str(selState.boxes)] = selState #printExplored(explored) # Obtem ações possíveis para o estado selecionado para expansão actions = self.prob.possibleActions( selState) # actions é do tipo [-1, -1, -1, 1 ] if selNode.gn >= LIMITE_BUSCA and VERIFICA_LIMITE: continue for actionIndex, act in enumerate(actions): if (act < 0): # Ação não é possível continue # INSERE NÓ FILHO NA ÁRVORE DE BUSCA - SEMPRE INSERE, DEPOIS # VERIFICA SE O INCLUI NA FRONTEIRA OU NÃO # Obtem o estado sucessor pela execução da ação <act> sucState = self.prob.suc(selState, actionIndex) # verifica se a acao sucessora bloqueia o tabuleiro if (VERIFICA_ACAO_BLOQUEIO and self.prob.isBlockAction(sucState)): continue # Instancia o filho ligando-o ao nó selecionado (nSel) child = selNode.addChild() child.state = sucState # Custo g(n): custo acumulado da raiz até o nó filho gnChild = selNode.gn + self.prob.getActionCost(actionIndex) if searchType == UNIFORME_COST: child.setGnHn( gnChild, 0 ) # Deixa h(n) zerada porque é busca de custo uniforme elif searchType == HEURISTICA_DISTS: child.setGnHn(gnChild, self.hn(sucState)) elif searchType == HEURISTICA_DISTS_PEN_OBSTACULOS: child.setGnHn(gnChild, self.hnwall(sucState)) elif searchType == H_OPT: child.setGnHn(gnChild, self.hnOptm(sucState)) elif searchType == H_EUCL: child.setGnHn(gnChild, self.hnOptmEucl(sucState)) elif searchType == H_OPT_PEN: child.setGnHn(gnChild, self.hnOptmWall(sucState)) child.action = actionIndex # INSERE NÓ FILHO NA FRONTEIRA (SE SATISFAZ CONDIÇÕES) alreadyExplored = False # Testa se estado do nó filho foi explorado expHash = str(child.state.row) + str(child.state.col) + str( child.state.boxes) if expHash in explored: exp = explored[expHash] if (child.state.cost >= exp.cost): alreadyExplored = True # Testa se estado do nó filho está na fronteira, caso esteja # guarda o nó existente em nFront nodeFront = None if not alreadyExplored: for node in frontier: if (child.state == node.state and child.state.row == node.state.row and child.state.col == node.state.col): nodeFront = node break # Se ainda não foi explorado if not alreadyExplored: # e não está na fronteira, adiciona à fronteira if nodeFront == None: # adiciona na fronteira se a acao nao bloqueia a solucao frontier.append(child) frontier.sort( key=lambda x: (x.getFn(), x.hn) ) # Ordena a fronteira pelo f(n), usando o valor de hn como desempate treeNodesCt += 1 else: # Se já está na fronteira temos que ver se é melhor if nodeFront.getFn() > child.getFn( ): # Nó da fronteira tem custo maior que o filho frontier.remove( nodeFront ) # Remove nó da fronteira (pior e deve ser substituído) nodeFront.remove() # Retira-se da árvore frontier.append( child) # Adiciona filho que é melhor #frontier.sort(key=lambda x: x.getFn() ) # Ordena a fronteira pelo f(n), ascendente frontier.sort( key=lambda x: (x.getFn(), x.hn) ) # Ordena a fronteira pelo f(n), usando o valor de hn como desempate # treeNodesCt não é incrementado por inclui o melhor e retira o pior else: # Conta como descartado porque o filho é pior que o nó da fronteira e foi descartado frontierDiscardedNodesCt += 1 else: exploredDicardedNodesCt += 1 print("\n{0:<30}{1}".format("Nós na árvore: ", treeNodesCt)) print("{0:<30}{1}".format("Descartados já na fronteira: ", frontierDiscardedNodesCt)) print("{0:<30}{1}".format("Descartados já explorados: ", exploredDicardedNodesCt)) print("{0:<30}{1}".format( "Total de nós gerados: ", treeNodesCt + frontierDiscardedNodesCt + exploredDicardedNodesCt)) if (solution != None): print("!!! Solução encontrada !!!") print("!!! Custo: {}".format(solution.gn)) print("!!! Profundidade: {}\n".format(solution.depth)) print("\n{0:<30}{1}".format("Nós na árvore: ", treeNodesCt)) print("{0:<30}{1}".format("Descartados já na fronteira: ", frontierDiscardedNodesCt)) print("{0:<30}{1}".format("Descartados já explorados: ", exploredDicardedNodesCt)) print("{0:<30}{1}".format( "Total de nós gerados: ", treeNodesCt + frontierDiscardedNodesCt + exploredDicardedNodesCt)) return buildPlan(solution) else: print("### Solução NÃO encontrada ###") return None def printPlan(self): """Apresenta o plano de busca.""" print("--- PLANO ---") # @TODO: Implementação do aluno for plannedAction in self.plan: print("{} > ".format(action[plannedAction]), end='') print("FIM\n\n")
class Agent: def __init__(self, model): """Construtor do agente. @param model: Referência do ambiente onde o agente atuará.""" self.model = model ## Pega o tipo de mesh, que está no model (influência na movimentação) self.mesh = self.model.mesh ## Cria a instância do problema para o agente self.prob = Problem() self.prob.createMaze(model.rows, model.columns, model.maze) # Posiciona fisicamente o agente no estado inicial initial = self.positionSensor() self.prob.defInitialState(initial.row, initial.col) # Define o estado atual do agente = estado inicial self.currentState = self.prob.initialState # Define o estado objetivo self.prob.defGoalState(model.goalPos[0], model.goalPos[1]) """ DEFINE OS PLANOS DE EXECUÇÃO DO AGENTE """ ##Para usar o Planner online, exemplo abaixo: ##plann = Planner() ##print(plann.generate()) # Plano de busca - inicialmente vazio (equivale a solucao) self.plan = [] ##Custo da solução self.costAll = 0 ## Cria a instancia do algoritmo LRTA* self.planToGoal = Lrta(model.rows, model.columns, self.prob.goalState, initial, "goal", self.mesh) self.planToGoal.startManhattanHeuristic(self.prob.mazeBelief.walls) ## Coloca na biblioteca de planos todos os planos possíveis self.libPlan = [] ## Coloca dentro do plano as ações, nesse caso, ele deve executar o LRTA self.plan = [] ## Metodo que define a deliberacao do agente def deliberate(self): ## Verifica se há algum plano a ser executado if len(self.plan) == 0: return -1 print ("******************************Inicio do ciclo***************") print("Posição agente : {0},{1}".format(self.model.agentPos[0],self.model.agentPos[1])) ## Define a proxima acao a ser realizada como a primeira do plano currentAction = self.plan[0] ## Executa esse acao, atraves do metodo executeGo self.executeGo(currentAction) ## Redefine o estado atual do agente self.currentState = self.positionSensor() ## Atualiza a biblioteca de planos self.updateLibPlan() ## Soma o custo da acao com o total self.costAll += self.prob.getActionCost(currentAction) print ("Custo até o momento (com a ação escolhida):", self.costAll) print ("***************************************************************") return 1 ## Metodo que executa as acoes def executeGo(self, action): """Atuador: solicita ao agente físico para executar a acao. @param direction: Direcao da acao do agente @return 1 caso movimentacao tenha sido executada corretamente.""" ## Passa a acao para o modelo result = self.model.go(action) ## Se o resultado for True, significa que a acao foi completada com sucesso, e ja pode ser removida do plano if (result): del self.plan[0] self.actionGo([6,7], True) return 1 ## Metodo que pega a posicao real do agente no ambiente def positionSensor(self): """Simula um sensor que realiza a leitura do posição atual no ambiente e traduz para uma instância da classe Estado. @return estado que representa a posição atual do agente no labirinto.""" pos = self.model.agentPos return State(pos[0],pos[1]) ## Metodo que atualiza a biblioteca de planos, de acordo com o estado atual do agente def updateLibPlan(self): for i in self.libPlan: i.updateCurrentState(self.currentState) def actionGo(self, posAction, action = True): self.model.do(posAction, action) def addPlan(self, plano): self.plan.append(plano)
class Agent: """""" counter = -1 # Contador de passos no plano, usado na deliberação def __init__(self, model): """Construtor do agente. @param model: Referência do ambiente onde o agente atuará.""" self.model = model self.prob = Problem() self.prob.createMaze(9, 9) self.prob.mazeBelief.putVerticalWall(0, 1, 0) self.prob.mazeBelief.putVerticalWall(0, 0, 1) self.prob.mazeBelief.putHorizontalWall(4, 6, 0) self.prob.mazeBelief.putVerticalWall(0, 1, 7) self.prob.mazeBelief.putHorizontalWall(3, 5, 2) self.prob.mazeBelief.putHorizontalWall(3, 5, 3) self.prob.mazeBelief.putHorizontalWall(7, 7, 3) self.prob.mazeBelief.putHorizontalWall(1, 2, 5) self.prob.mazeBelief.putVerticalWall(6, 7, 1) self.prob.mazeBelief.putVerticalWall(6, 7, 4) self.prob.mazeBelief.putVerticalWall(5, 6, 5) self.prob.mazeBelief.putVerticalWall(5, 7, 7) self.prob.mazeBelief.putHorizontalWall(1, 2, 8) # Posiciona fisicamente o agente no estado inicial initial = self.positionSensor() self.prob.defInitialState(initial.row, initial.col) # Define o estado atual do agente = estado inicial self.currentState = self.prob.initialState # Define o estado objetivo self.prob.defGoalState(2, 8) # o metodo abaixo serve apenas para a view desenhar a pos objetivo self.model.setGoalPos(2, 8) # Plano de busca - inicialmente vazio (equivale a solucao) self.plan = None def printPlan(self): """Apresenta o plano de busca.""" print("--- PLANO ---") # @TODO: Implementação do aluno for plannedAction in self.plan: print("{} > ".format(action[plannedAction]), end='') print("FIM\n\n") def deliberate(self): # Primeira chamada, realiza busca para elaborar um plano if self.counter == -1: self.plan = [N, N, N, NE, L, L, L, L, L, L, NE, N] if self.plan != None: self.printPlan() else: print("SOLUÇÃO NÃO ENCONTRADA") return -1 # Nas demais chamadas, executa o plano já calculado self.counter += 1 if self.prob.goalTest(self.positionSensor()): return -1 currentAction = self.plan[self.counter] self.executeGo(self.plan[self.counter]) self.currentState = self.positionSensor() cost = 0.0 for i in range(-1, self.counter): cost += self.prob.getActionCost(self.plan[i + 1]) print("*****************************************************") print("estado atual : ({0},{1})".format(self.model.agentPos[0], self.model.agentPos[1])) print("acoes possiveis:", end='') actions = self.prob.possibleActions(self.positionSensor()) for i in range(0, len(actions)): if actions[i] != -1: print(" {0}".format(action[i]), end='') print("\nct: {0} de {1}".format(self.counter + 1, len(self.plan))) print("custo ate o momento (com a acao escolhida): {0}".format(cost)) print("*****************************************************\n") return 1 def executeGo(self, direction): """Atuador: solicita ao agente física para executar a ação. @param direction: Direção da ação do agente @return 1 caso movimentação tenha sido executada corretamente.""" self.model.go(direction) return 1 def positionSensor(self): """Simula um sensor que realiza a leitura do posição atual no ambiente e traduz para uma instância da classe Estado. @return estado que representa a posição atual do agente no labirinto.""" pos = self.model.agentPos return State(pos[0], pos[1])