public SelfInjectiveQP <int> GetSelfInjectiveTriangleQP(int numRows, int firstVertex = DefaultFirstVertex)
        {
            if (numRows < 2)
            {
                throw new ArgumentOutOfRangeException(nameof(numRows));
            }

            var qp        = UsefulQPs.GetTriangleQP(numRows);
            var potential = new Potential <int>();

            // Rotation "once" clockwise to get the Nakayama permutation
            var nakayamaPermutation = new Dictionary <int, int>();
            // Start with the right-most "column" (1, 3, 6, 10, ...), which is mapped to the bottom row,
            // and go left to (2, 5, 9, ...), which is mapped to the second last row, and so on.
            var columnVertices = Enumerable.Range(1, numRows).Select(k => Utility.TriangularNumber(k));

            for (int rowIndex = numRows; rowIndex >= 1; rowIndex--)
            {
                var rowVertices      = Enumerable.Range(Utility.TriangularNumber(rowIndex - 1) + 1, rowIndex).Reverse();
                var inputOutputPairs = columnVertices.Zip(rowVertices, (x, y) => (x, y));
                foreach (var(x, y) in inputOutputPairs)
                {
                    nakayamaPermutation[x] = y;
                }

                columnVertices = columnVertices.Select(x => x - 1).Skip(1);
            }

            return(new SelfInjectiveQP <int>(qp, nakayamaPermutation));
        }
예제 #2
0
        public static Quiver <int> GetGeneralizedCobwebQuiver(int numVerticesInCenterPolygon, int numLayers, int firstVertex = DefaultFirstVertex)
        {
            if (!GeneralizedCobwebParameterIsValid(numVerticesInCenterPolygon, numLayers))
            {
                throw new ArgumentOutOfRangeException(nameof(numVerticesInCenterPolygon));
            }

            // Sort of backwards to construct the entire QP only to return just the quiver,
            // but this reduces duplicated logic.
            var qp = UsefulQPs.GetGeneralizedCobwebQP(numVerticesInCenterPolygon, numLayers, firstVertex);

            return(qp.Quiver);
        }
예제 #3
0
        public static Quiver <int> GetPointedFlowerQuiver(int numPeriods, int firstVertex = DefaultFirstVertex)
        {
            if (!PointedFlowerParameterIsValid(numPeriods))
            {
                throw new ArgumentOutOfRangeException(nameof(numPeriods));
            }

            // Sort of backwards to construct the entire QP only to return just the quiver
            // But this reduces duplicated logic
            var qp = UsefulQPs.GetPointedFlowerQP(numPeriods, firstVertex);

            return(qp.Quiver);
        }
예제 #4
0
        public static Quiver <int> GetEvenFlowerType2Quiver(int numVerticesInCenterPolygon, int firstVertex = DefaultFirstVertex)
        {
            if (!EvenFlowerType2ParameterIsValid(numVerticesInCenterPolygon))
            {
                throw new ArgumentOutOfRangeException(nameof(numVerticesInCenterPolygon));
            }

            // Sort of backwards to construct the entire QP only to return just the quiver
            // But this reduces duplicated logic
            var qp = UsefulQPs.GetEvenFlowerType2QP(numVerticesInCenterPolygon, firstVertex);

            return(qp.Quiver);
        }
        public SelfInjectiveQP <int> GetSelfInjectiveCycleQP(int numVertices, int firstVertex = DefaultFirstVertex)
        {
            if (numVertices < 3)
            {
                throw new ArgumentOutOfRangeException(nameof(numVertices));
            }

            var qp = UsefulQPs.GetCycleQP(numVertices, firstVertex);

            int n    = numVertices;
            var dict = Enumerable.Range(firstVertex, n).ToDictionary(k => k, k => (k - 2 - firstVertex).Modulo(n) + firstVertex);
            var nakayamaPermutation = new NakayamaPermutation <int>(dict);
            var selfInjectiveQp     = new SelfInjectiveQP <int>(qp, nakayamaPermutation);

            return(selfInjectiveQp);
        }
