Path: blob/master/src/sage/combinat/gelfand_tsetlin_patterns.py
8817 views
r"""1Gelfand-Tsetlin Patterns23AUTHORS:45- Travis Scrimshaw (2013-15-03): Initial version67REFERENCES:89.. [BBF] B. Brubaker, D. Bump, and S. Friedberg.10Weyl Group Multiple Dirichlet Series: Type A Combinatorial Theory.11Ann. of Math. Stud., vol. 175, Princeton Univ. Press, New Jersey, 2011.1213.. [GC50] I. M. Gelfand and M. L. Cetlin.14Finite-Dimensional Representations of the Group of Unimodular Matrices.15Dokl. Akad. Nauk SSSR **71**, pp. 825--828, 1950.1617.. [Tok88] T. Tokuyama.18A Generating Function of Strict Gelfand Patterns and Some Formulas on19Characters of General Linear Groups.20J. Math. Soc. Japan **40** (4), pp. 671--685, 1988.21"""22#*****************************************************************************23# Copyright (C) 2013 Travis Scrimshaw <[email protected]>24#25# Distributed under the terms of the GNU General Public License (GPL)26#27# This code is distributed in the hope that it will be useful,28# but WITHOUT ANY WARRANTY; without even the implied warranty of29# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU30# General Public License for more details.31#32# The full text of the GPL is available at:33#34# http://www.gnu.org/licenses/35#*****************************************************************************3637from sage.structure.parent import Parent38from sage.structure.list_clone import ClonableArray39from sage.structure.unique_representation import UniqueRepresentation40from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets41from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets42from sage.misc.classcall_metaclass import ClasscallMetaclass43from sage.misc.cachefunc import cached_method44from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing45from sage.rings.all import ZZ46from sage.combinat.partition import Partitions47from sage.combinat.tableau import Tableau, SemistandardTableaux48from sage.combinat.combinatorial_map import combinatorial_map49from sage.misc.misc import prod5051class GelfandTsetlinPattern(ClonableArray):52r"""53A Gelfand-Tsetlin (sometimes written as Gelfand-Zetlin or Gelfand-Cetlin)54pattern. They were originally defined in [GC50]_.5556A Gelfand-Tsetlin pattern is a triangular array:5758.. MATH::5960\begin{array}{ccccccccc}61a_{1,1} & & a_{1,2} & & a_{1,3} & & \cdots & & a_{1,n} \\62& a_{2,2} & & a_{2,3} & & \cdots & & a_{2,n} \\63& & a_{3,3} & & \cdots & & a_{3,n} \\64& & & \ddots \\65& & & & a_{n,n}66\end{array}6768such that `a_{i,j} \geq a_{i+1,j+1} \geq a_{i,j+1}`.6970Gelfand-Tsetlin patterns are in bijection with semistandard Young tableaux71by the following algorithm. Let `G` be a Gelfand-Tsetlin pattern with72`\lambda^{(k)}` being the `(n-k+1)`-st row (note that this is a partition).73The definition of `G` implies7475.. MATH::7677\lambda^{(0)} \subseteq \lambda^{(1)} \subseteq \cdots \subseteq78\lambda^{(n)},7980where `\lambda^{(0)}` is the empty partition, and each skew shape81`\lambda^{(k)}/\lambda^{(k-1)}` is a horizontal strip. Thus define `T(G)`82by inserting `k` into the squares of the skew shape83`\lambda^{(k)}/ \lambda^{(k-1)}`, for `k=1,\dots,n`.8485To each entry in a Gelfand-Tsetlin pattern, one may attach a decoration of86a circle or a box (or both or neither). These decorations appear in the87study of Weyl group multiple Dirichlet series, and are implemented here88following the exposition in [BBF]_.8990.. NOTE::9192We use the "right-hand" rule for determining circled and boxed entries.9394.. WARNING::9596The entries in Sage are 0-based and are thought of as flushed to the97left in a matrix. In other words, the coordinates of entries in the98Gelfand-Tsetlin patterns are thought of as the matrix:99100.. MATH::101102\begin{bmatrix}103g_{0,0} & g_{0,1} & g_{0,2} & \cdots & g_{0,n-2} & g_{n-1,n-1} \\104g_{1,0} & g_{1,1} & g_{1,2} & \cdots & g_{1,n-2} \\105g_{2,0} & g_{2,1} & g_{2,2} & \cdots \\106\vdots & \vdots & \vdots \\107g_{n-2,0} & g_{n-2,1} \\108g_{n-1,0}109\end{bmatrix}.110111However, in the discussions, we will be using the **standard**112numbering system.113114EXAMPLES::115116sage: G = GelfandTsetlinPattern([[3, 2, 1], [2, 1], [1]]); G117[[3, 2, 1], [2, 1], [1]]118sage: G.pp()1193 2 11202 11211122sage: G = GelfandTsetlinPattern([[7, 7, 4, 0], [7, 7, 3], [7, 5], [5]]); G.pp()1237 7 4 01247 7 31257 51265127sage: G.to_tableau().pp()1281 1 1 1 1 2 21292 2 2 2 2 3 31303 3 3 4131"""132# Note that the width == height, so len(gt) == len(gt[0]) except133# we don't have to check if it is the emtry GT pattern134__metaclass__ = ClasscallMetaclass135136@staticmethod137def __classcall_private__(self, gt):138"""139Return ``gt`` as a proper element of :class:`GelfandTsetlinPatterns`.140141EXAMPLES::142143sage: G = GelfandTsetlinPattern([[3,2,1],[2,1],[1]])144sage: G.parent()145Gelfand-Tsetlin patterns146sage: TestSuite(G).run()147"""148return GelfandTsetlinPatterns()(gt)149150def check(self):151"""152Check that this is a valid Gelfand-Tsetlin pattern.153154EXAMPLES::155156sage: G = GelfandTsetlinPatterns()157sage: G([[3,2,1],[2,1],[1]]).check()158"""159assert all( self[i-1][j] >= self[i][j] >= self[i-1][j+1]160for i in range(1, len(self)) for j in range(len(self[i])) )161162def _hash_(self):163"""164Return the hash value of ``self``.165166EXAMPLES::167168sage: G = GelfandTsetlinPatterns()169sage: gt = G([[3,2,1],[2,1],[1]])170sage: hash(gt) == hash(gt)171True172173Check that :trac:`14717` is fixed::174175sage: GT = GelfandTsetlinPattern([[2, 1, 0], [2, 0], [1]])176sage: GT in {}177False178"""179return hash(tuple(map(tuple, self)))180181def _repr_diagram(self):182"""183Return a string representation of ``self`` as a diagram.184185EXAMPLES::186187sage: G = GelfandTsetlinPatterns()188sage: print G([[3,2,1],[2,1],[1]])._repr_diagram()1893 2 11902 11911192"""193ret = ''194for i, row in enumerate(self):195if i != 0:196ret += '\n'197ret += ' '*i198ret += ' '.join('%3s'%val for val in row)199return ret200201def pp(self):202"""203Pretty print ``self``.204205EXAMPLES::206207sage: G = GelfandTsetlinPatterns()208sage: G([[3,2,1],[2,1],[1]]).pp()2093 2 12102 12111212"""213print self._repr_diagram()214215def _latex_(self):216r"""217Return a `\LaTeX` representation of ``self``.218219EXAMPLES::220221sage: G = GelfandTsetlinPatterns()222sage: latex(G([[3,2,1],[2,1],[1]]))223\begin{array}{ccccc}2243 & & 2 & & 1 \\225& 2 & & 1 & \\226& & 1 & &227\end{array}228sage: latex(G([]))229\emptyset230"""231n = len(self)232if n == 0:233return "\\emptyset"234ret = "\\begin{array}{" + 'c'*(n*2-1) + "}\n"235for i, row in enumerate(self):236if i > 0:237ret += " \\\\\n"238ret += "& "*i239ret += " & & ".join(repr(val) for val in row)240ret += " &"*i241return ret + "\n\\end{array}"242243@combinatorial_map(name='to semistandard tableau')244def to_tableau(self):245"""246Return ``self`` as a semistandard Young tableau.247248The conversion from a Gelfand-Tsetlin pattern to a semistandard Young249tableaux is as follows. Let `G` be a Gelfand-Tsetlin pattern with250`\lambda^{(k)}` being the `(n-k+1)`-st row (note that this is a251partition). The definition of `G` implies252253.. MATH::254255\lambda^{(0)} \subseteq \lambda^{(1)} \subseteq \cdots \subseteq256\lambda^{(n)},257258where `\lambda^{(0)}` is the empty partition, and each skew shape259`\lambda^{(k)} / \lambda^{(k-1)}` is a horizontal strip. Thus define260`T(G)` by inserting `k` into the squares of the skew shape261`\lambda^{(k)} / \lambda^{(k-1)}`, for `k=1,\dots,n`.262263EXAMPLES::264265sage: G = GelfandTsetlinPatterns()266sage: elt = G([[3,2,1],[2,1],[1]])267sage: T = elt.to_tableau(); T268[[1, 2, 3], [2, 3], [3]]269sage: T.pp()2701 2 32712 32723273sage: G(T) == elt274True275"""276ret = []277for i, row in enumerate(reversed(self)):278for j, val in enumerate(row):279if j >= len(ret):280if val == 0:281break282ret.append([i+1]*val)283else:284ret[j].extend([i+1]*(val-len(ret[j])))285S = SemistandardTableaux()286return S(ret)287288@cached_method289def boxed_entries(self):290"""291Return the position of the boxed entries of ``self``.292293Using the *right-hand* rule, an entry `a_{i,j}` is boxed if294`a_{i,j} = a_{i-1,j-1}`; i.e., `a_{i,j}` has the same value as its295neighbor to the northwest.296297EXAMPLES::298299sage: G = GelfandTsetlinPattern([[3,2,1],[3,1],[1]])300sage: G.boxed_entries()301((1, 0),)302"""303ret = []304for i in range(1, len(self)):305for j in range(len(self[i])):306if self[i][j] == self[i-1][j]:307ret.append((i, j))308return tuple(ret)309310@cached_method311def circled_entries(self):312"""313Return the circled entries of ``self``.314315Using the *right-hand* rule, an entry `a_{i,j}` is circled if316`a_{i,j} = a_{i-1,j}`; i.e., `a_{i,j}` has the same value as its317neighbor to the northeast.318319EXAMPLES::320321sage: G = GelfandTsetlinPattern([[3,2,1],[3,1],[1]])322sage: G.circled_entries()323((1, 1), (2, 0))324"""325ret = []326for i in range(1, len(self)):327for j in range(len(self[i])):328if self[i][j] == self[i-1][j+1]:329ret.append((i, j))330return tuple(ret)331332@cached_method333def special_entries(self):334"""335Return the special entries.336337An entry `a_{i,j}` is special if `a_{i-1,j-1} > a_{i,j} > a_{i-1,j}`,338that is to say, the entry is neither boxed nor circled and is **not**339in the first row. The name was coined by [Tok88]_.340341EXAMPLES::342343sage: G = GelfandTsetlinPattern([[3,2,1],[3,1],[1]])344sage: G.special_entries()345()346sage: G = GelfandTsetlinPattern([[4,2,1],[4,1],[2]])347sage: G.special_entries()348((2, 0),)349"""350ret = []351for i in range(1, len(self)):352for j in range(len(self[i])):353if self[i-1][j] > self[i][j] and self[i][j] > self[i-1][j+1]:354ret.append((i, j))355return tuple(ret)356357def number_of_boxes(self):358"""359Return the number of boxed entries. See :meth:`boxed_entries()`.360361EXAMPLES::362363sage: G = GelfandTsetlinPattern([[3,2,1],[3,1],[1]])364sage: G.number_of_boxes()3651366"""367return len(self.boxed_entries())368369def number_of_circles(self):370"""371Return the number of boxed entries. See :meth:`circled_entries()`.372373EXAMPLES::374375sage: G = GelfandTsetlinPattern([[3,2,1],[3,1],[1]])376sage: G.number_of_circles()3772378"""379return len(self.circled_entries())380381def number_of_special_entries(self):382"""383Return the number of special entries. See :meth:`special_entries()`.384385EXAMPLES::386387sage: G = GelfandTsetlinPattern([[4,2,1],[4,1],[2]])388sage: G.number_of_special_entries()3891390"""391return len(self.special_entries())392393def is_strict(self):394"""395Return ``True`` if ``self`` is a strict Gelfand-Tsetlin pattern.396397A Gelfand-Tsetlin pattern is said to be *strict* if every row is398strictly decreasing.399400EXAMPLES::401402sage: GelfandTsetlinPattern([[7,3,1],[6,2],[4]]).is_strict()403True404sage: GelfandTsetlinPattern([[3,2,1],[3,1],[1]]).is_strict()405True406sage: GelfandTsetlinPattern([[6,0,0],[3,0],[2]]).is_strict()407False408"""409for row in self:410if any(row[i] == row[i+1] for i in range(len(row)-1)):411return False412return True413414def row_sums(self):415r"""416Return the list of row sums.417418For a Gelfand-Tsetlin pattern `G`, the `i`-th row sum `d_i` is419420.. MATH::421422d_i = d_i(G) = \sum_{j=i}^{n} a_{i,j}.423424EXAMPLES::425426sage: G = GelfandTsetlinPattern([[5,3,2,1,0],[4,3,2,0],[4,2,1],[3,2],[3]])427sage: G.row_sums()428[11, 9, 7, 5, 3]429sage: G = GelfandTsetlinPattern([[3,2,1],[3,1],[2]])430sage: G.row_sums()431[6, 4, 2]432"""433return [sum(self[i][j] for j in range(len(self[i]))) \434for i in range(len(self))]435436def weight(self):437r"""438Return the weight of ``self``.439440Define the weight of `G` to be the content of the tableau to which `G`441corresponds under the bijection between Gelfand-Tsetlin patterns and442semistandard tableaux. More precisely,443444.. MATH::445446\mathrm{wt}(G) = (d_n, d_{n-1}-d_n, \dots, d_1-d_2),447448where the `d_i` are the row sums.449450EXAMPLES::451452sage: G = GelfandTsetlinPattern([[2,1,0],[1,0],[1]])453sage: G.weight()454(1, 0, 2)455sage: G = GelfandTsetlinPattern([[4,2,1],[3,1],[2]])456sage: G.weight()457(2, 2, 3)458"""459wt = [self.row_sums()[-1]] + [self.row_sums()[i-1]-self.row_sums()[i] for i in reversed(range(1,len(self[0])))]460return tuple(wt)461462def Tokuyama_coefficient(self, name='t'):463r"""464Return the Tokuyama coefficient attached to ``self``.465466Following the exposition of [BBF]_, Tokuyama's formula asserts467468.. MATH::469470\sum_{G} (t+1)^{s(G)} t^{l(G)}471z_1^{d_{n+1}} z_2^{d_{n}-d_{n+1}} \cdots z_{n+1}^{d_1-d_2}472=473s_{\lambda}(z_1,\dots,z_{n+1}) \prod_{i<j} (z_j+tz_i),474475where the sum is over all strict Gelfand-Tsetlin patterns with fixed476top row `\lambda + \rho`, with `\lambda` a partition with at most477`n+1` parts and `\rho = (n, n-1, \ldots, 1, 0)`, and `s_\lambda` is a478Schur function.479480INPUT:481482- ``name`` -- (Default: ``'t'``) An alternative name for the483variable `t`.484485EXAMPLES::486487sage: P = GelfandTsetlinPattern([[3,2,1],[2,2],[2]])488sage: P.Tokuyama_coefficient()4890490sage: G = GelfandTsetlinPattern([[3,2,1],[3,1],[2]])491sage: G.Tokuyama_coefficient()492t^2 + t493sage: G = GelfandTsetlinPattern([[2,1,0],[1,1],[1]])494sage: G.Tokuyama_coefficient()4950496sage: G = GelfandTsetlinPattern([[5,3,2,1,0],[4,3,2,0],[4,2,1],[3,2],[3]])497sage: G.Tokuyama_coefficient()498t^8 + 3*t^7 + 3*t^6 + t^5499"""500R = PolynomialRing(ZZ, name)501t = R.gen(0)502if self.is_strict() == False:503return R(0)504return (t+1)**(self.number_of_special_entries()) * t**(self.number_of_boxes())505506507class GelfandTsetlinPatterns(Parent, UniqueRepresentation):508"""509Gelfand-Tsetlin patterns.510511INPUT:512513- ``n`` -- The width or depth of the array, also known as the rank514515- ``k`` -- (Default: ``None``) If specified, this is the maximum value that516can occur in the patterns517518- ``top_row`` -- (Default: ``None``) If specified, this is the fixed top519row of all patterns520521- ``strict`` -- (Default: ``False``) Set to ``True`` if all patterns are522strict patterns523524TESTS:525526Check that the number of Gelfand-Tsetlin patterns is equal to the number527of semistandard Young tableaux::528529sage: G = GelfandTsetlinPatterns(3,3)530sage: c = 0531sage: from sage.combinat.crystals.kirillov_reshetikhin import partitions_in_box532sage: for p in partitions_in_box(3,3):533... S = SemistandardTableaux(p, max_entry=3)534... c += S.cardinality()535sage: c == G.cardinality()536True537538Note that the top row in reverse of the Gelfand-Tsetlin pattern is the539shape of the corresponding semistandard Young tableau under the bijection540described in :meth:`GelfandTsetlinPattern.to_tableau()`::541542sage: G = GelfandTsetlinPatterns(top_row=[2,2,1])543sage: S = SemistandardTableaux([2,2,1], max_entry=3)544sage: G.cardinality() == S.cardinality()545True546"""547@staticmethod548def __classcall_private__(cls, n=None, k=None, strict=False, top_row=None):549"""550Return the correct parent based upon the inputs.551552EXAMPLES::553554sage: G = GelfandTsetlinPatterns()555sage: G2 = GelfandTsetlinPatterns()556sage: G is G2557True558sage: G = GelfandTsetlinPatterns(3,4, strict=True)559sage: G2 = GelfandTsetlinPatterns(int(3),int(4), strict=True)560sage: G is G2561True562sage: G = GelfandTsetlinPatterns(top_row=[3,1,1])563sage: G2 = GelfandTsetlinPatterns(top_row=(3,1,1))564sage: G is G2565True566"""567if top_row is not None:568top_row = tuple(top_row)569if any(top_row[i] < top_row[i+1] for i in range(len(top_row)-1)):570raise ValueError("The top row must be weakly decreasing")571if n is not None and n != len(top_row):572raise ValueError("n must be the length of the specified top row")573return GelfandTsetlinPatternsTopRow(top_row, strict)574return super(GelfandTsetlinPatterns, cls).__classcall__(cls, n, k, strict)575576def __init__(self, n, k, strict):577"""578Initialize ``self``.579580EXAMPLES::581582sage: G = GelfandTsetlinPatterns()583sage: TestSuite(G).run()584sage: G = GelfandTsetlinPatterns(3)585sage: TestSuite(G).run()586sage: G = GelfandTsetlinPatterns(3, 3)587sage: TestSuite(G).run()588sage: G = GelfandTsetlinPatterns(3, 3, strict=True)589sage: TestSuite(G).run()590"""591self._n = n592self._k = k593self._strict = strict594# Note - if a top row is given, then n and k are not None595if k is not None and (n is not None or strict):596Parent.__init__(self, category=FiniteEnumeratedSets())597else:598Parent.__init__(self, category=InfiniteEnumeratedSets())599600def __contains__(self, gt):601"""602Check to see if ``gt`` is in ``self``.603604EXAMPLES::605606sage: G = GelfandTsetlinPatterns()607sage: [[3, 1],[2]] in G608True609sage: [[2, 3],[4]] in G610False611sage: [[3, 1],[0]] in G612False613sage: [] in G614True615sage: G = GelfandTsetlinPatterns(3,2)616sage: [] in G617False618sage: [[2,0,0],[1,0],[1]] in G619True620sage: [[0,0],[0]] in G621False622sage: [[3,0,0],[2,0],[0]] in G623False624sage: G = GelfandTsetlinPatterns(3,strict=True)625sage: [[2,1,0],[2,1],[1]] in G626True627sage: [[3,0,0],[3,0],[0]] in G628False629"""630if not isinstance(gt, (list, tuple, GelfandTsetlinPattern)):631return False632# Check if it has the correct width/depth (if applicable)633if self._n is not None and len(gt) != self._n:634return False635# Check if it has the correct maximum value636if self._k is not None and any( val > self._k for row in gt for val in row ):637return False638# Check if it is a GT pattern639if not all( gt[i-1][j] >= gt[i][j] >= gt[i-1][j+1]640for i in range(1, len(gt)) for j in range(len(gt[i])) ):641return False642# Check if it is strict if applicable643if self._strict and any( gt[i][j] == gt[i][j-1] for i in range(len(gt))644for j in range(1, len(gt[i])) ):645return False646return True647648def _repr_(self):649"""650Return a string representation of ``self``.651652EXAMPLES::653654sage: GelfandTsetlinPatterns(4)655Gelfand-Tsetlin patterns of width 4656sage: GelfandTsetlinPatterns(4, 3, strict=True)657Strict Gelfand-Tsetlin patterns of width 4 and max value 3658sage: G = GelfandTsetlinPatterns(k=3, strict=True); G659Strict Gelfand-Tsetlin patterns with max value 3660"""661base = "Gelfand-Tsetlin patterns"662if self._strict:663base = "Strict " + base664if self._n is not None:665if self._k is not None:666return base + " of width %s and max value %s"%(self._n, self._k)667return base + " of width %s"%self._n668if self._k is not None:669return base + " with max value %s"%self._k670return base671672def _element_constructor_(self, gt):673"""674Construct an element of ``self`` from ``gt``.675676EXAMPLES::677678sage: G = GelfandTsetlinPatterns(3, 3, strict=True); G679Strict Gelfand-Tsetlin patterns of width 3 and max value 3680sage: elt = G([[3,2,1],[2,1],[1]]); elt.pp()6813 2 16822 16831684sage: elt.parent()685Strict Gelfand-Tsetlin patterns of width 3 and max value 3686"""687if isinstance(gt, GelfandTsetlinPattern) and gt.parent() == self:688return gt689if isinstance(gt, Tableau):690gt = [list(x) for x in reversed(gt.to_chain()[1:])]691n = len(gt)692for i in range(n):693while len(gt[i]) < n-i:694gt[i].append(0)695if self._n is not None:696if len(gt) == 0:697gt = [[0]]698while self._n != len(gt):699gt.insert(0, gt[0][:] + [0])700return self.element_class(self, gt)701return self.element_class(self, list(gt))702703Element = GelfandTsetlinPattern704705def __iter__(self):706"""707Iterate through ``self`` by using a backtracing algorithm.708709EXAMPLES::710711sage: L = list(GelfandTsetlinPatterns(3,3))712sage: c = 0713sage: from sage.combinat.crystals.kirillov_reshetikhin import partitions_in_box714sage: for p in partitions_in_box(3,3):715... S = SemistandardTableaux(p, max_entry=3)716... c += S.cardinality()717sage: c == len(L)718True719sage: G = GelfandTsetlinPatterns(3, 3, strict=True)720sage: all(x.is_strict() for x in G)721True722sage: G = GelfandTsetlinPatterns(k=3, strict=True)723sage: all(x.is_strict() for x in G)724True725726Checking iterator when the set is infinite::727728sage: T = GelfandTsetlinPatterns()729sage: it = T.__iter__()730sage: [it.next() for i in range(10)]731[[],732[[1]],733[[2]],734[[1, 1], [1]],735[[3]],736[[2, 1], [1]],737[[2, 1], [2]],738[[1, 1, 1], [1, 1], [1]],739[[4]],740[[3, 1], [1]]]741sage: T = GelfandTsetlinPatterns(k=1)742sage: it = T.__iter__()743sage: [it.next() for i in range(10)]744[[],745[[0]],746[[1]],747[[0, 0], [0]],748[[1, 0], [0]],749[[1, 0], [1]],750[[1, 1], [1]],751[[0, 0, 0], [0, 0], [0]],752[[1, 0, 0], [0, 0], [0]],753[[1, 0, 0], [1, 0], [0]]]754755Check that :trac:`14718` is fixed::756757sage: T = GelfandTsetlinPatterns(1,3)758sage: list(T)759[[[0]],760[[1]],761[[2]],762[[3]]]763"""764# Special cases765if self._n is None:766yield self.element_class(self, [])767if self._k is None:768# Since both `n` and `k` are none, we need special consideration769# while iterating, so we do so by specifying the top row by770# using the iterator for partitions771n = 1772while True:773if self._strict:774P = Partitions(n, max_slope=-1)775else:776P = Partitions(n)777for p in P:778for x in GelfandTsetlinPatterns(top_row=tuple(p), strict=self._strict):779yield self.element_class(self, list(x))780n += 1781return782for x in xrange(self._k+1):783yield self.element_class(self, [[x]])784n = 2785while not self._strict or n <= self._k+1:786for x in self._list_iter(n):787yield self.element_class(self, x)788n += 1789return790if self._n < 0:791return792if self._n == 0:793yield self.element_class(self, [])794return795if self._n == 1:796if self._k is not None:797for x in xrange(self._k+1):798yield self.element_class(self, [[x]])799else:800k = 1801while True:802yield self.element_class(self, [[k]])803k += 1804return805for x in self._list_iter(self._n):806yield self.element_class(self, x)807808def _list_iter(self, n):809"""810Fast iterator which returns Gelfand-Tsetlin patterns of width ``n`` as811lists of lists.812813EXAMPLES::814815sage: G = GelfandTsetlinPatterns(3, 1)816sage: L = [x for x in G._list_iter(3)]817sage: len(L) == G.cardinality()818True819sage: type(L[0])820<type 'list'>821"""822# Setup the first row823iters = [None]*n824ret = [None]*n825iters[0] = self._top_row_iter(n)826ret[0] = iters[0].next()827min_pos = 0828iters[1] = self._row_iter(ret[0])829pos = 1830while pos >= min_pos:831try:832ret[pos] = iters[pos].next()833pos += 1834# If we've reached 0 width, yield and backstep835if pos == n:836yield ret[:]837pos -= 1838continue839iters[pos] = self._row_iter(ret[pos-1])840except StopIteration:841pos -= 1842843def _top_row_iter(self, n):844"""845Helper iterator for the top row.846847EXAMPLES::848849sage: G = GelfandTsetlinPatterns(3, 1)850sage: for x in G._top_row_iter(3): x851[0, 0, 0]852[1, 0, 0]853[1, 1, 0]854[1, 1, 1]855sage: G = GelfandTsetlinPatterns(3, 2, strict=True)856sage: for x in G._top_row_iter(3): x857[2, 1, 0]858"""859row = [-1]*n860pos = 0861while pos >= 0:862if pos == n:863yield row[:]864pos -= 1865continue866# If it would create an invalid entry, backstep867if ( pos > 0 and (row[pos] >= row[pos-1] \868or (self._strict and row[pos] == row[pos-1]-1)) ) \869or (self._k is not None and row[pos] >= self._k):870row[pos] = -1871pos -= 1872continue873row[pos] += 1874pos += 1875876def _row_iter(self, upper_row):877"""878Helper iterator for any row with a row above it.879880EXAMPLES::881882sage: G = GelfandTsetlinPatterns(3, 4)883sage: for x in G._row_iter([4,2,1]): x884[2, 1]885[2, 2]886[3, 1]887[3, 2]888[4, 1]889[4, 2]890sage: G = GelfandTsetlinPatterns(3, 2, strict=True)891sage: for x in G._row_iter([2, 1, 0]): x892[1, 0]893[2, 0]894[2, 1]895"""896row = [x-1 for x in upper_row[1:]]897row_len = len(row)898pos = 0899while pos >= 0:900if pos == row_len:901yield row[:]902pos -= 1903continue904# If it would create an invalid entry, backstep905if ( pos > 0 and (row[pos] >= row[pos-1] \906or (self._strict and row[pos] == row[pos-1]-1)) ) \907or row[pos] >= upper_row[pos] \908or (self._k is not None and row[pos] >= self._k):909row[pos] = upper_row[pos+1] - 1910pos -= 1911continue912row[pos] += 1913pos += 1914915class GelfandTsetlinPatternsTopRow(GelfandTsetlinPatterns):916"""917Gelfand-Tsetlin patterns with a fixed top row.918"""919def __init__(self, top_row, strict):920"""921Initialize ``self``.922923EXAMPLES::924925sage: G = GelfandTsetlinPatterns(top_row=[4,4,3,1])926sage: TestSuite(G).run()927928TESTS:929930Check a border case in :trac:`14765`::931932sage: G = GelfandTsetlinPatterns(top_row=[])933sage: list(G)934[[]]935"""936self._row = top_row937n = len(top_row)938if n == 0:939k = 0940else:941k = top_row[0]942GelfandTsetlinPatterns.__init__(self, n, k, strict)943944def _repr_(self):945"""946Return a string representation of ``self``.947948EXAMPLES::949950sage: GelfandTsetlinPatterns(top_row=[4,4,3,1])951Gelfand-Tsetlin patterns with top row [4, 4, 3, 1]952sage: GelfandTsetlinPatterns(top_row=[5,4,3,1], strict=True)953Strict Gelfand-Tsetlin patterns with top row [5, 4, 3, 1]954"""955base = "Gelfand-Tsetlin patterns with top row %s"%list(self._row)956if self._strict:957base = "Strict " + base958return base959960def __contains__(self, gt):961"""962Check if ``gt`` is in ``self``.963964EXAMPLES::965966sage: G = GelfandTsetlinPatterns(top_row=[4,4,1])967sage: [[4,4,1], [4,2], [3]] in G968True969sage: [[4,3,1], [4,2], [3]] in G970False971"""972# Check if the the top row matches (if applicable)973if tuple(gt[0]) != self._row:974return False975return GelfandTsetlinPatterns.__contains__(self, gt)976977def __iter__(self):978"""979Iterate over ``self``.980981EXAMPLES::982983sage: G = GelfandTsetlinPatterns(top_row=[4,2,1])984sage: list(G)985[[[4, 2, 1], [2, 1], [1]],986[[4, 2, 1], [2, 1], [2]],987[[4, 2, 1], [2, 2], [2]],988[[4, 2, 1], [3, 1], [1]],989[[4, 2, 1], [3, 1], [2]],990[[4, 2, 1], [3, 1], [3]],991[[4, 2, 1], [3, 2], [2]],992[[4, 2, 1], [3, 2], [3]],993[[4, 2, 1], [4, 1], [1]],994[[4, 2, 1], [4, 1], [2]],995[[4, 2, 1], [4, 1], [3]],996[[4, 2, 1], [4, 1], [4]],997[[4, 2, 1], [4, 2], [2]],998[[4, 2, 1], [4, 2], [3]],999[[4, 2, 1], [4, 2], [4]]]1000"""1001# If we enforce strictness, check to see if a specified top row is strict1002if self._strict and any(self._row[i] == self._row[i+1] for i in range(self._n-1)):1003return1004if self._n == 0:1005yield self.element_class(self, [])1006return1007if self._n == 1:1008yield self.element_class(self, [list(self._row)])1009return1010# Setup the first row1011iters = [None]*self._n1012ret = [None]*self._n1013ret[0] = list(self._row)1014min_pos = 11015iters[1] = self._row_iter(ret[0])1016pos = 11017while pos >= min_pos:1018try:1019ret[pos] = iters[pos].next()1020pos += 11021# If we've reached 0 width, yield and backstep1022if pos == self._n:1023yield self.element_class(self, ret[:])1024pos -= 11025continue1026iters[pos] = self._row_iter(ret[pos-1])1027except StopIteration:1028pos -= 110291030def top_row(self):1031"""1032Return the top row of ``self``.10331034EXAMPLES::10351036sage: G = GelfandTsetlinPatterns(top_row=[4,4,3,1])1037sage: G.top_row()1038(4, 4, 3, 1)1039"""1040return self._row10411042def Tokuyama_formula(self, name='t'):1043r"""1044Return the Tokuyama formula of ``self``.10451046Following the exposition of [BBF]_, Tokuyama's formula asserts10471048.. MATH::10491050\sum_{G} (t+1)^{s(G)} t^{l(G)}1051z_1^{d_{n+1}} z_2^{d_{n}-d_{n+1}} \cdots z_{n+1}^{d_1-d_2}1052= s_{\lambda} (z_1, \ldots, z_{n+1}) \prod_{i<j} (z_j+tz_i),10531054where the sum is over all strict Gelfand-Tsetlin patterns with fixed1055top row `\lambda+\rho`, with `\lambda` a partition with at most1056`n+1` parts and `\rho = (n,n-1,\dots,1,0)`, and `s_{\lambda}` is a Schur1057function.10581059INPUT:10601061- ``name`` -- (Default: ``'t'``) An alternative name for the1062variable `t`.10631064EXAMPLES::10651066sage: GT = GelfandTsetlinPatterns(top_row=[2,1,0],strict=True)1067sage: GT.Tokuyama_formula()1068t^3*x1^2*x2 + t^2*x1*x2^2 + t^2*x1^2*x3 + t^2*x1*x2*x3 + t*x1*x2*x3 + t*x2^2*x3 + t*x1*x3^2 + x2*x3^21069sage: GT = GelfandTsetlinPatterns(top_row=[3,2,1],strict=True)1070sage: GT.Tokuyama_formula()1071t^3*x1^3*x2^2*x3 + t^2*x1^2*x2^3*x3 + t^2*x1^3*x2*x3^2 + t^2*x1^2*x2^2*x3^2 + t*x1^2*x2^2*x3^2 + t*x1*x2^3*x3^2 + t*x1^2*x2*x3^3 + x1*x2^2*x3^31072sage: GT = GelfandTsetlinPatterns(top_row=[1,1,1],strict=True)1073sage: GT.Tokuyama_formula()107401075"""1076n = self._n1077variables = [name] + ["x%d"%i for i in range(1,n+1)]1078R = PolynomialRing(ZZ,names=variables)1079t = R.gen(0)1080x = R.gens()[1:]1081GT = GelfandTsetlinPatterns(top_row=self._row, strict=True)1082return sum((t+1)**(gt.number_of_special_entries()) * t**(gt.number_of_boxes()) * prod(x[i]**gt.weight()[i] for i in range(n)) for gt in GT)108310841085