Ticket #14099: poset_functionality_14099-er.patch

File poset_functionality_14099-er.patch, 6.3 KB (added by rowland, 8 years ago)
  • sage/combinat/posets/posets.py

    # HG changeset patch
    # User Eric Rowland <rowland at lacim.ca>
    # Date 1371741228 -7200
    # Node ID 1d5a2c317046573fc37b0824b7ccadb3542a8aff
    # Parent  18a07180e9a453c2db9e6520c2d60e5e4d8ac955
    #14099: Method for testing (m+n)-freeness in poset
    
    diff --git a/sage/combinat/posets/posets.py b/sage/combinat/posets/posets.py
    a b This module implements finite partialy o 
    5353    :meth:`~FinitePoset.is_linear_extension` | Returns whether ``l`` is a linear extension of ``self``
    5454    :meth:`~FinitePoset.is_meet_semilattice` | Returns True if self has a meet operation, and False otherwise.
    5555    :meth:`~FinitePoset.join_matrix` | Returns a matrix whose ``(i,j)`` entry is ``k``, where ``self.linear_extension()[k]`` is the join (least upper bound) of ``self.linear_extension()[i]`` and ``self.linear_extension()[j]``.
     56    :meth:`~FinitePoset.is_incomparable_chain_free` | Returns whether the poset is `(m+n)`-free.
    5657    :meth:`~FinitePoset.is_ranked` | Returns whether this poset is ranked.
    5758    :meth:`~FinitePoset.is_slender` | Returns whether the poset ``self`` is slender or not.
    5859    :meth:`~FinitePoset.lequal_matrix` | Computes the matrix whose ``(i,j)`` entry is 1 if ``self.linear_extension()[i] < self.linear_extension()[j]`` and 0 otherwise
    from sage.structure.parent import Parent 
    124125from sage.rings.integer import Integer
    125126from sage.rings.integer_ring import ZZ
    126127from sage.graphs.digraph import DiGraph
     128from sage.graphs.digraph_generators import digraphs
    127129from sage.combinat.posets.hasse_diagram import HasseDiagram
    128130from sage.combinat.posets.elements import PosetElement
    129131
    class FinitePoset(UniqueRepresentation,  
    15311533                if leq_mat[i,j]:
    15321534                    yield [elements[i], elements[j]]
    15331535
     1536    def is_incomparable_chain_free(self, m, n = None):
     1537        r"""
     1538        Returns ``True`` if the poset is `(m+n)`-free (that is, there is no pair
     1539        of incomparable chains of lengths `m` and `n`), and ``False`` if not.
     1540
     1541        If ``m`` is a tuple of pairs of chain lengths, returns ``True`` if the poset
     1542        does not contain a pair of incomparable chains whose lengths comprise
     1543        one of the chain pairs, and ``False`` if not.
     1544       
     1545        A poset is `(m+n)`-free if it contains no induced subposet that is
     1546        isomorphic to the poset consisting of two disjoint chains of lengths
     1547        `m` and `n`.  See, for example, Exercise 15 in Chapter 3 of
     1548        Stanley, *Enumerative Combinatorics, Volume 1*, 2nd edition.
     1549
     1550        INPUT:
     1551
     1552        - ``m`` - tuple of pairs of nonnegative integers
     1553        - ``m``, ``n`` - nonnegative integers
     1554
     1555        EXAMPLES::
     1556
     1557            sage: P = Poset({0:[2], 1:[2], 2:[3], 3:[4], 4:[]})
     1558            sage: P.is_incomparable_chain_free(1, 1)
     1559            False
     1560            sage: P.is_incomparable_chain_free(2, 1)
     1561            True
     1562
     1563        ::
     1564
     1565            sage: P = Poset(((0, 1, 2, 3, 4), ((0, 1), (1, 2), (0, 3), (4, 2))))
     1566            sage: P.is_incomparable_chain_free(((3, 1), (2, 2)))
     1567            True
     1568
     1569        ::
     1570
     1571            sage: P = Poset((("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"), (("d", "a"), ("e", "a"), ("f", "a"), ("g", "a"), ("h", "b"), ("f", "b"), ("h", "c"), ("g", "c"), ("h", "d"), ("i", "d"), ("h", "e"), ("i", "e"), ("j", "f"), ("i", "f"), ("j", "g"), ("i", "g"), ("j", "h"))))
     1572            sage: P.is_incomparable_chain_free(3, 1)
     1573            True
     1574            sage: P.is_incomparable_chain_free(2, 2)
     1575            False
     1576
     1577        ::
     1578
     1579            sage: [len([p for p in Posets(n) if p.is_incomparable_chain_free(((3, 1), (2, 2)))]) for n in range(6)]
     1580            [1, 1, 2, 5, 14, 42]
     1581
     1582        TESTS::
     1583
     1584            sage: Q = Poset({0:[2], 1:[2], 2:[3], 3:[4], 4:[]})
     1585            sage: Q.is_incomparable_chain_free(2, 20/10)
     1586            True
     1587            sage: Q.is_incomparable_chain_free(2, pi)
     1588            Traceback (most recent call last):
     1589            ...
     1590            TypeError: 2 and pi must be integers.
     1591            sage: Q.is_incomparable_chain_free(2, -1)
     1592            Traceback (most recent call last):
     1593            ...
     1594            ValueError: 2 and -1 must be nonnegative integers.
     1595            sage: P = Poset(((0, 1, 2, 3, 4), ((0, 1), (1, 2), (0, 3), (4, 2))))
     1596            sage: P.is_incomparable_chain_free((3, 1))
     1597            Traceback (most recent call last):
     1598            ...
     1599            TypeError: (3, 1) is not a tuple of tuples.
     1600            sage: P.is_incomparable_chain_free([3, 1], [2, 2])
     1601            Traceback (most recent call last):
     1602            ...
     1603            TypeError: [3, 1] and [2, 2] must be integers.
     1604            sage: P.is_incomparable_chain_free([[3, 1], [2, 2]])
     1605            True
     1606            sage: P.is_incomparable_chain_free(([3, 1], [2, 2]))
     1607            True
     1608            sage: P.is_incomparable_chain_free([3, 1], 2)
     1609            Traceback (most recent call last):
     1610            ...
     1611            TypeError: [3, 1] and 2 must be integers.
     1612            sage: P.is_incomparable_chain_free(([3, 1], [2, 2, 2]))
     1613            Traceback (most recent call last):
     1614            ...
     1615            ValueError: '([3, 1], [2, 2, 2])' is not a tuple of length-2 tuples.
     1616
     1617        AUTHOR:
     1618
     1619        - Eric Rowland (2013-05-28)
     1620        """
     1621        if n is None:
     1622            try:
     1623                chain_pairs = [tuple(chain_pair) for chain_pair in m]
     1624            except TypeError:
     1625                raise TypeError('%s is not a tuple of tuples.' % str(tuple(m)))
     1626            if not all(len(chain_pair) is 2 for chain_pair in chain_pairs):
     1627                raise ValueError('%r is not a tuple of length-2 tuples.' % str(tuple(m)))
     1628            return all(self.is_incomparable_chain_free(*chain_pair) for chain_pair in chain_pairs)
     1629        try:
     1630            m, n = Integer(m), Integer(n)
     1631        except TypeError:
     1632            raise TypeError('%s and %s must be integers.' % (m, n))
     1633        if m < 0 or n < 0:
     1634            raise ValueError("%s and %s must be nonnegative integers." % (m, n))
     1635        twochains = digraphs.TransitiveTournament(m) + digraphs.TransitiveTournament(n)
     1636        return self.hasse_diagram().transitive_closure().subgraph_search(twochains, induced = True) is None
     1637
    15341638    def is_lequal(self, x, y):
    15351639        """
    15361640        Returns ``True`` if `x` is less than or equal to `y` in the poset, and