public static bool Evaluate <T>(Context <T> ctx) { if (ctx.procTermination.Invoke(ctx.start)) { ctx.path = new List <T>(); return(true); } var opened = new MinHeap <T>(); var map = new Dictionary <int, Node <T> >(); var closed = new HashSet <int>(); var startNode = new Node <T>(ctx.start, 0, 0); foreach (var adj in ctx.procAdjacencies.Invoke(ctx.start)) { var node = new Node <T>(adj, ctx.procWeight.Invoke(ctx.start, adj), ctx.procDistanceEstimator(adj)); node.backwardRef = startNode; map.Add(ctx.procTrait.Invoke(node.substance), node); opened.AddNode(node); } closed.Add(ctx.procTrait.Invoke(ctx.start)); List <Node <T> > matches = new List <Node <T> >(); while (opened.Length > 0) { matches.Clear(); var cur = opened.ExtractMin(); if (ctx.procTermination.Invoke(cur.substance)) { ctx.path = new List <T>(); var step = cur; while (null != step) { ctx.path.Add(step.substance); step = step.backwardRef; } return(true); } var adjs = ctx.procAdjacencies.Invoke(cur.substance); closed.Add(ctx.procTrait.Invoke(cur.substance)); map.Remove(ctx.procTrait.Invoke(cur.substance)); foreach (var adj in adjs) { if (closed.Contains(ctx.procTrait.Invoke(adj))) { continue; } var estimation = ctx.procDistanceEstimator.Invoke(adj); var dstIncrease = ctx.procWeight.Invoke(cur.substance, adj); if (map.ContainsKey(ctx.procTrait.Invoke(adj))) { var exist = map[ctx.procTrait.Invoke(adj)]; if (cur.dstStart + dstIncrease + estimation < exist.dstStart + exist.dstEndEstimated) { exist.dstStart = cur.dstStart + dstIncrease; exist.backwardRef = cur; opened.HeapifyAll(); } } else { var node = new Node <T>(adj, cur.dstStart + dstIncrease, ctx.procDistanceEstimator(adj)); node.backwardRef = cur; map.Add(ctx.procTrait.Invoke(adj), node); opened.AddNode(node); } } } return(false); }