Exemplo n.º 1
0
        private static ImmutableArray <BoundDecisionDagNode> ShortestPathToNode(
            ImmutableArray <BoundDecisionDagNode> nodes,
            BoundDecisionDagNode node,
            bool nullPaths,
            out bool requiresFalseWhenClause)
        {
            // compute the distance from each node to the endpoint.
            var dist = PooledDictionary <BoundDecisionDagNode, (int distance, BoundDecisionDagNode next)> .GetInstance();

            int nodeCount = nodes.Length;
            int infinity  = 2 * nodeCount + 2;

            int distance(BoundDecisionDagNode x)
            {
                if (x == null)
                {
                    return(infinity);
                }
                if (dist.TryGetValue(x, out var v))
                {
                    return(v.distance);
                }
                Debug.Assert(!nodes.Contains(x));
                return(infinity);
            }

            for (int i = nodeCount - 1; i >= 0; i--)
            {
                var n = nodes[i];
                dist.Add(n, n switch
                {
                    BoundEvaluationDecisionDagNode e => (distance(e.Next), e.Next),
                    BoundTestDecisionDagNode {
                        Test: BoundDagNonNullTest _
                    } t when !nullPaths => (1 + distance(t.WhenTrue), t.WhenTrue),
                    BoundTestDecisionDagNode {
                        Test: BoundDagExplicitNullTest _
                    } t when !nullPaths => (1 + distance(t.WhenFalse), t.WhenFalse),
                    BoundTestDecisionDagNode t when distance(t.WhenTrue) is var trueDist1 && distance(t.WhenFalse) is var falseDist1 =>
                    (trueDist1 <= falseDist1) ? (1 + trueDist1, t.WhenTrue) : (1 + falseDist1, t.WhenFalse),
                    BoundWhenDecisionDagNode w when distance(w.WhenTrue) is var trueDist2 && distance(w.WhenFalse) is var falseDist2 =>
                    // add nodeCount to the distance if we need to flag that the path requires failure of a when clause
                    (trueDist2 <= falseDist2) ? (1 + trueDist2, w.WhenTrue) : (1 + (falseDist2 < nodeCount ? nodeCount : 0) + falseDist2, w.WhenFalse),
                    // treat the endpoint as distance 1.
                    // treat other nodes as not on the path to the endpoint
                    _ => ((n == node) ? 1 : infinity, null),
                });
Exemplo n.º 2
0
        /// <summary>
        /// Find the shortest path from the root node to the node of interest.
        /// </summary>
        /// <param name="nodes">The set of nodes in topological order.</param>
        /// <param name="node">The node of interest.</param>
        /// <param name="nullPaths">Whether to permit following paths that test for null.</param>
        /// <returns>The shortest path, excluding the node of interest.</returns>
        private static ImmutableArray <BoundDecisionDagNode> ShortestPathToNode(
            ImmutableArray <BoundDecisionDagNode> nodes,
            BoundDecisionDagNode node,
            bool nullPaths)
        {
            // compute the distance from each node to the endpoint.
            var dist = PooledDictionary <BoundDecisionDagNode, (int distance, BoundDecisionDagNode next)> .GetInstance();

            int nodeCount = nodes.Length;

            int distance(BoundDecisionDagNode x)
            {
                if (x == null)
                {
                    return(nodeCount + 2);
                }
                if (dist.TryGetValue(x, out var v))
                {
                    return(v.distance);
                }
                Debug.Assert(!nodes.Contains(x));
                return(nodeCount + 2);
            }

            for (int i = nodeCount - 1; i >= 0; i--)
            {
                var n = nodes[i];
                dist.Add(n, n switch
                {
                    BoundEvaluationDecisionDagNode e => (distance(e.Next), e.Next),
                    BoundTestDecisionDagNode {
                        Test: BoundDagNonNullTest _
                    } t when !nullPaths => (1 + distance(t.WhenTrue), t.WhenTrue),
                    BoundTestDecisionDagNode {
                        Test: BoundDagExplicitNullTest _
                    } t when !nullPaths => (1 + distance(t.WhenFalse), t.WhenFalse),
                    BoundTestDecisionDagNode t when distance(t.WhenTrue) is var trueDist && distance(t.WhenFalse) is var falseDist =>
                    (trueDist <= falseDist) ? (1 + trueDist, t.WhenTrue) : (1 + falseDist, t.WhenFalse),
                    BoundWhenDecisionDagNode w when distance(w.WhenTrue) is var trueDist && distance(w.WhenFalse) is var falseDist =>
                    (trueDist <= falseDist) ? (1 + trueDist, w.WhenTrue) : (1 + falseDist, w.WhenFalse),
                    // treat the endpoint as distance 1.
                    // treat other nodes as not on the path to the endpoint
                    _ => ((n == node) ? 1 : nodeCount + 2, null),
                });