public List <Operator> Search(Problem p) { // AL CONSTRUCTOR LE METÍAN UN 5 A CAPÓN COMO PRIMER PARÁMETRO (INITIALCAPACITY)... ESO CREO QUE YA NO HACE FALTA, QUE ESTA LISTA DE PREORIDAD SE REDIMENSIONA SOLA return(search.Search(p, new PriorityQueueWrapper())); // He puesto Node, Node... tanto en los Item como en la prioridad... // NO LE METO COMPARER NI NADA PORQUE LA IDEA NO VA A SER AQUÍ COPARAR NODOS SINO QUE INTERNAMENTE SE COMPAREN FLOATS, SOLAMENTE }
// Dado el nodo a expandir (y considerando el problema), devuelve los nodos hijos que hace falta añadir a la frontera public abstract List <Node> GetResultingNodesToAddToFrontier(Node node, Problem problem);
// 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>()); }
/* Ahora mismo no tiene sentido hacer un borrado de un nodo que no sea el primeroque ofrece la cola * public override bool RemoveNodeFromFrontier(Node toRemove) * { * bool removed = base.RemoveNodeFromFrontier(toRemove); * if (removed) * { * frontierSetup.Remove(toRemove.GetSetup()); * } * return removed; * } */ public override List <Node> GetResultingNodesToAddToFrontier(Node nodeToExpand, Problem problem) { addToFrontier.Clear(); // add the node to the explored set explored.Add(nodeToExpand.GetSetup()); // expand the chosen node, adding the resulting nodes to the frontier foreach (Node cfn in ExpandNode(nodeToExpand, problem)) { Node frontierNode; frontierSetup.TryGetValue(cfn.GetSetup(), out frontierNode); // El funcionamiento de este Diccionario parece estar fallando (antes es que tenía notación de array y seguramente no era válido) bool yesAddToFrontier = false; // only if not in the frontier or explored set if (null == frontierNode && !explored.Contains(cfn.GetSetup())) { yesAddToFrontier = true; } else if (null != frontierNode && null != replaceFrontierNodeAtSetupCostFunction && replaceFrontierNodeAtSetupCostFunction.Compare(cfn, frontierNode) < 0) { // child.SETUP is in frontier with higher cost // replace that frontier node with child yesAddToFrontier = true; // Want to replace the current frontier node with the child // node therefore mark the child to be added and remove the // current fontierNode /************************************************************** * POR AHORA HE ELIMINADO ESTA PARTE, HAY COMENTARIOS DE QUE USANDO COLAS DE PRIORIDAD NO SE NECESITA ESTO * ADEMÁS TÉCNICAMENTE NO SE PUEDE ELIMINAR UN NODO DE FORMA TAN DIRECTAN DE UNA COLA... * * RemoveNodeFromFrontier(frontierNode); **********************************************/ // Ensure removed from add to frontier as well // as 1 or more may reach the same setup at the same time addToFrontier.Remove(frontierNode); } if (yesAddToFrontier) { addToFrontier.Add(cfn); frontierSetup.Add(cfn.GetSetup(), cfn); } } return(addToFrontier); }