예제 #1
0
    def __classcall_private__(cls, t, weight):
        r"""
        Implements the shortcut ``LittlewoodRichardsonTableau(t, weight)`` to
        ``LittlewoodRichardsonTableaux(shape , weight)(t)``
        where ``shape`` is the shape of the tableau.

        TESTS::

            sage: LR = LittlewoodRichardsonTableaux([3,2,1],[[2,1],[2,1]])
            sage: t = LR([[1, 1, 3], [2, 3], [4]])
            sage: t.check()
            sage: type(t)
            <class 'sage.combinat.lr_tableau.LittlewoodRichardsonTableaux_with_category.element_class'>
            sage: TestSuite(t).run()
            sage: from sage.combinat.lr_tableau import LittlewoodRichardsonTableau
            sage: LittlewoodRichardsonTableau([[1,1,3],[2,3],[4]], [[2,1],[2,1]])
            [[1, 1, 3], [2, 3], [4]]
        """
        if isinstance(t, cls):
            return t
        tab = SemistandardTableau(list(t))
        shape = tab.shape()
        return LittlewoodRichardsonTableaux(shape, weight)(t)
예제 #2
0
파일: lr_tableau.py 프로젝트: sagemath/sage
    def __classcall_private__(cls, t, weight):
        r"""
        Implements the shortcut ``LittlewoodRichardsonTableau(t, weight)`` to
        ``LittlewoodRichardsonTableaux(shape , weight)(t)``
        where ``shape`` is the shape of the tableau.

        TESTS::

            sage: LR = LittlewoodRichardsonTableaux([3,2,1],[[2,1],[2,1]])
            sage: t = LR([[1, 1, 3], [2, 3], [4]])
            sage: t.check()
            sage: type(t)
            <class 'sage.combinat.lr_tableau.LittlewoodRichardsonTableaux_with_category.element_class'>
            sage: TestSuite(t).run()
            sage: from sage.combinat.lr_tableau import LittlewoodRichardsonTableau
            sage: LittlewoodRichardsonTableau([[1,1,3],[2,3],[4]], [[2,1],[2,1]])
            [[1, 1, 3], [2, 3], [4]]
        """
        if isinstance(t, cls):
            return t
        tab = SemistandardTableau(list(t))
        shape = tab.shape()
        return LittlewoodRichardsonTableaux(shape, weight)(t)
예제 #3
0
    def to_semistandard_tableau(self):
        """
        Return the semistandard tableau corresponding the monotone triangle
        corresponding to ``self``.

        EXAMPLES::

            sage: A = AlternatingSignMatrices(3)
            sage: A([[0,0,1],[1,0,0],[0,1,0]]).to_semistandard_tableau()
            [[1, 1, 3], [2, 3], [3]]
            sage: t = A([[0,1,0],[1,-1,1],[0,1,0]]).to_semistandard_tableau(); t
            [[1, 1, 2], [2, 3], [3]]
            sage: parent(t)
            Semistandard tableaux
            """
        from sage.combinat.tableau import SemistandardTableau, SemistandardTableaux
        mt = self.to_monotone_triangle()
        ssyt = [[0]*(len(mt) - j) for j in range(len(mt))]
        for i in range(len(mt)):
            for j in range(len(mt[i])):
                ssyt[i][j] = mt[j][-(i+1)]
        return SemistandardTableau(ssyt)
