def from_labelled_dyck_word(LDW): r""" Return the parking function corresponding to the labelled Dyck word. INPUT: - ``LDW`` -- labelled Dyck word OUTPUT: - the parking function corresponding to the labelled Dyck word that is half the size of ``LDW`` EXAMPLES:: sage: from sage.combinat.parking_functions import from_labelled_dyck_word sage: LDW = [2, 6, 0, 4, 5, 0, 0, 0, 3, 7, 0, 1, 0, 0] sage: from_labelled_dyck_word(LDW) [6, 1, 5, 2, 2, 1, 5] :: sage: from_labelled_dyck_word([2, 3, 0, 0, 1, 0, 4, 0]) [3, 1, 1, 4] sage: from_labelled_dyck_word([2, 3, 4, 0, 0, 0, 1, 0]) [4, 1, 1, 1] sage: from_labelled_dyck_word([2, 4, 0, 1, 0, 0, 3, 0]) [2, 1, 4, 1] """ L = [ell for ell in LDW if ell != 0] D = DyckWord(map(lambda x: Integer(not x.is_zero()), LDW)) return from_labelling_and_area_sequence(L, D.to_area_sequence())
def to_perfect_matching(self): r""" Return the perfect matching associated to ``self``. EXAMPLES:: sage: path_tableaux.DyckPath([0,1,2,1,2,1,0,1,0]).to_perfect_matching() [(0, 5), (1, 2), (3, 4), (6, 7)] TESTS:: sage: path_tableaux.DyckPath([1,2,1,2,1,0,1]).to_perfect_matching() Traceback (most recent call last): ... ValueError: [1, 2, 1, 2, 1, 0, 1] does not start at 0 """ if self.is_skew(): raise ValueError("%s does not start at 0" % (str(self))) w = self.to_word() y = DyckWord(w) pairs = set() for i, a in enumerate(y): c = y.associated_parenthesis(i) if i < c: pairs.add((i, c)) return PerfectMatching(pairs)
def from_labelled_dyck_word(LDW): r""" Returns the parking function corresponding to the labelled Dyck word. INPUT: - ``LDW`` -- labelled Dyck word OUTPUT: - returns the parking function corresponding to the labelled Dyck word that is half the size of ``LDW`` EXAMPLES:: sage: from sage.combinat.parking_functions import from_labelled_dyck_word sage: LDW = [2, 6, 0, 4, 5, 0, 0, 0, 3, 7, 0, 1, 0, 0] sage: from_labelled_dyck_word(LDW) [6, 1, 5, 2, 2, 1, 5] :: sage: from_labelled_dyck_word([2, 3, 0, 0, 1, 0, 4, 0]) [3, 1, 1, 4] sage: from_labelled_dyck_word([2, 3, 4, 0, 0, 0, 1, 0]) [4, 1, 1, 1] sage: from_labelled_dyck_word([2, 4, 0, 1, 0, 0, 3, 0]) [2, 1, 4, 1] """ L = [ell for ell in LDW if ell!=0] D = DyckWord(map(lambda x: Integer(not x.is_zero()), LDW)) return from_labelling_and_area_sequence(L, D.to_area_sequence())
def to_dyck_word(self): r""" Returns the support Dyck word of the parking function. INPUT: - ``self`` -- parking function word OUTPUT: - returns the Dyck word of the corresponding parking function .. SEEALSO:: :meth:`DyckWord` EXAMPLES:: sage: PF = ParkingFunction([6, 1, 5, 2, 2, 1, 5]) sage: PF.to_dyck_word() [1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0] :: sage: ParkingFunction([3,1,1,4]).to_dyck_word() [1, 1, 0, 0, 1, 0, 1, 0] sage: ParkingFunction([4,1,1,1]).to_dyck_word() [1, 1, 1, 0, 0, 0, 1, 0] sage: ParkingFunction([2,1,4,1]).to_dyck_word() [1, 1, 0, 1, 0, 0, 1, 0] """ return DyckWord(area_sequence=self.to_area_sequence())
def Possible(n): r""" Possible stack of DyckWords inside a n x n cube. EXAMPLES:: sage: from slabbe.dyck_3d import Possible sage: Possible(1) The Cartesian product of ({[1, 0]},) sage: Possible(2) The Cartesian product of ({[1, 1, 0, 0]}, {[1, 0, 1, 0], [1, 1, 0, 0]}) sage: Possible(3).list() [([1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 0, 1, 0, 1, 0]), ([1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 0, 1, 1, 0, 0]), ([1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 1, 0, 0, 1, 0]), ([1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 1, 0, 1, 0, 0]), ([1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 1, 1, 0, 0, 0]), ([1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 0, 1, 0, 1, 0]), ([1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 0, 1, 1, 0, 0]), ([1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 0, 0, 1, 0]), ([1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0]), ([1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0])] """ from sage.combinat.dyck_word import DyckWords, DyckWord from sage.categories.cartesian_product import cartesian_product L = [] for i in range(1, n + 1): K = [] for w in DyckWords(i): w = DyckWord([1] * (n - i) + list(w) + [0] * (n - i)) K.append(w) L.append(K) return cartesian_product(L)
def to_DyckWord(self): r""" Converts ``self`` to a Dyck word. EXAMPLES:: sage: c = path_tableaux.DyckPath([0,1,2,1,0]) sage: c.to_DyckWord() [1, 1, 0, 0] """ return DyckWord(heights_sequence=list(self))
def to_dyck_word(self, usemap="1L0R"): r""" INPUT: - ``usemap`` -- a string, either ``1L0R``, ``1R0L``, ``L1R0``, ``R1L0`` Return the Dyck word associated with ``self`` using the given map. The bijection is defined recursively as follows: - a leaf is associated to the empty Dyck Word - a tree with children `l,r` is associated with the Dyck word described by ``usemap`` where `L` and `R` are respectively the Dyck words associated with the `l` and `r`. EXAMPLES:: sage: BinaryTree().to_dyck_word() [] sage: BinaryTree([]).to_dyck_word() [1, 0] sage: BinaryTree([[[], [[], None]], [[], []]]).to_dyck_word() [1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0] sage: BinaryTree([[None,[]],None]).to_dyck_word() [1, 1, 0, 1, 0, 0] sage: BinaryTree([[None,[]],None]).to_dyck_word("1R0L") [1, 0, 1, 1, 0, 0] sage: BinaryTree([[None,[]],None]).to_dyck_word("L1R0") [1, 1, 0, 0, 1, 0] sage: BinaryTree([[None,[]],None]).to_dyck_word("R1L0") [1, 1, 0, 1, 0, 0] sage: BinaryTree([[None,[]],None]).to_dyck_word("R10L") Traceback (most recent call last): ... ValueError: R10L is not a correct map TESTS:: sage: bt = BinaryTree([[[], [[], None]], [[], []]]) sage: bt == bt.to_dyck_word().to_binary_tree() True sage: bt == bt.to_dyck_word("1R0L").to_binary_tree("1R0L") True sage: bt == bt.to_dyck_word("L1R0").to_binary_tree("L1R0") True sage: bt == bt.to_dyck_word("R1L0").to_binary_tree("R1L0") True """ from sage.combinat.dyck_word import DyckWord if usemap not in ["1L0R", "1R0L", "L1R0", "R1L0"]: raise ValueError, "%s is not a correct map"%(usemap) return DyckWord(self._to_dyck_word_rec(usemap))
def from_bounce_pair(dyck, alpha): r""" Returns an LAC-tree in bijection with the given bounce pair. A check is performed for validity. INPUT: - ``dyck``: a Dyck path in the 0,1 format - ``alpha``: a composition indicating the bounce path OUTPUT: An LAC-tree in bijection with this bounce pair """ n = sum(alpha) if n * 2 != len(dyck): raise ValueError('Inconsistent sizes of parameters') bounce = [] for a in alpha: bounce += ([1] * a) + ([0] * a) dwa = DyckWord(dyck) dwb = DyckWord(bounce) area_a = dwa.to_area_sequence() area_b = dwb.to_area_sequence() if not all(area_a[i] >= area_b[i] for i in range(n)): raise ValueError('Incompatible parameters') # count children number by counting north steps on each x-coordinate vsteps = [0] * (n + 1) cur = 0 x = 0 while cur < len(dyck): while 1 == dyck[cur]: cur += 1 vsteps[x] += 1 cur += 1 x += 1 # construct tree l = len(alpha) dyckpost = n - alpha[l - 1] actives = [OrderedTree([]) for i in range(alpha[l - 1])] for region in range(l - 2, -1, -1): newactives = [] for i in range(alpha[region]): newnode = OrderedTree(actives[:vsteps[dyckpost]]) actives = actives[vsteps[dyckpost]:] newactives.append(newnode) dyckpost -= 1 actives = newactives + actives T = OrderedTree(actives) # coloring with existent function return LACTree(T, alpha)
def to_dyck_word(self): r""" Return the Dyck path corresponding to ``self`` where the maximal height of the Dyck path is the depth of ``self`` . EXAMPLES:: sage: T = OrderedTree([[],[]]) sage: T.to_dyck_word() [1, 0, 1, 0] sage: T = OrderedTree([[],[[]]]) sage: T.to_dyck_word() [1, 0, 1, 1, 0, 0] sage: T = OrderedTree([[], [[], []], [[], [[]]]]) sage: T.to_dyck_word() [1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0] """ word = [] for child in self: word.append(1) word.extend(child.to_dyck_word()) word.append(0) from sage.combinat.dyck_word import DyckWord return DyckWord(word)
def ParkingFunction(pf=None, labelling=None, area_sequence=None, labelled_dyck_word=None): r""" Return the combinatorial class of Parking Functions. A *parking function* of size `n` is a sequence `(a_1, \ldots,a_n)` of positive integers such that if `b_1 \leq b_2 \leq \cdots \leq b_n` is the increasing rearrangement of `a_1, \ldots, a_n`, then `b_i \leq i`. A *parking function* of size `n` is a pair `(L, D)` of two sequences `L` and `D` where `L` is a permutation and `D` is an area sequence of a Dyck Path of size `n` such that `D[i] \geq 0`, `D[i+1] \leq D[i]+1` and if `D[i+1] = D[i]+1` then `L[i+1] > L[i]`. The number of parking functions of size `n` is equal to the number of rooted forests on `n` vertices and is equal to `(n+1)^{n-1}`. INPUT: - ``pf`` -- (default: None) a list whose increasing rearrangement satisfies `b_i \leq i` - ``labelling`` -- (default: None) a labelling of the Dyck path - ``area_sequence`` -- (default: None) an area sequence of a Dyck path - ``labelled_dyck_word`` -- (default: None) a Dyck word with 1's replaced by labelling OUTPUT: - A parking function EXAMPLES:: sage: ParkingFunction([]) [] sage: ParkingFunction([1]) [1] sage: ParkingFunction([2]) Traceback (most recent call last): ... ValueError: [2] is not a parking function. sage: ParkingFunction([1,2]) [1, 2] sage: ParkingFunction([1,1,2]) [1, 1, 2] sage: ParkingFunction([1,4,1]) Traceback (most recent call last): ... ValueError: [1, 4, 1] is not a parking function. sage: ParkingFunction(labelling=[3,1,2], area_sequence=[0,0,1]) [2, 2, 1] sage: ParkingFunction([2,2,1]).to_labelled_dyck_word() [3, 0, 1, 2, 0, 0] sage: ParkingFunction(labelled_dyck_word = [3,0,1,2,0,0]) [2, 2, 1] sage: ParkingFunction(labelling=[3,1,2], area_sequence=[0,1,1]) Traceback (most recent call last): ... ValueError: [3, 1, 2] is not a valid labeling of area sequence [0, 1, 1] """ if pf is not None: return ParkingFunction_class(pf) elif labelling is not None: if (area_sequence is None): raise ValueError("must also provide area sequence along with labelling.") if (len(area_sequence) != len(labelling)): raise ValueError("%s must be the same size as the labelling %s" % (area_sequence, labelling)) if any(area_sequence[i] < area_sequence[i+1] and labelling[i] > labelling[i + 1] for i in range(len(labelling) - 1)): raise ValueError("%s is not a valid labeling of area sequence %s" % (labelling, area_sequence)) return from_labelling_and_area_sequence(labelling, area_sequence) elif labelled_dyck_word is not None: return from_labelled_dyck_word(labelled_dyck_word) elif area_sequence is not None: DW = DyckWord(area_sequence) return ParkingFunction(labelling=range(1, DW.size() + 1), area_sequence=DW) raise ValueError("did not manage to make this into a parking function")
def ParkingFunction(pf=None, labelling=None, area_sequence=None, labelled_dyck_word = None): r""" Returns the combinatorial class of Parking Functions. A *parking function* of size `n` is a sequence `(a_1, \ldots,a_n)` of positive integers such that if `b_1 \leq b_2 \leq \cdots \leq b_n` is the increasing rearrangement of `a_1, \ldots, a_n`, then `b_i \leq i`. A *parking function* of size `n` is a pair `(L, D)` of two sequences `L` and `D` where `L` is a permutation and `D` is an area sequence of a Dyck Path of size `n` such that `D[i] \geq 0`, `D[i+1] \leq D[i]+1` and if `D[i+1] = D[i]+1` then `L[i+1] > L[i]`. The number of parking functions of size `n` is equal to the number of rooted forests on `n` vertices and is equal to `(n+1)^{n-1}`. INPUT: - ``pf`` -- (default: None) a list whose increasing rearrangement satisfies `b_i \leq i` - ``labelling`` -- (default: None) a labelling of the Dyck path - ``area_sequence`` -- (default: None) an area sequence of a Dyck path - ``labelled_dyck_word`` -- (default: None) a Dyck word with 1's replaced by labelling OUTPUT: - A parking function EXAMPLES:: sage: ParkingFunction([]) [] sage: ParkingFunction([1]) [1] sage: ParkingFunction([2]) Traceback (most recent call last): ... ValueError: [2] is not a parking function. sage: ParkingFunction([1,2]) [1, 2] sage: ParkingFunction([1,1,2]) [1, 1, 2] sage: ParkingFunction([1,4,1]) Traceback (most recent call last): ... ValueError: [1, 4, 1] is not a parking function. sage: ParkingFunction(labelling=[3,1,2], area_sequence=[0,0,1]) [2, 2, 1] sage: ParkingFunction([2,2,1]).to_labelled_dyck_word() [3, 0, 1, 2, 0, 0] sage: ParkingFunction(labelled_dyck_word = [3,0,1,2,0,0]) [2, 2, 1] sage: ParkingFunction(labelling=[3,1,2], area_sequence=[0,1,1]) Traceback (most recent call last): ... ValueError: [3, 1, 2] is not a valid labeling of area sequence [0, 1, 1] """ if pf is not None: return ParkingFunction_class(pf) elif labelling is not None: if (area_sequence is None): raise ValueError("must also provide area sequence along with labelling.") if (len(area_sequence)!=len(labelling)): raise ValueError("%s must be the same size as the labelling %s"%(area_sequence,labelling)) if any(area_sequence[i]<area_sequence[i+1] and labelling[i]>labelling[i+1] for i in range(len(labelling)-1)): raise ValueError("%s is not a valid labeling of area sequence %s"%(labelling, area_sequence)) return from_labelling_and_area_sequence( labelling, area_sequence ) elif labelled_dyck_word is not None: return from_labelled_dyck_word(labelled_dyck_word) elif area_sequence is not None: DW = DyckWord(area_sequence) return ParkingFunction(labelling=range(1,DW.size()+1), area_sequence=DW) else: raise ValueError("did not manage to make this into a parking function")
def from_steep_pair(steep, path): r""" Returns an LAC-tree in bijection with the given steep pair. A check is performed for validity. INPUT: - ``steep``: a steep path in the 0,1 format - ``path``: a Dyck path in the 0,1 format OUTPUT: An LAC-tree in bijection with this steep pair """ if len(steep) != len(path): raise ValueError('Inconsistent sizes of parameters') n = len(path) // 2 a1 = DyckWord(steep).to_area_sequence() a2 = DyckWord(path).to_area_sequence() for i in range(len(a1)): if a1[i] < a2[i]: raise ValueError('Incompatible parameters: not nested') Tc = DyckWord(path).to_ordered_tree().left_right_symmetry() Tc = Tc.canonical_labelling().left_right_symmetry() # extract marks from steep, 2 means marked north step marks = [True] for i in range(1, len(steep)): if steep[i] != 0: marks.append(0 != steep[i - 1]) marked = list(path) curptr = 0 for i in range(len(marked)): if marked[i] != 0: marked[i] = 2 if marks[curptr] else 1 curptr += 1 # coloring colorlist = [-1 for i in range(n + 2)] colorstack = [-1] colorptr = 0 curcolor = -1 curlabel = 0 colorlast = {} colorcount = {} labellist = [x.label() for x in Tc.pre_order_traversal_iter()] for x in marked: if 2 == x: curcolor += 1 colorptr += 1 colorstack.insert(colorptr, curcolor) curlabel += 1 colorlist[curlabel] = curcolor colorlast[curcolor] = labellist[curlabel] colorcount[curcolor] = 1 elif 1 == x: colorptr += 1 curlabel += 1 mycolor = colorstack[colorptr] colorlist[curlabel] = mycolor colorlast[mycolor] = labellist[curlabel] colorcount[mycolor] += 1 else: colorptr -= 1 alpha = sorted(colorlast.items(), key=lambda x: x[1]) alpha = list(map(lambda x: colorcount[x[0]], alpha)) return LACTree(Tc.shape().left_right_symmetry(), alpha)
def __init__(self, parent, ot, check=True): r""" Initialize a Dyck path. TESTS:: sage: D = path_tableaux.DyckPath(Tableau([[1,2], [3,4]])) sage: TestSuite(D).run() sage: D = path_tableaux.DyckPath(PerfectMatching([(1,4), (2,3), (5,6)])) sage: TestSuite(D).run() sage: t = path_tableaux.DyckPath([0,1,2,3,2,1,0]) sage: TestSuite(t).run() sage: path_tableaux.DyckPath(PerfectMatching([(1, 3), (2, 4), (5, 6)])) Traceback (most recent call last): ... ValueError: the perfect matching must be non crossing sage: path_tableaux.DyckPath(Tableau([[1,2,5],[3,5,6]])) Traceback (most recent call last): ... ValueError: the tableau must be standard sage: path_tableaux.DyckPath(Tableau([[1,2,4],[3,5,6],[7]])) Traceback (most recent call last): ... ValueError: the tableau must have at most two rows sage: path_tableaux.DyckPath(SkewTableau([[None, 1,4],[2,3],[5]])) Traceback (most recent call last): ... ValueError: the skew tableau must have at most two rows sage: path_tableaux.DyckPath([0,1,2.5,1,0]) Traceback (most recent call last): ... ValueError: [0, 1, 2.50000000000000, 1, 0] is not a sequence of integers sage: path_tableaux.DyckPath(Partition([3,2,1])) Traceback (most recent call last): ... ValueError: invalid input [3, 2, 1] """ w = None if isinstance(ot, DyckWord): w = ot.heights() elif isinstance(ot, PerfectMatching): if ot.is_noncrossing(): u = [1] * ot.size() for a in ot.arcs(): u[a[1] - 1] = 0 w = DyckWord(u).heights() else: raise ValueError("the perfect matching must be non crossing") elif isinstance(ot, Tableau): if len(ot) > 2: raise ValueError("the tableau must have at most two rows") if ot.is_standard(): u = [1] * ot.size() for i in ot[1]: u[i - 1] = 0 w = DyckWord(u).heights() else: raise ValueError("the tableau must be standard") elif isinstance(ot, SkewTableau): if len(ot) > 2: raise ValueError("the skew tableau must have at most two rows") # The check that ot is standard is not implemented c = ot.to_chain() w = [0] * len(c) for i, a in enumerate(c): if len(a) == 1: w[i] = a[0] else: w[i] = a[0] - a[1] elif isinstance(ot, (list, tuple)): try: w = tuple([Integer(a) for a in ot]) except TypeError: raise ValueError("%s is not a sequence of integers" % ot) if w is None: raise ValueError("invalid input %s" % ot) PathTableau.__init__(self, parent, w, check=check)