Ticket #14099: poset_functionality_14099_er.patch

File poset_functionality_14099_er.patch, 5.8 KB (added by rowland, 8 years ago)
  • sage/combinat/posets/posets.py

    # HG changeset patch
    # User Eric Rowland <rowland at lacim.ca>
    # Date 1360638503 18000
    # Node ID 1ab2e5736a9e5a7a3fc023ffb29c12fc1269f055
    # Parent  ec1fb07db6e23f9fbd4c34f0d48198d08ec76473
    #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 from sage.structure.parent import Parent 
    121121from sage.rings.integer import Integer
    122122from sage.rings.integer_ring import ZZ
    123123from sage.graphs.digraph import DiGraph
     124from sage.graphs.digraph_generators import digraphs
    124125from sage.combinat.posets.hasse_diagram import HasseDiagram
    125126from sage.combinat.posets.elements import PosetElement
    126127
    class FinitePoset(UniqueRepresentation,  
    15141515                if leq_mat[i,j]:
    15151516                    yield [elements[i], elements[j]]
    15161517
     1518    def _is_m_plus_n_free(self, m, n):
     1519        r"""
     1520        Returns ``True`` if the poset is (m+n)-free (that is, there is no pair
     1521        of incomparable chains of lengths m and n), and ``False`` if not.
     1522
     1523        INPUT:
     1524
     1525        - ``m``, ``n`` - nonnegative integers
     1526
     1527        EXAMPLES::
     1528
     1529            sage: Q = Poset({0:[2], 1:[2], 2:[3], 3:[4], 4:[]})
     1530            sage: Q._is_m_plus_n_free(1, 1)
     1531            False
     1532            sage: Q._is_m_plus_n_free(2, 1)
     1533            True
     1534
     1535        TESTS::
     1536
     1537            sage: Q = Poset({0:[2], 1:[2], 2:[3], 3:[4], 4:[]})
     1538            sage: Q._is_m_plus_n_free(2, 20/10)
     1539            True
     1540            sage: Q._is_m_plus_n_free(2, pi)
     1541            Traceback (most recent call last):
     1542            ...
     1543            TypeError: pi is not an integer.
     1544            sage: Q._is_m_plus_n_free(2, -1)
     1545            Traceback (most recent call last):
     1546            ...
     1547            ValueError: -1 is not a nonnegative integer.
     1548        """
     1549        try:
     1550            m = Integer(m)
     1551        except TypeError:
     1552            raise TypeError('%s is not an integer.' % m)
     1553        try:
     1554            n = Integer(n)
     1555        except TypeError:
     1556            raise TypeError('%s is not an integer.' % n)
     1557        if m < 0:
     1558            raise ValueError('%s is not a nonnegative integer.' % m)
     1559        if n < 0:
     1560            raise ValueError('%s is not a nonnegative integer.' % n)
     1561        relations = self.relations()
     1562        g = DiGraph([rel for rel in relations if rel[0] != rel[1]])
     1563        g.add_vertices([rel[0] for rel in relations if rel[0] == rel[1]])
     1564        mchain = digraphs.Circuit(m+1)
     1565        mchain.delete_vertex(m)
     1566        nchain = digraphs.Circuit(n+1)
     1567        nchain.delete_vertex(n)
     1568        return g.transitive_closure().subgraph_search((mchain + nchain).transitive_closure(), induced = True) is None
     1569
     1570    def is_incomparable_chain_free(self, *chain_pairs):
     1571        r"""
     1572        Returns ``True`` if the poset does not contain a pair of incomparable chains
     1573        whose lengths comprise one of the ``chain_pairs``, and ``False`` if not.
     1574       
     1575        A poset is *``(m+n)``-free* if it contains no induced subposet that is
     1576        isomorphic to the poset consisting of two disjoint chains of lengths
     1577        ``m`` and ``n``.  See, for example, Exercise 15 in Chapter 3 of
     1578        [Stanley, Enumerative Combinatorics Volume 1, 2nd edition].
     1579
     1580        INPUT:
     1581
     1582        - ``*chain_pairs`` - sequence of pairs ``(m, n)`` of nonnegative integers
     1583
     1584        EXAMPLES::
     1585
     1586            sage: P = Poset(((0, 1, 2, 3, 4), ((0, 1), (1, 2), (0, 3), (4, 2))))
     1587            sage: P.is_incomparable_chain_free((3, 1), (2, 2))
     1588            True
     1589
     1590        ::
     1591
     1592            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"))))
     1593            sage: P.is_incomparable_chain_free((3, 1))
     1594            True
     1595            sage: P.is_incomparable_chain_free((2, 2))
     1596            False
     1597
     1598        ::
     1599
     1600            sage: [len([p for p in Posets(n) if p.is_incomparable_chain_free((3, 1), (2, 2))]) for n in range(6)]
     1601            [1, 1, 2, 5, 14, 42]
     1602
     1603        TESTS::
     1604
     1605            sage: P = Poset(((0, 1, 2, 3, 4), ((0, 1), (1, 2), (0, 3), (4, 2))))
     1606            sage: P.is_incomparable_chain_free([3, 1], [2, 2])
     1607            True
     1608            sage: P.is_incomparable_chain_free([[3, 1], [2, 2]])
     1609            True
     1610            sage: P.is_incomparable_chain_free(([3, 1], [2, 2]))
     1611            True
     1612            sage: P.is_incomparable_chain_free([3, 1])
     1613            True
     1614            sage: P.is_incomparable_chain_free((3, 1))
     1615            True
     1616            sage: P.is_incomparable_chain_free([3, 1], 2)
     1617            Traceback (most recent call last):
     1618            ...
     1619            TypeError: ([3, 1], 2) is not a tuple of tuples.
     1620            sage: P.is_incomparable_chain_free([3, 1], [2, 2, 2])
     1621            Traceback (most recent call last):
     1622            ...
     1623            ValueError: '((3, 1), (2, 2, 2))' is not a tuple of length-2 tuples.
     1624        """
     1625        try:
     1626            if len(chain_pairs) is 1 and all(isinstance(tuple(chain_pair), tuple) for chain_pair in chain_pairs[0]):
     1627                chain_pairs = chain_pairs[0]
     1628        except:
     1629            None
     1630        try:
     1631            chain_pairs = [tuple(chain_pair) for chain_pair in chain_pairs]
     1632        except TypeError:
     1633            raise TypeError('%s is not a tuple of tuples.' % str(tuple(chain_pairs)))
     1634        if not all(len(chain_pair) is 2 for chain_pair in chain_pairs):
     1635            raise ValueError('%r is not a tuple of length-2 tuples.' % str(tuple(chain_pairs)))
     1636        return all(self._is_m_plus_n_free(chain_pair[0], chain_pair[1]) for chain_pair in chain_pairs)
     1637
    15171638    def is_lequal(self, x, y):
    15181639        """
    15191640        Returns ``True`` if `x` is less than or equal to `y` in the poset, and