/// <summary>
        /// Computes the equivalence class of the specified node.
        /// </summary>
        /// <typeparam name="TVertex">The type of the vertices in the quiver.</typeparam>
        /// <param name="node">The node whose equivalence class to determine.</param>
        /// <param name="state">The state of the computation.</param>
        /// <param name="transformationRuleTree">The transformation rule tree.</param>
        /// <param name="settings">The computation settings.</param>
        /// <returns><see cref="EquivalenceClassResult.TooLongPath"/> if
        /// <paramref name="settings"/> has <see cref="AnalysisSettings.UseMaxLength"/> equal to
        /// <see langword="true"/> and a path of length (in arrows) strictly greater than
        /// <see cref="AnalysisSettings.MaxPathLength"/> of <paramref name="settings"/> is
        /// encountered during the equivalence class search. Otherwise,
        /// <see cref="EquivalenceClassResult.Zero"/> if the equivalence class is the zero
        /// class, and <see cref="EquivalenceClassResult.Nonzero"/> if the equivalence class is not
        /// the zero class.</returns>
        /// <remarks>
        /// <para>This method may modify the
        /// <see cref="AnalysisStateForSingleStartingVertex{TVertex}.SearchTree"/>,
        /// <see cref="AnalysisStateForSingleStartingVertex{TVertex}.EquivalenceClasses"/>, and
        /// <see cref="AnalysisStateForSingleStartingVertex{TVertex}.LongestPathEncounteredNode"/>
        /// properties of the <paramref name="state"/> argument.</para>
        /// </remarks>
        private EquivalenceClassResult ComputeEquivalenceClass <TVertex>(
            SearchTreeNode <TVertex> startNode,
            AnalysisStateForSingleStartingVertex <TVertex> state,
            TransformationRuleTreeNode <TVertex> transformationRuleTree,
            MaximalNonzeroEquivalenceClassRepresentativeComputationSettings settings)
            where TVertex : IEquatable <TVertex>, IComparable <TVertex>
        {
            // The stack or queue of nodes to process
            var equivClassStack = new Stack <SearchTreeNode <TVertex> >();

            equivClassStack.Push(startNode);
            startNode.HasBeenDiscoveredDuringEquivalenceClassComputation = true;

            while (equivClassStack.Count > 0)
            {
                var node   = equivClassStack.Pop();
                var result = ExploreNodeForEquivalenceClassSearch(node, equivClassStack, state, transformationRuleTree, settings);
                if (result == EquivalenceClassResult.TooLongPath)
                {
                    return(EquivalenceClassResult.TooLongPath);                                              // If too long, return "too long".
                }
                else if (result == EquivalenceClassResult.Zero)
                {
                    return(EquivalenceClassResult.Zero);                                            // If definitely zero-equivalent, return "zero"
                }
            }

            return(EquivalenceClassResult.Nonzero);
        }
        /// <summary>
        /// Determines the equivalence class of the specified node.
        /// </summary>
        /// <typeparam name="TVertex">The type of the vertices in the quiver.</typeparam>
        /// <param name="node">The node whose equivalence class to determine.</param>
        /// <param name="state">The state of the computation.</param>
        /// <param name="transformationRuleTree">The transformation rule tree.</param>
        /// <param name="settings">The computation settings.</param>
        /// <returns><see cref="EquivalenceClassResult.TooLongPath"/> if the equivalence class has
        /// not been computed before, <paramref name="settings"/> has
        /// <see cref="AnalysisSettings.UseMaxLength"/> equal to <see langword="true"/>, and a path
        /// of length (in arrows) strictly greater than
        /// <see cref="AnalysisSettings.MaxPathLength"/> of <paramref name="settings"/> is
        /// encountered during the equivalence class search. Otherwise,
        /// <see cref="EquivalenceClassResult.Zero"/> if the equivalence class is the zero
        /// class, and <see cref="EquivalenceClassResult.Nonzero"/> if the equivalence class is
        /// not the zero class.</returns>
        /// <remarks>
        /// <para>This method may modify the
        /// <see cref="AnalysisStateForSingleStartingVertex{TVertex}.SearchTree"/>,
        /// <see cref="AnalysisStateForSingleStartingVertex{TVertex}.EquivalenceClasses"/>, and
        /// <see cref="AnalysisStateForSingleStartingVertex{TVertex}.LongestPathEncounteredNode"/>
        /// properties of the <paramref name="state"/> argument.</para>
        /// </remarks>
        private EquivalenceClassResult DetermineEquivalenceClass <TVertex>(
            SearchTreeNode <TVertex> node,
            AnalysisStateForSingleStartingVertex <TVertex> state,
            TransformationRuleTreeNode <TVertex> transformationRuleTree,
            MaximalNonzeroEquivalenceClassRepresentativeComputationSettings settings)
            where TVertex : IEquatable <TVertex>, IComparable <TVertex>
        {
            if (node.EquivalenceClassIsComputed)
            {
                return(state.NodeIsZeroEquivalent(node) ? EquivalenceClassResult.Zero : EquivalenceClassResult.Nonzero);
            }

            return(ComputeEquivalenceClass(node, state, transformationRuleTree, settings));
        }
        /// <summary>
        /// Checks if the path is too long given the specified computation settings and also updates
        /// the <see cref="AnalysisStateForSingleStartingVertex{TVertex}.LongestPathEncounteredNode"/>
        /// property if necessary.
        /// </summary>
        /// <typeparam name="TVertex">The type of the vertices in the quiver.</typeparam>
        /// <param name="node">The node whose corresponding path to check.</param>
        /// <param name="state">The state of the computation.</param>
        /// <param name="settings">The computation settings, which indicates whether to detect too
        /// long paths.</param>
        /// <returns>A value of the <see cref="PathLengthCheckResult"/> enum indicating whether the
        /// path was too long.</returns>
        private PathLengthCheckResult DoPathLengthCheck <TVertex>(
            SearchTreeNode <TVertex> node,
            AnalysisStateForSingleStartingVertex <TVertex> state,
            MaximalNonzeroEquivalenceClassRepresentativeComputationSettings settings)
            where TVertex : IEquatable <TVertex>, IComparable <TVertex>
        {
            if (node.PathLength <= state.LongestPathEncounteredNode.Length)
            {
                return(PathLengthCheckResult.Fine);
            }

            // node.Path is slow, but this will be executed at most
            // min(maxPathLength, largestPathLengthInQuiver) times or so
            state.LongestPathEncounteredNode = node.Path;

            return((settings.UseMaxLength && node.PathLength > settings.MaxPathLength) ? PathLengthCheckResult.TooLongPath : PathLengthCheckResult.Fine);
        }
