Exemplo n.º 1
0
    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);
    }