예제 #1
0
        /// <summary>
        /// Analyzes a QP with the specified computer of maximal nonzero equivalence class
        /// representatives.
        /// </summary>
        /// <typeparam name="TVertex">The type of the vertices of the quiver.</typeparam>
        /// <param name="qp">The quiver with potential.</param>
        /// <param name="settings">The settings for the analysis.</param>
        /// <param name="computer">A computer of maximal nonzero equivalence class representatives.</param>
        /// <returns>The results of the analysis.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="qp"/> is
        /// <see langword="null"/>, or <paramref name="settings"/> is <see langword="null"/>,
        /// or <paramref name="computer"/> is <see langword="null"/>.</exception>
        /// <exception cref="NotSupportedException">The potential of <paramref name="qp"/> has a
        /// cycle with coefficient not equal to either of -1 and +1,
        /// or some arrow occurs multiple times in a single cycle of the potential of
        /// <paramref name="qp"/>.</exception>
        /// <exception cref="ArgumentException">For some arrow in the potential of
        /// <paramref name="qp"/> and sign, the arrow is contained in more than one cycle of that
        /// sign.</exception>
        public IQPAnalysisResults <TVertex> Analyze <TVertex>(
            QuiverWithPotential <TVertex> qp,
            QPAnalysisSettings settings,
            IMaximalNonzeroEquivalenceClassRepresentativeComputer computer)
            where TVertex : IEquatable <TVertex>, IComparable <TVertex>
        {
            if (qp is null)
            {
                throw new ArgumentNullException(nameof(qp));
            }
            if (settings is null)
            {
                throw new ArgumentNullException(nameof(settings));
            }
            if (computer is null)
            {
                throw new ArgumentNullException(nameof(computer));
            }

            // Simply get the underlying semimonomial unbound quiver and analyze it using the appropriate analyzer
            var semimonomialUnboundQuiver = SemimonomialUnboundQuiverFactory.CreateSemimonomialUnboundQuiverFromQP(qp);
            var suqAnalyzer = new SemimonomialUnboundQuiverAnalyzer();
            var suqSettings = AnalysisSettingsFactory.CreateSemimonomialUnboundQuiverAnalysisSettings(settings);
            var suqResults  = suqAnalyzer.Analyze(semimonomialUnboundQuiver, suqSettings, computer);
            var results     = AnalysisResultsFactory.CreateQPAnalysisResults(suqResults);

            return(results);
        }
예제 #2
0
        private ExploreChildNodesResult ExploreChildNodes <TVertex>(
            QuiverWithPotential <TVertex> qp,
            TransformationRuleTreeNode <TVertex> transformationRuleTree,
            AnalysisStateForSingleStartingVertexOld <TVertex> state,
            SearchTreeNodeOld <TVertex> parentNode,
            QPAnalysisSettings settings)
            where TVertex : IEquatable <TVertex>, IComparable <TVertex>
        {
            bool pathHasNonzeroExtension = false; // Path has no nonzero extension until proven otherwise

            // Explore every child node (determine its equivalence class)
            foreach (var nextVertex in qp.Quiver.AdjacencyLists[parentNode.Vertex])
            {
                var result = ExploreChildNode(transformationRuleTree, state, parentNode, nextVertex, settings);
                switch (result)
                {
                case ExploreChildNodeResult.NotZeroEquivalent:
                    pathHasNonzeroExtension = true;
                    break;

                case ExploreChildNodeResult.NonCancellativityDetected:
                    return(ExploreChildNodesResult.NonCancellativityDetected);

                case ExploreChildNodeResult.TooLongPath:
                    return(ExploreChildNodesResult.TooLongPath);
                }
            }

            return(pathHasNonzeroExtension ? ExploreChildNodesResult.PathHasNonzeroExtension : ExploreChildNodesResult.PathHasNoNonzeroExtension);
        }
