// admisible, consistente y dominante: devolvera la distancia euclidea entre el // nodo e y el destino private double heuristic3(NodeCool e) { int inix = (int)(e.GetPos() / gm.columns); int iniy = (int)(e.GetPos() - inix * gm.columns); int destx = (int)(f_ / gm.columns); int desty = (int)(f_ - destx * gm.columns); double catA = destx - inix; double catB = desty - iniy; return(Math.Sqrt(catA * catA + catB * catB)); // hipotenusa }
// admisible y consistente: devolvera la suma del numero de casillas horizontales // y verticales que separan al nodo e del destino private double heuristic2(NodeCool e) { int inix = (int)(e.GetPos() / gm.columns); int iniy = (int)(e.GetPos() - inix * gm.columns); int destx = (int)(f_ / gm.columns); int desty = (int)(f_ - destx * gm.columns); double A = Math.Abs(destx - inix); double B = Math.Abs(desty - iniy); return(A + B); }
// admisible e inconsistente: devolvera una h aleatoria, nunca mayor que el // coste fisico minimo de ir desde el nodo actual al destino (1 x numCasillas hasta el destino) private double heuristic1(NodeCool e) { int inix = (int)(e.GetPos() / gm.columns); int iniy = (int)(e.GetPos() - inix * gm.columns); int destx = (int)(f_ / gm.columns); int desty = (int)(f_ - destx * gm.columns); double A = Math.Abs(destx - inix); double B = Math.Abs(desty - iniy); System.Random rnd = new System.Random(); return(rnd.Next(0, (int)(A + B + 1)));; }
// elige una de las heuristicas dado el tipo de heuristica que reciba public double chooseHeuristic(TipoHeuristicas t, NodeCool e, int fin) { f_ = fin; switch (t) { case TipoHeuristicas.H1: return(heuristic1(e)); case TipoHeuristicas.H2: return(heuristic2(e)); case TipoHeuristicas.H3: return(heuristic3(e)); default: return(0.0); } }
private HeuristicFunctions heuristic = new HeuristicFunctions(); // elige las heuristicas public void Init(EdgeWeightedDigraph G, ref List <NodeCool> list, int s = 0, int f = 0, TipoHeuristicas H = TipoHeuristicas.SINH) { // inicializacion de variables s_ = s; f_ = f; nodeGraph = new List <NodeCool>(); // se actualizan las posiciones de cada nodo // equivalente a las posiciones que tendrian en la matriz logica (0, 1, 2, ..., rows x columns) for (int i = 0; i < G.V(); i++) { NodeCool aux = new NodeCool(); aux.SetPos(i); nodeGraph.Add(aux); } // establecemos el coste final del nodo origen (su coste fisico sera 0) nodeGraph[s_].SetFCost(nodeGraph[s_].GetGCost() + heuristic.chooseHeuristic(H, nodeGraph[s_], f_)); list.Add(nodeGraph[s_]); // introducimos el primer nodo en la lista // hasta que la lista no quede vacia de nodos vamos sacando el de menor coste final // y actualizamos los caminos y distancias en caso de ser necesario while (list.Count != 0) { int current = list.First().GetPos(); // si el nodo actual es el destino, devolvemos el camino y paramos if (current == f_) { path = nodeGraph[current].GetPathFromRoot(); depth = path.Count; break; } list.Remove(nodeGraph[current]); nodeGraph[current].SetClosed(true); // lo marcamos como visitado // para cada adyacente (vecino) de la posicion del nodo actual en el grafo foreach (DirectedEdge e in G.Adj(nodeGraph[current].GetPos())) { int neighbour = e.To(); // su vecino es el destino de la arista (el origen sera el nodo actual) // si el vecino no ha sido visitado ya if (!nodeGraph[neighbour].GetClosed()) { // coste fisico double gcost = nodeGraph[current].GetGCost() + e.Weight(); // si la lista no lo contiene ya, le actualizamos los costes, el padre y lo añadimos if (!list.Contains(nodeGraph[neighbour])) { nodeGraph[neighbour].SetParent(nodeGraph[current]); nodeGraph[neighbour].SetGCost(gcost); nodeGraph[neighbour].SetFCost(gcost + heuristic.chooseHeuristic(H, nodeGraph[neighbour], f_)); list.Add(nodeGraph[neighbour]); expandedNodes++; if (memSize < list.Count) { memSize = list.Count; } } // si no, le modificamos los costes y el padre else if (gcost < nodeGraph[neighbour].GetGCost()) { list.Remove(nodeGraph[neighbour]); nodeGraph[neighbour].SetParent(nodeGraph[current]); nodeGraph[neighbour].SetGCost(gcost); nodeGraph[neighbour].SetFCost(gcost + heuristic.chooseHeuristic(H, nodeGraph[neighbour], f_)); list.Add(nodeGraph[neighbour]); } list.Sort(); // ordenamos la lista de nodos segun su coste final (coste fisico + heuristica) } } } }