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)); }
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); }
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); }
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); }
/// <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))); } }