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> GetTriangleQuiver(int numRows, int firstVertex = DefaultFirstVertex) { if (!TriangleParameterIsValid(numRows)) { throw new ArgumentOutOfRangeException(nameof(numRows)); } if (numRows == 1) { var vertices = new int[] { firstVertex }; var arrows = new Arrow <int>[] { }; return(new Quiver <int>(vertices, arrows)); } // Sort of backwards to construct the entire QP only to return just the quiver // But this reduces duplicated logic var qp = UsefulQPs.GetTriangleQP(numRows, firstVertex); return(qp.Quiver); }