예제 #6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="numRows">The number of rows of vertices.</param>
        /// <param name="firstVertex"></param>
        /// <returns></returns>
        public static Quiver <int> GetSquareQuiver(int numRows, int firstVertex = DefaultFirstVertex)
        {
            if (!SquareParameterIsValid(numRows))
            {
                throw new ArgumentOutOfRangeException(nameof(numRows));
            }

            if (numRows == 1)
            {
                return(new Quiver <int>(vertices: new int[] { firstVertex }, arrows: new Arrow <int> [0]));
            }

            // Sort of backwards to construct the entire QP only to return just the quiver
            // But this reduces duplicated logic
            var qp = UsefulQPs.GetSquareQP(numRows, firstVertex);

            return(qp.Quiver);
        }
        public SelfInjectiveQP <int> GetSelfInjectiveSquareQP(int numRows, int firstVertex = DefaultFirstVertex)
        {
            if (!SquareParameterIsValid(numRows))
            {
                throw new ArgumentOutOfRangeException(nameof(numRows));
            }

            var qp = UsefulQPs.GetSquareQP(numRows);

            int numVerticesInRow = numRows;
            int numVertices      = numRows * numVerticesInRow;

            // Rotation "twice" clockwise/counterclockwise to get the Nakayama permutation
            // This map happens to be just "x mapsto (n+1)-x" (labeling the vertices from 0 would be cleaner here I guess)
            var nakayamaPermutation = Enumerable.Range(1, numVertices).ToDictionary(x => x, x => numVertices + 1 - x);

            return(new SelfInjectiveQP <int>(qp, nakayamaPermutation));
        }
        /// <remarks>It is <em>assumed</em> that <em>all</em> odd flower QPs are self-injective.</remarks>
        public SelfInjectiveQP <int> GetSelfInjectiveOddFlowerQP(int numVerticesInCenterPolygon, int firstVertex = DefaultFirstVertex)
        {
            if (numVerticesInCenterPolygon < 3 || numVerticesInCenterPolygon.Modulo(2) == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(numVerticesInCenterPolygon));
            }

            var qp = UsefulQPs.GetOddFlowerQP(numVerticesInCenterPolygon);

            int numLayers = (numVerticesInCenterPolygon + 1) / 2;
            int numVerticesInFullInnerLayer = 2 * numVerticesInCenterPolygon;
            int numVerticesInOuterLayer     = 2 * numVerticesInFullInnerLayer;

            // Rotate clockwise by 2*pi / ((numVerticesInCenterPolygon-1)/2) for the Nakayama permutation?
            var nakayamaPermutation = new Dictionary <int, int>();

            for (int layerIndex = 0; layerIndex < numLayers; layerIndex++)
            {
                var layer = GetLayerVertices(layerIndex);
                for (int indexInLayer = 0; indexInLayer < layer.Count; indexInLayer++)
                {
                    int input           = layer[indexInLayer];
                    int stepsToRotateBy = (numVerticesInCenterPolygon - 1) / 2 * (layer.Count / numVerticesInCenterPolygon);
                    int output          = layer[indexInLayer + stepsToRotateBy];
                    nakayamaPermutation[input] = output;
                }
            }

            return(new SelfInjectiveQP <int>(qp, nakayamaPermutation));

            CircularList <int> GetLayerVertices(int layerIndex) // 0-based layer index
            {
                if (layerIndex == 0)
                {
                    return(new CircularList <int>(Enumerable.Range(1, numVerticesInCenterPolygon)));
                }
                int startVertex = layerIndex * numVerticesInFullInnerLayer - numVerticesInCenterPolygon + 1;
                int numVertices = layerIndex < numLayers - 1 ? numVerticesInFullInnerLayer : numVerticesInOuterLayer;

                return(new CircularList <int>(Enumerable.Range(startVertex, numVertices)));
            }
        }