예제 #4
0
def hecke_insertion(obj1, obj2=None):
    """
    Return the Hecke insertion of the pair ``[obj1, obj2]``.

    .. SEEALSO::

        :func:`RSK`

    EXAMPLES::

        sage: w = [5, 4, 1, 3, 4, 2, 5, 1, 2, 1, 4, 2, 4]
        sage: RSK(w, insertion='hecke')
        [[[1, 2, 4, 5], [2, 4, 5], [3, 5], [4], [5]],
         [[(1,), (4,), (5,), (7,)],
          [(2,), (9,), (11, 13)],
          [(3,), (12,)],
          [(6,)],
          [(8, 10)]]]
    """
    if obj2 is None:
        obj2 = obj1
        obj1 = range(1,len(obj2)+1)

    from sage.combinat.tableau import SemistandardTableau, Tableau
    from bisect import bisect_right
    p = []       #the "insertion" tableau
    q = []       #the "recording" tableau

    for i, x in izip(obj1, obj2):
        for j,r in enumerate(p):
            if r[-1] > x:
                #Figure out where to insert x into the row r.  The
                #bisect command returns the position of the least
                #element of r greater than x.  We will call it y.
                y_pos = bisect_right(r, x)
                y = r[y_pos]
                # Check to see if we can swap x for y
                if (y_pos == 0 or r[y_pos-1] < x) and (j == 0 or p[j-1][y_pos] < x):
                    r[y_pos] = x
                x = y
            else:
                # We must have len(p[j-1]) > len(r), since x is coming
                # from the previous row.
                if r[-1] < x and (j == 0 or p[j-1][len(r)] < x):
                    # We can add a box to the row
                    r.append(x)
                    q[j].append((i,)) # Values are always inserted to the right
                else:
                    # We must append i to the bottom of this column
                    l = len(r) - 1
                    while j < len(q) and len(q[j]) > l:
                        j += 1
                    q[j-1][-1] = q[j-1][-1] + (i,)
                break
        else:
            #We made through all of the rows of p without breaking
            #so we need to add a new row to p and q.
            p.append([x])
            q.append([(i,)])

    return [SemistandardTableau(p), Tableau(q)]