예제 #3
0
        // After figuring out the use cases (high performance?) for these methods and figuring out
        // whether to change the interface, implement the counterparts of the methods in
        // SemimonomialUnboundQuiverAnalyzer and have the public methods of this class just be a
        // wrapper for said methods in SemimonomialUnboundQuiverAnalyzer (like the Analyze method
        // is right now).
        #region Code to refactor
        public AnalysisResultsForSingleStartingVertexOld <TVertex> AnalyzeWithStartingVertex <TVertex>(
            QuiverWithPotential <TVertex> qp,
            TVertex startingVertex,
            TransformationRuleTreeNode <TVertex> transformationRuleTree,
            QPAnalysisSettings settings)
            where TVertex : IEquatable <TVertex>, IComparable <TVertex>
        {
            // Parameter validation
            if (qp == null)
            {
                throw new ArgumentNullException(nameof(qp));
            }
            if (!qp.Quiver.Vertices.Contains(startingVertex))
            {
                throw new ArgumentException($"The QP does not contain the starting vertex {startingVertex}.");
            }

            // Set up for analysis/graph search
            var  state = new AnalysisStateForSingleStartingVertexOld <TVertex>(startingVertex);
            bool cancellativityFailed   = false;
            bool tooLongPathEncountered = false;

            // Analysis/graph search
            // Keep a stack of "recently explored" nodes
            // In every iteration, pop a recently explored node from the stack and explore (determine
            // the equivalence classes of) its child nodes.
            // It would be cleaner to in every iteration explore the current node (determine its equivalence class)
            // and discover its child nodes (push new equivalence class representatives (which may overlap?) onto
            // the stack for future iterations, but this makes it non-trivial to keep track of the maximal nonzero
            // equivalence classes
            while (state.Stack.Count > 0)
            {
                var node   = state.Stack.Pop();
                var result = ExploreChildNodes(qp, transformationRuleTree, state, node, settings);
                if (result == ExploreChildNodesResult.PathHasNoNonzeroExtension)
                {
                    state.maximalPathRepresentatives.Add(node);
                }
                else if (result == ExploreChildNodesResult.NonCancellativityDetected)
                {
                    cancellativityFailed = true;
                    break;
                }
                else if (result == ExploreChildNodesResult.TooLongPath)
                {
                    tooLongPathEncountered = true;
                    break;
                }
            }

            // Return results
            var results = new AnalysisResultsForSingleStartingVertexOld <TVertex>(state, cancellativityFailed, tooLongPathEncountered);

            return(results);
        }
예제 #4
0
 /// <summary>
 /// Analyzes a QP in a way that utilizes the &quot;periodicity&quot; of the QP and
 /// concurrently.
 /// </summary>
 /// <typeparam name="TVertex">The type of the vertices of the quiver.</typeparam>
 /// <param name="qp">The quiver with potential.</param>
 /// <param name="periods">A collection of consecutive non-empty periods of the QP that are
 /// jointly exhaustive and mutually exclusive.</param>
 /// <param name="settings">The settings for the analysis.</param>
 /// <returns>The results of the analysis.</returns>
 /// <exception cref="ArgumentNullException"><paramref name="qp"/> is
 /// <see langword="null"/>,
 /// or <paramref name="periods"/> is <see langword="null"/>,
 /// or <paramref name="settings"/> is <see langword="null"/>.</exception>
 /// <exception cref="NotSupportedException">The potential of <paramref name="qp"/> has a
 /// cycle with coefficient not equal to either of -1 and +1,
 /// or some arrow occurs multiple times in a single cycle of the potential of
 /// <paramref name="qp"/>.</exception>
 /// <exception cref="ArgumentException">For some arrow in the potential of
 /// <paramref name="qp"/> and sign, the arrow is contained in more than one cycle of that
 /// sign, or some of the periods in <paramref name="periods"/> overlap, or the union of all
 /// periods in <paramref name="periods"/> is not precisely the collection of all vertices
 /// in the quiver.</exception>
 /// <remarks>
 /// <para>Some validation of <paramref name="periods"/> is done, but
 /// <paramref name="periods"/> is not verified to constitute a sequence of consecutive
 /// &quot;periods&quot; of the QP.</para>
 /// </remarks>
 public IQPAnalysisResults <TVertex> AnalyzeUtilizingPeriodicityConcurrently <TVertex>(
     QuiverWithPotential <TVertex> qp,
     IEnumerable <IEnumerable <TVertex> > periods,
     QPAnalysisSettings settings)
     where TVertex : IEquatable <TVertex>, IComparable <TVertex>
 {
     return(AnalyzeUtilizingPeriodicityConcurrently(
                qp,
                periods,
                settings,
                defaultComputer));
 }
예제 #5
0
        public MaximalNonzeroEquivalenceClassRepresentativesResults <TVertex> ComputeMaximalNonzeroEquivalenceClassRepresentativesStartingAt <TVertex>(
            QuiverWithPotential <TVertex> qp,
            TVertex startingVertex,
            TransformationRuleTreeNode <TVertex> transformationRuleTree,
            QPAnalysisSettings settings)
            where TVertex : IEquatable <TVertex>, IComparable <TVertex>
        {
            var bogusPath       = new Path <TVertex>(qp.Quiver.Vertices.First());
            var analysisResults = AnalyzeWithStartingVertex(qp, startingVertex, transformationRuleTree, settings);
            var outputResults   = new MaximalNonzeroEquivalenceClassRepresentativesResults <TVertex>(
                analysisResults.NonCancellativityDetected ? CancellativityTypes.Cancellativity : CancellativityTypes.None,
                analysisResults.TooLongPathEncountered,
                analysisResults.MaximalPathRepresentatives.Select(node => node.Path),
                longestPathEncountered: bogusPath); // bogus path because this is an old method and the longest path feature is new

            return(outputResults);
        }
