Ticket #7492: trac_7492.patch

File trac_7492.patch, 8.8 KB (added by ncohen, 11 years ago)
  • sage/combinat/permutation.py

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1258735152 -3600
    # Node ID 0e61ef223c1f993feed01244af555decccebebe6
    # Parent  e67e994beb2a53a181961c89aa74c522363e823e
    function Permutation.bistochastic_as_sum_of_permutations
    
    diff -r e67e994beb2a -r 0e61ef223c1f sage/combinat/permutation.py
    a b  
    34713471
    34723472    return Permutation(p)
    34733473
     3474
    34743475def robinson_schensted_inverse(p, q):
    34753476    r"""
    34763477    Returns the permutation corresponding to the pair of tableaux `(p,q)`
     
    35573558        permutation.append(x)
    35583559    return Permutation(reversed(permutation))
    35593560
     3561def bistochastic_as_sum_of_permutations(M, check = True):
     3562    r"""
     3563    Returns the positive sum of permutations corresponding to
     3564    the bistochastic matrix.
     3565
     3566    A stochastic matrix is a matrix such that the sum of the elements
     3567    of any row is equal to 1. A bistochastic matrix is a stochastic matrix
     3568    whose transpose matrix is also stochastic ( there are conditions
     3569    both on the rows and on the columns ).
     3570
     3571    According to the Birkhoff-von Neumann Theorem, any bistochastic matrix
     3572    can be written as a positive sum of permutation matrices, which also
     3573    means that the polytope of bistochastic matrices is integer.
     3574
     3575    As a non-bistochastic matrix can obviously not be written as a sum of
     3576    permutations, this theorem is an equivalence.
     3577
     3578    This function, given a bistochastic matrix, returns the corresponding
     3579    decomposition.
     3580
     3581    INPUT:
     3582
     3583    - ``M`` -- A bistochastic matrix
     3584
     3585    - ``check`` (boolean) -- set to ``True`` (default) to checl
     3586      that the matrix is indeed bistochastic
     3587
     3588    OUTPUT:
     3589
     3590    - An element of ``CombinatorialFreeModule``, which is a free `F`-module
     3591      ( where `F` is the ground ring of the given matrix ) whose basis is
     3592      indexed by the permutations.
     3593
     3594    .. NOTE::
     3595
     3596        - In this function, we just assume 1 to be any constant : for us a matrix M
     3597          is bistochastic if there exists `c>0` such that `M/c` is bistochastic.
     3598
     3599        - You can obtain a sequence of pairs ``(permutation,coeff)``, where
     3600          ``permutation` is a Sage ``Permutation`` instance, and ``coeff``
     3601          its corresponding coefficient from the result of this function
     3602          by applying the ``list`` function.
     3603
     3604        - If you are interested in the matrix corresponding to a ``Permutation``
     3605          you will be glad to learn about the ``Permutation.to_matrix()`` method.
     3606
     3607        - The base ring of the matrix can be anything that can be coerced to ``RR``.
     3608
     3609    .. SEEALSO:
     3610
     3611    - :meth:`as_sum_of_permutations <sage.matrix.matrix2.as_sum_of_permutations>`
     3612      -- to use this method through the ``Matrix`` class.
     3613
     3614    EXAMPLE:
     3615
     3616    We create a bistochastic matrix from a convex sum of permutations, then
     3617    try to deduce the decomposition from the matrix ::
     3618
     3619
     3620        sage: from sage.combinat.permutation import bistochastic_as_sum_of_permutations
     3621        sage: L = []
     3622        sage: L.append((9,Permutation([4, 1, 3, 5, 2])))
     3623        sage: L.append((6,Permutation([5, 3, 4, 1, 2])))
     3624        sage: L.append((3,Permutation([3, 1, 4, 2, 5])))
     3625        sage: L.append((2,Permutation([1, 4, 2, 3, 5])))
     3626        sage: M = sum([c * p.to_matrix() for (c,p) in L])
     3627        sage: decomp = bistochastic_as_sum_of_permutations(M)
     3628        sage: print decomp
     3629        2*B[[1, 4, 2, 3, 5]] + 3*B[[3, 1, 4, 2, 5]] + 9*B[[4, 1, 3, 5, 2]] + 6*B[[5, 3, 4, 1, 2]]
     3630
     3631    An exception is raised when the matrix is not bistochastic::
     3632
     3633        sage: M = Matrix([[2,3],[2,2]])
     3634        sage: decomp = bistochastic_as_sum_of_permutations(M)
     3635        Traceback (most recent call last):
     3636        ...
     3637        ValueError: The matrix is not bistochastic
     3638    """
     3639
     3640    from sage.graphs.bipartite_graph import BipartiteGraph
     3641    from sage.combinat.free_module import CombinatorialFreeModule
     3642    from sage.rings.real_mpfr import RR
     3643
     3644    n=M.nrows()
     3645
     3646    if n != M.ncols():
     3647        raise ValueError("The matrix is expected to be square")
     3648
     3649    if check and not M.is_bistochastic(normalized = False):
     3650        raise ValueError("The matrix is not bistochastic")
     3651
     3652    if not RR.has_coerce_map_from(M.base_ring()):
     3653        raise ValueError("The base ring of the matrix must have a coercion map to RR")
     3654
     3655    CFM=CombinatorialFreeModule(M.base_ring(),Permutations(n))
     3656    value=0
     3657
     3658    G = BipartiteGraph(M,weighted=True)
     3659
     3660    while G.size() > 0:
     3661        matching = G.matching(use_edge_labels=True)
     3662
     3663        # This minimum is strictly larger than 0
     3664        minimum = min([x[2] for x in matching])
     3665
     3666        for (u,v,l) in matching:
     3667            if minimum == l:
     3668                G.delete_edge((u,v,l))
     3669            else:
     3670                G.set_edge_label(u,v,l-minimum)
     3671           
     3672        matching.sort(key=lambda x: x[0])
     3673        value+=minimum*CFM(Permutation([x[1]-n+1 for x in matching]))
     3674
     3675    return value
     3676       
    35603677class StandardPermutations_descents(CombinatorialClass):
    35613678    def __init__(self, d, n):
    35623679        """
  • sage/matrix/matrix2.pyx

    diff -r e67e994beb2a -r 0e61ef223c1f sage/matrix/matrix2.pyx
    a b  
    51245124                        return False
    51255125        return True
    51265126
     5127    def is_bistochastic(self, normalized = True):
     5128        r"""
     5129        Returns ``True`` if this matrix is bistochastic.
     5130
     5131        A matrix is said to be bistochastic if both the sums of the
     5132        entries of each row and the sum of the entries of each column
     5133        are equal to 1.
     5134
     5135        INPUT:
     5136
     5137        - ``normalized`` -- if set to ``True`` (default), checks that
     5138          the sums are equal to 1. When set to ``False``, checks that
     5139          the row sums and column sums are all equal to some constant
     5140          possibly different from 1.
     5141
     5142        EXAMPLES:
     5143
     5144        The identity matrix is clearly bistochastic::
     5145
     5146            sage: Matrix(5,5,1).is_bistochastic()
     5147            True
     5148
     5149        The same matrix, multiplied by 2, is not bistochastic anymore,
     5150        though is verifies the constraints of ``normalized == False``::
     5151
     5152            sage: (2 * Matrix(5,5,1)).is_bistochastic()
     5153            False
     5154            sage: (2 * Matrix(5,5,1)).is_bistochastic(normalized = False)
     5155            True
     5156        """
     5157
     5158        row_sums = map(sum, self.rows())
     5159        col_sums = map(sum, self.columns())
     5160
     5161        return self.is_square() and\
     5162                col_sums[0] == row_sums[0] and\
     5163                row_sums == col_sums and\
     5164                row_sums == len(row_sums) * [col_sums[0]] and\
     5165                ((not normalized) or col_sums[0] == self.base_ring()(1))
     5166
     5167    def as_sum_of_permutations(self):
     5168        r"""
     5169        Returns the current matrix as a sum of permutation matrices
     5170
     5171        According to the Birkhoff-von Neumann Theorem, any bistochastic matrix
     5172        can be written as a positive sum of permutation matrices, which also
     5173        means that the polytope of bistochastic matrices is integer.
     5174
     5175        As a non-bistochastic matrix can obviously not be written as a sum of
     5176        permutations, this theorem is an equivalence.
     5177
     5178        This function, given a bistochastic matrix, returns the corresponding
     5179        decomposition.
     5180
     5181        .. SEEALSO:
     5182
     5183        - :meth:`bistochastic_as_sum_of_permutations <sage.combinat.permutation.bistochastic_as_sum_of_permutations>`
     5184          -- for more information on this method.
     5185
     5186        EXAMPLE:
     5187         
     5188        We create a bistochastic matrix from a convex sum of permutations, then
     5189        try to deduce the decomposition from the matrix ::
     5190
     5191            sage: L = []
     5192            sage: L.append((9,Permutation([4, 1, 3, 5, 2])))
     5193            sage: L.append((6,Permutation([5, 3, 4, 1, 2])))
     5194            sage: L.append((3,Permutation([3, 1, 4, 2, 5])))
     5195            sage: L.append((2,Permutation([1, 4, 2, 3, 5])))
     5196            sage: M = sum([c * p.to_matrix() for (c,p) in L])
     5197            sage: decomp = sage.combinat.permutation.bistochastic_as_sum_of_permutations(M)
     5198            sage: print decomp
     5199            2*B[[1, 4, 2, 3, 5]] + 3*B[[3, 1, 4, 2, 5]] + 9*B[[4, 1, 3, 5, 2]] + 6*B[[5, 3, 4, 1, 2]]
     5200
     5201        An exception is raised when the matrix is not bistochastic::
     5202
     5203            sage: M = Matrix([[2,3],[2,2]])
     5204            sage: decomp = sage.combinat.permutation.bistochastic_as_sum_of_permutations(M)
     5205            Traceback (most recent call last):
     5206            ...
     5207            ValueError: The matrix is not bistochastic
     5208        """
     5209
     5210        from sage.combinat.permutation import bistochastic_as_sum_of_permutations
     5211        return bistochastic_as_sum_of_permutations(self)
     5212
     5213
    51275214    def visualize_structure(self, filename=None, maxsize=512):
    51285215        """
    51295216        Write a PNG image to 'filename' which visualizes self by putting