예제 #5
0
def RSK(obj1=None, obj2=None, insertion='RSK', check_standard=False, **options):
    r"""
    Perform the Robinson-Schensted-Knuth (RSK) correspondence.

    The Robinson-Schensted-Knuth (RSK) correspondence (also known
    as the RSK algorithm) is most naturally stated as a bijection
    between generalized permutations (also known as two-line arrays,
    biwords, ...) and pairs of semi-standard Young tableaux `(P, Q)`
    of identical shape. The tableau `P` is known as the insertion
    tableau, and `Q` is known as the recording tableau.

    The basic operation is known as row insertion `P \leftarrow k`
    (where `P` is a given semi-standard Young tableau, and `k` is an
    integer). Row insertion is a recursive algorithm which starts by
    setting `k_0 = k`, and in its `i`-th step inserts the number `k_i`
    into the `i`-th row of `P` (we start counting the rows at `0`) by
    replacing the first integer greater than `k_i` in the row by `k_i`
    and defines `k_{i+1}` as the integer that has been replaced. If no
    integer greater than `k_i` exists in the `i`-th row, then `k_i` is
    simply appended to the row and the algorithm terminates at this
    point.

    Now the RSK algorithm, applied to a generalized permutation
    `p = ((j_0, k_0), (j_1, k_1), \ldots, (j_{\ell-1}, k_{\ell-1}))`
    (encoded as a lexicographically sorted list of pairs) starts by
    initializing two semi-standard tableaux `P_0` and `Q_0` as empty
    tableaux. For each nonnegative integer `t` starting at `0`, take
    the pair `(j_t, k_t)` from `p` and set
    `P_{t+1} = P_t \leftarrow k_t`, and define `Q_{t+1}` by adding a
    new box filled with `j_t` to the tableau `Q_t` at the same
    location the row insertion on `P_t` ended (that is to say, adding
    a new box with entry `j_t` such that `P_{t+1}` and `Q_{t+1}` have
    the same shape). The iterative process stops when `t` reaches the
    size of `p`, and the pair `(P_t, Q_t)` at this point is the image
    of `p` under the Robinson-Schensted-Knuth correspondence.

    This correspondence has been introduced in [Knu1970]_, where it has
    been referred to as "Construction A".

    For more information, see Chapter 7 in [Sta-EC2]_.

    We also note that integer matrices are in bijection with generalized
    permutations. Furthermore, we can convert any word `w` (and, in
    particular, any permutation) to a generalized permutation by
    considering the top line to be `(1, 2, \ldots, n)` where `n` is the
    length of `w`.

    The optional argument ``insertion`` allows to specify an alternative
    insertion procedure to be used instead of the standard
    Robinson-Schensted-Knuth insertion. If the input is a reduced word of
    a permutation (i.e., an element of a type-`A` Coxeter group), one can
    set ``insertion`` to ``'EG'``, which gives Edelman-Greene insertion,
    an algorithm defined in [EG1987]_ Definition 6.20 (where it is
    referred to as Coxeter-Knuth insertion). The Edelman-Greene insertion
    is similar to the standard row insertion except that if `k_i` and
    `k_i + 1` both exist in row `i`, we *only* set `k_{i+1} = k_i + 1` and
    continue.

    One can also perform a "Hecke RSK algorithm", defined using the
    Hecke insertion studied in [BKSTY06]_ (but using rows instead of
    columns). The algorithm proceeds similarly to the classical RSK
    algorithm. However, it is not clear in what generality it works;
    thus, following [BKSTY06]_, we shall assume that our biword `p`
    has top line `(1, 2, \ldots, n)` (or, at least, has its top line
    strictly increasing). The Hecke RSK algorithm returns a pair of
    an increasing tableau and a set-valued standard tableau. If
    `p = ((j_0, k_0), (j_1, k_1), \ldots, (j_{\ell-1}, k_{\ell-1}))`,
    then the algorithm recursively constructs pairs
    `(P_0, Q_0), (P_1, Q_1), \ldots, (P_\ell, Q_\ell)` of tableaux.
    The construction of `P_{t+1}` and `Q_{t+1}` from `P_t`, `Q_t`,
    `j_t` and `k_t` proceeds as follows: Set `i = j_t`, `x = k_t`,
    `P = P_t` and `Q = Q_t`. We are going to insert `x` into the
    increasing tableau `P` and update the set-valued "recording
    tableau" `Q` accordingly. As in the classical RSK algorithm, we
    first insert `x` into row `1` of `P`, then into row `2` of the
    resulting tableau, and so on, until the construction terminates.
    The details are different: Suppose we are inserting `x` into
    row `R` of `P`. If (Case 1) there exists an entry `y` in row `R`
    such that `x < y`, then let `y` be the minimal such entry. We
    replace this entry `y` with `x` if the result is still an
    increasing tableau; in either subcase, we then continue
    recursively, inserting `y` into the next row of `P`.
    If, on the other hand, (Case 2) no such `y` exists, then we
    append `x` to the end of `R` if the result is an increasing
    tableau (Subcase 2.1), and otherwise (Subcase 2.2) do nothing.
    Furthermore, in Subcase 2.1, we add the box that we have just
    filled with `x` in `P` to the shape of `Q`, and fill it with
    the one-element set `\{i\}`. In Subcase 2.2, we find the
    bottommost box of the column containing the rightmost box of
    row `R`, and add `i` to the entry of `Q` in this box (this
    entry is a set, since `Q` is a set-valued). In either
    subcase, we terminate the recursion, and set
    `P_{t+1} = P` and `Q_{t+1} = Q`.

    Notice that set-valued tableaux are encoded as tableaux whose
    entries are tuples of positive integers; each such tuple is strictly
    increasing and encodes a set (namely, the set of its entries).

    INPUT:

    - ``obj1, obj2`` -- Can be one of the following:

      - A word in an ordered alphabet
      - An integer matrix
      - Two lists of equal length representing a generalized permutation
      - Any object which has a method ``_rsk_iter()`` which returns an
        iterator over the object represented as generalized permutation or
        a pair of lists.

    - ``insertion`` -- (Default: ``'RSK'``) The following types of insertion
      are currently supported:

      - ``'RSK'`` -- Robinson-Schensted-Knuth
      - ``'EG'`` -- Edelman-Greene (only for reduced words of
        permutations/elements of a type-`A` Coxeter group)
      - ``'hecke'`` -- Hecke insertion (only guaranteed for
        generalized permutations whose top row is strictly increasing)

    - ``check_standard`` -- (Default: ``False``) Check if either of the
      resulting tableaux is a standard tableau, and if so, typecast it
      as such

    EXAMPLES:

    If we only give one line, we treat the top line as being
    `(1, 2, \ldots, n)`::

        sage: RSK([3,3,2,4,1])
        [[[1, 3, 4], [2], [3]], [[1, 2, 4], [3], [5]]]
        sage: RSK(Word([3,3,2,4,1]))
        [[[1, 3, 4], [2], [3]], [[1, 2, 4], [3], [5]]]
        sage: RSK(Word([2,3,3,2,1,3,2,3]))
        [[[1, 2, 2, 3, 3], [2, 3], [3]], [[1, 2, 3, 6, 8], [4, 7], [5]]]

    With a generalized permutation::

        sage: RSK([1, 2, 2, 2], [2, 1, 1, 2])
        [[[1, 1, 2], [2]], [[1, 2, 2], [2]]]
        sage: RSK(Word([1,1,3,4,4]), [1,4,2,1,3])
        [[[1, 1, 3], [2], [4]], [[1, 1, 4], [3], [4]]]
        sage: RSK([1,3,3,4,4], Word([6,2,2,1,7]))
        [[[1, 2, 7], [2], [6]], [[1, 3, 4], [3], [4]]]

    If we give it a matrix::

        sage: RSK(matrix([[0,1],[2,1]]))
        [[[1, 1, 2], [2]], [[1, 2, 2], [2]]]

    We can also give it something looking like a matrix::

        sage: RSK([[0,1],[2,1]])
        [[[1, 1, 2], [2]], [[1, 2, 2], [2]]]

    There are also variations of the insertion algorithm in RSK.
    Here we consider Edelman-Greene insertion::

        sage: RSK([2,1,2,3,2], insertion='EG')
        [[[1, 2, 3], [2, 3]], [[1, 3, 4], [2, 5]]]

    We reproduce figure 6.4 in [EG1987]_::

        sage: RSK([2,3,2,1,2,3], insertion='EG')
        [[[1, 2, 3], [2, 3], [3]], [[1, 2, 6], [3, 5], [4]]]

    Hecke insertion is also supported. We construct Example 2.1
    in :arxiv:`0801.1319v2`::

        sage: w = [5, 4, 1, 3, 4, 2, 5, 1, 2, 1, 4, 2, 4]
        sage: RSK(w, insertion='hecke')
        [[[1, 2, 4, 5], [2, 4, 5], [3, 5], [4], [5]],
         [[(1,), (4,), (5,), (7,)],
          [(2,), (9,), (11, 13)],
          [(3,), (12,)],
          [(6,)],
          [(8, 10)]]]

    There is also :func:`~sage.combinat.rsk.RSK_inverse` which performs
    the inverse of the bijection on a pair of semistandard tableaux. We
    note that the inverse function takes 2 separate tableaux as inputs, so
    to compose with :func:`~sage.combinat.rsk.RSK`, we need to use the
    python ``*`` on the output::

        sage: RSK_inverse(*RSK([1, 2, 2, 2], [2, 1, 1, 2]))
        [[1, 2, 2, 2], [2, 1, 1, 2]]
        sage: P,Q = RSK([1, 2, 2, 2], [2, 1, 1, 2])
        sage: RSK_inverse(P, Q)
        [[1, 2, 2, 2], [2, 1, 1, 2]]

    TESTS:

    Empty objects::

        sage: RSK(Permutation([]))
        [[], []]
        sage: RSK(Word([]))
        [[], []]
        sage: RSK(matrix([[]]))
        [[], []]
        sage: RSK([], [])
        [[], []]
        sage: RSK([[]])
        [[], []]
        sage: RSK(Word([]), insertion='EG')
        [[], []]
        sage: RSK(Word([]), insertion='hecke')
        [[], []]
    """
    from sage.combinat.tableau import SemistandardTableau, StandardTableau

    if insertion == 'hecke':
        return hecke_insertion(obj1, obj2)

    if obj1 is None and obj2 is None:
        if 'matrix' in options:
            obj1 = matrix(options['matrix'])
        else:
            raise ValueError("invalid input")

    if is_Matrix(obj1):
        obj1 = obj1.rows()
    if len(obj1) == 0:
        return [StandardTableau([]), StandardTableau([])]

    if obj2 is None:
        try:
            itr = obj1._rsk_iter()
        except AttributeError:
            # If this is (something which looks like) a matrix
            #   then build the generalized permutation
            try:
                t = []
                b = []
                for i, row in enumerate(obj1):
                    for j, mult in enumerate(row):
                        if mult > 0:
                            t.extend([i+1]*mult)
                            b.extend([j+1]*mult)
                itr = izip(t, b)
            except TypeError:
                itr = izip(range(1, len(obj1)+1), obj1)
    else:
        if len(obj1) != len(obj2):
            raise ValueError("the two arrays must be the same length")
        # Check it is a generalized permutation
        lt = 0
        lb = 0
        for t,b in izip(obj1, obj2):
            if t < lt or (lt == t and b < lb):
                raise ValueError("invalid generalized permutation")
            lt = t
            lb = b
        itr = izip(obj1, obj2)

    from bisect import bisect_right
    p = []       #the "insertion" tableau
    q = []       #the "recording" tableau

    use_EG = (insertion == 'EG')

    #For each x in self, insert x into the tableau p.
    lt = 0
    lb = 0
    for i, x in itr:
        for r, qr in izip(p,q):
            if r[-1] > x:
                #Figure out where to insert x into the row r.  The
                #bisect command returns the position of the least
                #element of r greater than x.  We will call it y.
                y_pos = bisect_right(r, x)
                if use_EG and r[y_pos] == x + 1 and y_pos > 0 and x == r[y_pos - 1]:
                    #Special bump: Nothing to do except increment x by 1
                    x += 1
                else:
                    #Switch x and y
                    x, r[y_pos] = r[y_pos], x
            else:
                break
        else:
            #We made through all of the rows of p without breaking
            #so we need to add a new row to p and q.
            r = []; p.append(r)
            qr = []; q.append(qr)

        r.append(x)
        qr.append(i) # Values are always inserted to the right

    if check_standard:
        try:
            P = StandardTableau(p)
        except ValueError:
            P = SemistandardTableau(p)
        try:
            Q = StandardTableau(q)
        except ValueError:
            Q = SemistandardTableau(q)
        return [P, Q]
    return [SemistandardTableau(p), SemistandardTableau(q)]