예제 #6
0
 /// <summary>
 /// Analyzes a QP with the default computer of maximal nonzero equivalence class
 /// representatives.
 /// </summary>
 /// <typeparam name="TVertex">The type of the vertices of the quiver.</typeparam>
 /// <param name="qp">The quiver with potential.</param>
 /// <param name="settings">The settings for the analysis.</param>
 /// <returns>The results of the analysis.</returns>
 /// <exception cref="ArgumentNullException"><paramref name="qp"/> is
 /// <see langword="null"/>, or <paramref name="settings"/> is
 /// <see langword="null"/>.</exception>
 /// <exception cref="NotSupportedException">The potential of <paramref name="qp"/> has a
 /// cycle with coefficient not equal to either of -1 and +1,
 /// or some arrow occurs multiple times in a single cycle of the potential of
 /// <paramref name="qp"/>.</exception>
 /// <exception cref="ArgumentException">For some arrow in the potential of
 /// <paramref name="qp"/> and sign, the arrow is contained in more than one cycle of that
 /// sign.</exception>
 public IQPAnalysisResults <TVertex> Analyze <TVertex>(QuiverWithPotential <TVertex> qp, QPAnalysisSettings settings)
     where TVertex : IEquatable <TVertex>, IComparable <TVertex>
 {
     return(Analyze(qp, settings, defaultComputer));
 }
예제 #7
0
        /// <returns>A boolean value indicating whether the path correspondings to the explored
        /// child node is nonzero (up to equivalence).</returns>
        private ExploreChildNodeResult ExploreChildNode <TVertex>(
            TransformationRuleTreeNode <TVertex> transformationRuleTree,
            AnalysisStateForSingleStartingVertexOld <TVertex> state,
            SearchTreeNodeOld <TVertex> parentNode,
            TVertex nextVertex,
            QPAnalysisSettings settings)
            where TVertex : IEquatable <TVertex>, IComparable <TVertex>
        {
            // Either the child node has not already been discovered, or the child node was
            // discovered during an equivalence class search.

            if (parentNode.Children.TryGetValue(nextVertex, out var childNode))
            {
                // The child node has already been discovered.
                // Do a non-cancellativity check (if we are to detect non-cancellativity):
                //     If the child node is zero, everything is fine.
                //     If a different arrow was added to the origin than to the parent to get child node (i.e., origin and parent have different last vertices), things are fine.
                //     Else, make sure that the origin is equivalent to the parent
                // (otherwise, the QP is not cancellative).
                if (
                    settings.DetectCancellativityFailure &&
                    !state.NodeIsZeroEquivalent(childNode) &&
                    parentNode.Vertex.Equals(childNode.Origin.Vertex) &&
                    state.EquivalenceClasses.FindSet(parentNode) != state.EquivalenceClasses.FindSet(childNode.Origin))
                {
                    return(ExploreChildNodeResult.NonCancellativityDetected);
                }
            }
            else
            {
                // The child node has not been discovered, so let's discover it by inserting it
                // into the search tree.
                childNode = state.InsertChildNode(parentNode, nextVertex, parentNode);
            }

            if (childNode.Explored)
            {
                return(state.NodeIsZeroEquivalent(childNode) ? ExploreChildNodeResult.ZeroEquivalent : ExploreChildNodeResult.NotZeroEquivalent);
            }

            // Code for equivalence class searching begins here
            // Stack containing all the nodes to explore (by path transformation)
            var equivClassStack = new Stack <SearchTreeNodeOld <TVertex> >(state.EquivalenceClasses.GetSet(childNode));

            // This could happen with the current code, namely when the current childNode was encountered
            // in a previous call to ExploreChildNodes (in EquivClassExploreNode, as transformationNode)
            // and 'node' was found to be zero equivalent (in which case the search is cancelled
            // before transformationNode is explored in EquivClassExploreNode)
            // Thought: Would probably be good to have several Explored properties (or an
            // enum-valued Explored property) containing information about the extent to which the
            // node is explored (explored-as-in-encountered-in-EquivClassExploreNode would be
            // useful here; more easily understood and maintained than this comment methinks)
            if (equivClassStack.Count != 1)
            {
                return(ExploreChildNodeResult.ZeroEquivalent);
            }

            while (equivClassStack.Count > 0)
            {
                var equivalentNode = equivClassStack.Pop();
                if (equivalentNode.Explored)
                {
                    continue;
                }
                if (settings.UseMaxLength && equivalentNode.PathLengthInVertices > settings.MaxPathLength + 1)
                {
                    return(ExploreChildNodeResult.TooLongPath);
                }
                var exploredNodeWasFoundZeroEquivalent = EquivClassExploreNode(transformationRuleTree, equivalentNode, state, equivClassStack, parentNode);
                if (exploredNodeWasFoundZeroEquivalent)
                {
                    return(ExploreChildNodeResult.ZeroEquivalent);
                }
            }

            // Child node was not zero-equivalent
            state.Stack.Push(childNode);
            return(ExploreChildNodeResult.NotZeroEquivalent);
        }
예제 #8
0
        public static SemimonomialUnboundQuiverAnalysisSettings CreateSemimonomialUnboundQuiverAnalysisSettings(QPAnalysisSettings settings)
        {
            if (settings is null)
            {
                throw new ArgumentNullException(nameof(settings));
            }

            return(new SemimonomialUnboundQuiverAnalysisSettings(
                       settings.CancellativityFailureDetection,
                       settings.MaxPathLength,
                       settings.EarlyTerminationConditions));
        }