// Si se ha encontrado el objetivo, devuelve la lista operadores hasta llegar hasta él. // Si ya estás en el objetivo, devuelve una lista con un sólo operador NoOp dentro. // Si falla en encontrar el objetivo se devuelve una lista vacía y eso significa que la búsqueda ha fallado. public virtual List <Operator> Search(Problem problem, IQueue <Node> frontier) { this.frontier = frontier; ClearInstrumentation(); // initialize the frontier using the initial setup of the problem Node root = new Node(problem.GetInitialSetup()); if (IsCheckGoalBeforeAddingToFrontier()) { if (SearchUtils.IsGoalSetup(problem, root)) { return(SearchUtils.GetOperatorsFromNodes(root.GetPathFromRoot())); } } frontier.Enqueue(root); setQueueSize(frontier.Count); while (!(frontier.Count == 0)) { // choose a leaf node and remove it from the frontier Node nodeToExpand = PopNodeFromFrontier(); setQueueSize(frontier.Count); // Only need to check the nodeToExpand if have not already // checked before adding to the frontier if (!IsCheckGoalBeforeAddingToFrontier()) { // if the node contains a goal setup then return the corresponding solution if (SearchUtils.IsGoalSetup(problem, nodeToExpand)) { setPathCost(nodeToExpand.GetPathCost()); return(SearchUtils.GetOperatorsFromNodes(nodeToExpand .GetPathFromRoot())); } } // expand the chosen node, adding the resulting nodes to the // frontier foreach (Node fn in GetResultingNodesToAddToFrontier(nodeToExpand, problem)) { if (IsCheckGoalBeforeAddingToFrontier()) { if (SearchUtils.IsGoalSetup(problem, fn)) { setPathCost(fn.GetPathCost()); return(SearchUtils.GetOperatorsFromNodes(fn .GetPathFromRoot())); } } frontier.Enqueue(fn); } setQueueSize(frontier.Count); } // if the frontier is empty then return failure return(Failure()); }
// Devuelve si es cierto o no que un nodo contiene una configuración objetivo public static bool IsGoalSetup(Problem p, Node n) { bool isGoal = false; GoalTest gt = p.GetGoalTest(); if (gt.IsGoalSetup(n.GetSetup())) { if (gt is SolutionChecker) { isGoal = ((SolutionChecker)gt).IsAcceptableSolution( SearchUtils.GetOperatorsFromNodes(n.GetPathFromRoot()), n .GetSetup()); } else { isGoal = true; } } return(isGoal); }
// Busca la solución a un problema, usando una cola como frontera (FIFO, LIFO, de prioridad...), y devuelve la lista de operadores para llegar desde la configuración actual a una configuración objetivo // Si se ha encontrado un objetivo, se devuelve únicamente la lista de operadores // Si la propia configuración inicial ya es un objetivo, devuelve una lista con un sólo operador: NoOp // Si la búsqueda no logra encontrar un objetivo, se devuelve una lista vacía para representar el fallo public virtual List <Operator> Search(Problem problem, IQueue <Node> frontier) { ClearMetrics(); // Se inicializa la frontera con la configuración inicial del problema Node root = new Node(problem.InitialSetup); // Si debemos hacer la prueba de objetivo antes de meterlo en la frontera, la hacemos... if (TestGoalBeforeAddToFrontier) { // ... y si resulta que es un objetivo, devolvemos ya la solución if (SearchUtils.IsGoal(problem, root)) { SetPathCost(root.PathCost); return(SearchUtils.GetOperatorsFromNodes(root.GetPathFromRoot())); } } this.frontier = frontier; this.frontier.Enqueue(root); SetQueueSizes(frontier.Count); // Mientras que queden nodos en la frontera, expandirlos y buscar en sus hijos while (!(frontier.Count == 0)) { // Sacar un nodo de la frontera (el que corresponda según el tipo de cola que sea la frontera) Node node = PopNodeFromFrontier(); UnityEngine.Debug.Log("Expanding " + node.ToString()); SetQueueSizes(frontier.Count); // Si no hicimos la prueba de objetivo antes de meterlo en la frontera, toca hacerla ahora... if (!TestGoalBeforeAddToFrontier) { // ... y si resulta que es un objetivo, devolvemos ya la solución if (SearchUtils.IsGoal(problem, node)) { SetPathCost(node.PathCost); return(SearchUtils.GetOperatorsFromNodes(node.GetPathFromRoot())); } } // Expandimos el nodo, añadiendo sus hijos a la frontera foreach (Node child in GetResultingNodesToAddToFrontier(node, problem)) { // Si debemos hacer la prueba de objetivo antes de meterlo en la frontera, la hacemos... if (TestGoalBeforeAddToFrontier) { // ... y si resulta que es un objetivo, devolvemos ya la solución if (SearchUtils.IsGoal(problem, child)) { SetPathCost(child.PathCost); return(SearchUtils.GetOperatorsFromNodes(child.GetPathFromRoot())); } } frontier.Enqueue(child); UnityEngine.Debug.Log("Adding " + child.ToString() + " to the frontier"); } SetQueueSizes(frontier.Count); } // Si la frontera ha quedado vacía y no hemos dado con ninguna solución, devolvemos fallo (representado por una lista vacía de operadores) return(new List <Operator>()); }