예제 #6
0
 def to_tableaux(self):
     return SemistandardTableau(
         [row.to_list() for row in self.rows()[::-1]])
예제 #7
0
파일: rsk.py 프로젝트: sagemathinc/smc-sage
def RSK(obj1=None,
        obj2=None,
        insertion='RSK',
        check_standard=False,
        **options):
    r"""
    Perform the Robinson-Schensted-Knuth (RSK) correspondence.

    The Robinson-Schensted-Knuth (RSK) correspondence is most naturally stated
    as a bijection between generalized permutations (also known as two-line
    arrays, biwords, ...) and pairs of semi-standard Young tableaux `(P, Q)`
    of identical shape. The tableau `P` is known as the insertion tableau and
    `Q` is known as the recording tableau.

    The basic operation is known as row insertion `P \leftarrow k` (where `P`
    is a given semi-standard Young tableau, and `k` is an integer). Row
    insertion is a recursive algorithm which starts by setting `k_0 = k`,
    and in its `i`-th step inserts the number `k_i` into the `i`-th row of
    `P` by replacing the first integer greater than `k_i` in the row by `k_i`
    and defines `k_{i+1}` as the integer that has been replaced. If no integer
    greater than `k_i` exists in the `i`-th row, then `k_i` is simply appended
    to the row and the algorithm terminates at this point.

    Now the RSK algorithm starts by initializing two semi-standard tableaux
    `P_0` and `Q_0` as empty tableaux. For each nonnegative integer `t`
    starting at `0`, take the pair `(j_t, k_t)` from `p` and set
    `P_{t+1} = P_t \leftarrow k_t`, and define `Q_{t+1}` by adding a new box
    filled with `j_t` to the tableau `Q_t` at the same location the row
    insertion on `P_t` ended (that is to say, adding `j_t` such that
    `P_{t+1}` and `Q_{t+1}` have the same shape). The iterative process stops
    when `t` reaches the size of `p`, and the pair `(P_t, Q_t)` at this point
    is the image of `p` under the Robinson-Schensted-Knuth correspondence.

    This correspondence has been introduced in [Knu1970]_, where it has been
    referred to as "Construction A".

    For more information, see Chapter 7 in [Sta-EC2]_.

    We also note that integer matrices are in bijection with generalized
    permutations. In addition, we can also convert any word `w` (and any
    permutation) to a generalized permutation by considering the top line
    to be `(1, 2, \ldots, n)` where `n` is the length of `w`.

    The optional argument ``insertion`` allows to specify an alternative
    insertion procedure to be used instead of the standard
    Robinson-Schensted-Knuth insertion. If the input is a reduced word of
    a permutation (i.e., a type `A` Coxeter element), one can set
    ``insertion`` to ``'EG'``, which gives Edelman-Greene insertion, an
    algorithm defined in [EG1987]_ Definition 6.20 (where it is referred
    to as Coxeter-Knuth insertion). The Edelman-Greene insertion is similar
    to the standard row insertion except that if `k_i` and `k_i + 1` both
    exist in row `i`, we *only* set `k_{i+1} = k_i + 1` and continue.

    INPUT:

    - ``obj1, obj2`` -- Can be one of the following:

      - A word in an ordered alphabet
      - An integer matrix
      - Two lists of equal length representing a generalized permutation
      - Any object which has a method ``_rsk_iter()`` which returns an iterator
        over the object represented as generalized permutation or a pair of
        lists.

    - ``insertion`` -- (Default: ``'RSK'``) The following types of insertion
      are currently supported:

      - ``'RSK'`` -- Robinson-Schensted-Knuth
      - ``'EG'`` -- Edelman-Greene (only for reduced words of
        permutations/type `A` Coxeter elements)

    - ``check_standard`` -- (Default: ``False``) Check if either of the resulting
      tableaux should be standard tableau.

    EXAMPLES:

    If we only give one line, we treat the top line as being
    `(1, 2, \ldots, n)`::

        sage: RSK([3,3,2,4,1])
        [[[1, 3, 4], [2], [3]], [[1, 2, 4], [3], [5]]]
        sage: RSK(Word([3,3,2,4,1]))
        [[[1, 3, 4], [2], [3]], [[1, 2, 4], [3], [5]]]
        sage: RSK(Word([2,3,3,2,1,3,2,3]))
        [[[1, 2, 2, 3, 3], [2, 3], [3]], [[1, 2, 3, 6, 8], [4, 7], [5]]]

    With a generalized permutation::

        sage: RSK([1, 2, 2, 2], [2, 1, 1, 2])
        [[[1, 1, 2], [2]], [[1, 2, 2], [2]]]
        sage: RSK(Word([1,1,3,4,4]), [1,4,2,1,3])
        [[[1, 1, 3], [2], [4]], [[1, 1, 4], [3], [4]]]
        sage: RSK([1,3,3,4,4], Word([6,2,2,1,7]))
        [[[1, 2, 7], [2], [6]], [[1, 3, 4], [3], [4]]]

    If we give it a matrix::

        sage: RSK(matrix([[0,1],[2,1]]))
        [[[1, 1, 2], [2]], [[1, 2, 2], [2]]]

    We can also give it something looking like a matrix::

        sage: RSK([[0,1],[2,1]])
        [[[1, 1, 2], [2]], [[1, 2, 2], [2]]]

    There are also variations of the insertion algorithm in RSK, and currently
    only Edelman-Greene insertion is supported::

        sage: RSK([2,1,2,3,2], insertion='EG')
        [[[1, 2, 3], [2, 3]], [[1, 3, 4], [2, 5]]]

    We reproduce figure 6.4 in [EG1987]_::

        sage: RSK([2,3,2,1,2,3], insertion='EG')
        [[[1, 2, 3], [2, 3], [3]], [[1, 2, 6], [3, 5], [4]]]

    There is also :func:`~sage.combinat.rsk.RSK_inverse` which performs the
    inverse of the bijection on a pair of semistandard tableaux. We note
    that the inverse function takes 2 separate tableaux inputs, so to compose
    with :func:`~sage.combinat.rsk.RSK`, we need to use the python ``*`` on
    the output::

        sage: RSK_inverse(*RSK([1, 2, 2, 2], [2, 1, 1, 2]))
        [[1, 2, 2, 2], [2, 1, 1, 2]]
        sage: P,Q = RSK([1, 2, 2, 2], [2, 1, 1, 2])
        sage: RSK_inverse(P, Q)
        [[1, 2, 2, 2], [2, 1, 1, 2]]

    TESTS:

    Empty objects::

        sage: RSK(Permutation([]))
        [[], []]
        sage: RSK(Word([]))
        [[], []]
        sage: RSK(matrix([[]]))
        [[], []]
        sage: RSK([], [])
        [[], []]
        sage: RSK([[]])
        [[], []]
        sage: RSK(Word([]), insertion='EG')
        [[], []]
    """
    from sage.combinat.tableau import SemistandardTableau, StandardTableau

    if obj1 is None and obj2 is None:
        if 'matrix' in options:
            obj1 = matrix(options['matrix'])
        else:
            raise ValueError("Invalid input")

    if is_Matrix(obj1):
        obj1 = obj1.rows()
    if len(obj1) == 0:
        return [StandardTableau([]), StandardTableau([])]

    if obj2 is None:
        try:
            itr = obj1._rsk_iter()
        except AttributeError:
            # If this is (something which looks like) a matrix
            #   then build the generalized permutation
            try:
                t = []
                b = []
                for i, row in enumerate(obj1):
                    for j, mult in enumerate(row):
                        if mult > 0:
                            t.extend([i + 1] * mult)
                            b.extend([j + 1] * mult)
                itr = izip(t, b)
            except TypeError:
                itr = izip(range(1, len(obj1) + 1), obj1)
    else:
        if len(obj1) != len(obj2):
            raise ValueError("The two arrays must be the same length")
        # Check it is a generalized permutation
        lt = 0
        lb = 0
        for t, b in izip(obj1, obj2):
            if t < lt or (lt == t and b < lb):
                raise ValueError("Invalid generalized permutation")
            lt = t
            lb = b
        itr = izip(obj1, obj2)

    from bisect import bisect_right
    p = []  #the "insertion" tableau
    q = []  #the "recording" tableau

    use_EG = (insertion == 'EG')

    #For each x in self, insert x into the tableau p.
    lt = 0
    lb = 0
    for i, x in itr:
        for r, qr in izip(p, q):
            if r[-1] > x:
                #Figure out where to insert x into the row r.  The
                #bisect command returns the position of the least
                #element of r greater than x.  We will call it y.
                y_pos = bisect_right(r, x)
                if use_EG and r[y_pos] == x + 1 and y_pos > 0 and x == r[y_pos
                                                                         - 1]:
                    #Special bump: Nothing to do except increment x by 1
                    x += 1
                else:
                    #Switch x and y
                    x, r[y_pos] = r[y_pos], x
            else:
                break
        else:
            #We made through all of the rows of p without breaking
            #so we need to add a new row to p and q.
            r = []
            p.append(r)
            qr = []
            q.append(qr)

        r.append(x)
        qr.append(i)  # Values are always inserted to the right

    if check_standard:
        try:
            P = StandardTableau(p)
        except ValueError:
            P = SemistandardTableau(p)
        try:
            Q = StandardTableau(q)
        except ValueError:
            Q = SemistandardTableau(q)
        return [P, Q]
    return [SemistandardTableau(p), SemistandardTableau(q)]