Пример #1
0
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())
Пример #2
0
    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())
Пример #5
0
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)
Пример #6
0
    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))
Пример #7
0
    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))
Пример #8
0
    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)
Пример #9
0
    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)
Пример #10
0
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")
Пример #12
0
    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)
Пример #13
0
    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)