Exemplo n.º 4
0
 internal AnalysisResultsForSingleStartingVertex(
     SearchTreeNode <TVertex> zeroDummyNode,
     SearchTreeNode <TVertex> searchTree,
     IEnumerable <SearchTreeNode <TVertex> > maximalPathRepresentatives,
     DisjointSets <SearchTreeNode <TVertex> > equivalenceClasses,
     CancellativityTypes cancellativityFailuresDetected,
     bool tooLongPathEncountered,
     Path <TVertex> longestPathEncountered)
 {
     ZeroDummyNode = zeroDummyNode;
     SearchTree    = searchTree;
     MaximalPathRepresentatives     = maximalPathRepresentatives;
     EquivalenceClasses             = equivalenceClasses;
     CancellativityFailuresDetected = cancellativityFailuresDetected;
     TooLongPathEncountered         = tooLongPathEncountered;
     LongestPathEncountered         = longestPathEncountered;
 }
        /// <summary>
        /// Explores the specified node in the equivalence class search.
        /// </summary>
        /// <typeparam name="TVertex">The type of the vertices in the quiver.</typeparam>
        /// <param name="node">The node to explore.</param>
        /// <param name="equivClassStack">The stack or queue of nodes to explore.</param>
        /// <param name="state">The state of the computation.</param>
        /// <param name="transformationRuleTree">The transformation rule tree.</param>
        /// <param name="settings">The computation settings.</param>
        /// <returns>A value of the <see cref="EquivalenceClassResult"/> enum indicating whether
        /// the node was <em>found</em> to be zero-equivalent. That is, the returned value is
        /// <see cref="EquivalenceClassResult.Zero"/> <em>only</em> if the node is zero-equivalent
        /// but may be <see cref="EquivalenceClassResult.Nonzero"/> even if the node is
        /// zero-equivalent.
        /// <remarks>
        /// <para>A node is found to be zero-equivalent either if its path can be killed or if
        /// the path is equivalent (up to replacement) to a path that has previously been
        /// determined to be zero-equivalent.</para>
        /// <para>This method may modify the
        /// <see cref="AnalysisStateForSingleStartingVertex{TVertex}.SearchTree"/>,
        /// <see cref="AnalysisStateForSingleStartingVertex{TVertex}.EquivalenceClasses"/>, and
        /// <see cref="AnalysisStateForSingleStartingVertex{TVertex}.LongestPathEncounteredNode"/>
        /// properties of the <paramref name="state"/> argument.</para>
        /// </remarks>
        private EquivalenceClassResult ExploreNodeForEquivalenceClassSearch <TVertex>(
            SearchTreeNode <TVertex> node,
            Stack <SearchTreeNode <TVertex> > equivClassStack,
            AnalysisStateForSingleStartingVertex <TVertex> state,
            TransformationRuleTreeNode <TVertex> transformationRuleTree,
            MaximalNonzeroEquivalenceClassRepresentativeComputationSettings settings)
            where TVertex : IEquatable <TVertex>, IComparable <TVertex>
        {
            // A list of the vertices that appear after the path being considered from transformation.
            // The vertices are in reversed order.
            var trailingVertexPath = new List <TVertex>();

            foreach (var endingNode in node.ReversePathOfNodes) // The vertex (i.e., last vertex) of endingNode is the last vertex in the subpath
            {
                var transformationNode = transformationRuleTree;
                foreach (var startingNode in endingNode.ReversePathOfNodes) // The vertex (i.e., last vertex) of startingNode is the first vertex in the subpath
                {
                    var pathVertex = startingNode.Vertex;
                    if (!transformationNode.Children.TryGetValue(pathVertex, out transformationNode))
                    {
                        break;
                    }

                    if (transformationNode.CanBeKilled)
                    {
                        state.EquivalenceClasses.Union(node, state.ZeroDummyNode);
                        return(EquivalenceClassResult.Zero);
                    }

                    // If replacement is possible, do the replacement on the subpath
                    // and add a search tree node for the entire resulting path
                    if (transformationNode.CanBeReplaced)
                    {
                        // Add search tree nodes for replacement path

                        // This doesn't work when pathNode is the root ...
                        // var lastUnreplacedNode = pathNode.Parent;
                        // var curNode = lastUnreplacedNode;

                        // ... so instead do the following (with Skip), which assumes that the replacement
                        // path has the same first vertex (which it does for the semimonomial unbound
                        // quivers under consideration)
                        var firstNodeInTransformedPath = startingNode;
                        var curNode = firstNodeInTransformedPath;

                        foreach (var vertex in transformationNode.ReplacementPath.Vertices.Skip(1))
                        {
                            curNode = state.GetInsertChildNode(curNode, vertex);
                        }

                        // Add search tree nodes for the trailing path
                        foreach (var vertex in trailingVertexPath.Reversed())
                        {
                            curNode = state.GetInsertChildNode(curNode, vertex);
                        }

                        // We now have the node obtained by applying the replacement rule.
                        var transformedNode = curNode;

                        // Do stuff with its path length.
                        bool tooLong = DoPathLengthCheck(transformedNode, state, settings) == PathLengthCheckResult.TooLongPath;
                        if (tooLong)
                        {
                            return(EquivalenceClassResult.TooLongPath);
                        }

                        if (state.NodeIsZeroEquivalent(transformedNode))
                        {
                            state.EquivalenceClasses.Union(node, transformedNode); // Unioning with state.ZeroDummyNode would work equally well
                            return(EquivalenceClassResult.Zero);
                        }

                        // If transformedNode.HasBeenDiscoveredDuringEquivalenceClassComputation
                        // at this point, then it was discovered during this equivalence class
                        // search (not during an earlier search that ended with zero equivalence),
                        // and in this case, we should ignore it!

                        if (!transformedNode.HasBeenDiscoveredDuringEquivalenceClassComputation)
                        {
                            transformedNode.HasBeenDiscoveredDuringEquivalenceClassComputation = true;
                            state.EquivalenceClasses.Union(node, transformedNode);
                            equivClassStack.Push(transformedNode);
                        }
                    }
                }

                trailingVertexPath.Add(endingNode.Vertex);
            }

            return(EquivalenceClassResult.Nonzero);
        }