Example #1
0
    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"""
        # @TODO: Implementação do aluno
        # 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
        solutionBox = []
        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))

            if self.prob.goalBoxTest():
                solutionBox.append(selNode)
                if self.prob.goalFinalTest():
                    solution = selNode
                    break
            explored.append(selNode)
            printExplored(explored)

            # Obtem ações possíveis para o estado selecionado para expansão
            actions = self.prob.possibleActionsWithoutCollaterals(
                selState)  # actions é do tipo [-1, -1, -1, 1, 1, -1, -1, -1]

            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
                # Instancia o filho ligando-o ao nó selecionado (nSel)
                child = selNode.addChild()
                # Obtem o estado sucessor pela execução da ação <act>
                sucState = self.prob.suc(selState, actionIndex)
                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 == A_START_1:
                    child.setGnHn(gnChild, self.hn1(sucState, actionIndex))
                elif searchType == A_START_2:
                    child.setGnHn(gnChild, self.hn2(sucState))

                child.action = actionIndex
                # INSERE NÓ FILHO NA FRONTEIRA (SE SATISFAZ CONDIÇÕES)

                # Testa se estado do nó filho foi explorado
                alreadyExplored = False
                # for node in explored:
                #     if child.state == node.state:
                #         alreadyExplored = True
                #         break

                # 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):
                            nodeFront = node
                            break
                # Se ainda não foi explorado
                if not alreadyExplored:
                    # e não está na fronteira, adiciona à fronteira
                    if nodeFront == None:
                        frontier.append(child)
                        frontier.sort(key=lambda x: x.getFn(
                        ))  # Ordena a fronteira pelo f(n), ascendente
                        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
                            # 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
Example #2
0
    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