Ticket #15322: trac_15322-chains-and-antichains-dg.patch

File trac_15322-chains-and-antichains-dg.patch, 11.8 KB (added by Darij Grinberg, 9 years ago)
  • sage/categories/posets.py

    # HG changeset patch
    # User darij grinberg <darijgrinberg@gmail.com>
    # Date 1382664742 25200
    # Node ID eee2ccac0352fbbf1c3d5cf461ab630ecb1d8878
    # Parent  404bc6de9738465c4be02b312815b502cdbf1f0d
    trac #15322: is_antichain_of_poset and is_chain_of_poset
    
    diff --git a/sage/categories/posets.py b/sage/categories/posets.py
    a b class Posets(Category): 
    451451            EXAMPLES::
    452452
    453453                sage: P = Poset((divisors(12), attrcall("divides")), facade=True, linear_extension=True)
    454                 sage: P.list()
     454                sage: sorted(P.list())
    455455                [1, 2, 3, 4, 6, 12]
    456456                sage: P.is_order_ideal([1, 3])
    457457                True
    class Posets(Category): 
    477477            EXAMPLES::
    478478
    479479                sage: P = Poset((divisors(12), attrcall("divides")), facade=True, linear_extension=True)
    480                 sage: P.list()
     480                sage: sorted(P.list())
    481481                [1, 2, 3, 4, 6, 12]
    482482                sage: P.is_order_filter([4, 12])
    483483                True
    class Posets(Category): 
    491491            """
    492492            return all((u in self and all(x in o for x in self.upper_covers(u))) for u in o)
    493493
     494        def is_chain_of_poset(self, o, ordered=False):
     495            """
     496            Return whether an iterable ``o`` is a chain of ``self``,
     497            including a check for ``o`` being ordered from smallest
     498            to largest element if the keyword ``ordered`` is set to
     499            ``True``.
     500
     501            INPUT:
     502
     503            - ``o`` -- an iterable (e. g., list, set, or tuple)
     504              containing some elements of ``self``
     505
     506            - ``ordered`` -- a Boolean (default: ``False``) which
     507              decides whether the notion of a chain includes being
     508              ordered
     509
     510            OUTPUT:
     511
     512            If ``ordered`` is set to ``False``, the truth value of
     513            the following assertion is returned: The subset of ``self``
     514            formed by the elements of ``o`` is a chain in ``self``.
     515
     516            If ``ordered`` is set to ``True``, the truth value of
     517            the following assertion is returned: Every element of the
     518            list ``o`` is (strictly!) smaller than its successor in
     519            ``self``. (This makes no sense if ``ordered`` is a set.)
     520
     521            EXAMPLES::
     522
     523                sage: P = Poset((divisors(12), attrcall("divides")), facade=True, linear_extension=True)
     524                sage: sorted(P.list())
     525                [1, 2, 3, 4, 6, 12]
     526                sage: P.is_chain_of_poset([1, 3])
     527                True
     528                sage: P.is_chain_of_poset([3, 1])
     529                True
     530                sage: P.is_chain_of_poset([1, 3], ordered=True)
     531                True
     532                sage: P.is_chain_of_poset([3, 1], ordered=True)
     533                False
     534                sage: P.is_chain_of_poset([])
     535                True
     536                sage: P.is_chain_of_poset([], ordered=True)
     537                True
     538                sage: P.is_chain_of_poset((2, 12, 6))
     539                True
     540                sage: P.is_chain_of_poset((2, 6, 12), ordered=True)
     541                True
     542                sage: P.is_chain_of_poset((2, 12, 6), ordered=True)
     543                False
     544                sage: P.is_chain_of_poset((2, 12, 6, 3))
     545                False
     546                sage: P.is_chain_of_poset((2, 3))
     547                False
     548
     549                sage: Q = Poset({2: [3, 1], 3: [4], 1: [4]})
     550                sage: Q.is_chain_of_poset([1, 2], ordered=True)
     551                False
     552                sage: Q.is_chain_of_poset([1, 2])
     553                True
     554                sage: Q.is_chain_of_poset([2, 1], ordered=True)
     555                True
     556                sage: Q.is_chain_of_poset([3])
     557                True
     558                sage: Q.is_chain_of_poset([4, 2, 3])
     559                True
     560                sage: Q.is_chain_of_poset([4, 2, 3], ordered=True)
     561                False
     562                sage: Q.is_chain_of_poset([2, 3, 4], ordered=True)
     563                True
     564
     565            Examples with infinite posets::
     566
     567                sage: from sage.categories.examples.posets import FiniteSetsOrderedByInclusion
     568                sage: R = FiniteSetsOrderedByInclusion()
     569                sage: R.is_chain_of_poset([R(set([3, 1, 2])), R(set([1, 4])), R(set([4, 5]))])
     570                False
     571                sage: R.is_chain_of_poset([R(set([3, 1, 2])), R(set([1, 2])), R(set([1]))], ordered=True)
     572                False
     573                sage: R.is_chain_of_poset([R(set([3, 1, 2])), R(set([1, 2])), R(set([1]))])
     574                True
     575
     576                sage: from sage.categories.examples.posets import PositiveIntegersOrderedByDivisibilityFacade
     577                sage: T = PositiveIntegersOrderedByDivisibilityFacade()
     578                sage: T.is_chain_of_poset((T(3), T(4), T(7)))
     579                False
     580                sage: T.is_chain_of_poset((T(3), T(6), T(3)))
     581                True
     582                sage: T.is_chain_of_poset((T(3), T(6), T(3)), ordered=True)
     583                False
     584                sage: T.is_chain_of_poset((T(3), T(3), T(6)))
     585                True
     586                sage: T.is_chain_of_poset((T(3), T(3), T(6)), ordered=True)
     587                True
     588                sage: T.is_chain_of_poset((), ordered=True)
     589                True
     590                sage: T.is_chain_of_poset((T(3),), ordered=True)
     591                True
     592                sage: T.is_chain_of_poset((T(q) for q in divisors(27)))
     593                True
     594                sage: T.is_chain_of_poset((T(q) for q in divisors(18)))
     595                False
     596            """
     597            list_o = list(o)
     598            if ordered:
     599                return all(self.le(a, b) for a, b in zip(list_o, list_o[1:]))
     600            else:
     601                for (i, x) in enumerate(list_o):
     602                    for y in list_o[:i]:
     603                        if (not self.le(x, y)) and (not self.gt(x, y)):
     604                            return False
     605                return True
     606
     607        def is_antichain_of_poset(self, o):
     608            """
     609            Return whether an iterable ``o`` is an antichain of
     610            ``self``.
     611
     612            INPUT:
     613
     614            - ``o`` -- an iterable (e. g., list, set, or tuple)
     615              containing some elements of ``self``
     616
     617            OUTPUT:
     618
     619            ``True`` if the subset of ``self`` consisting of the entries
     620            of ``o`` is an antichain of ``self``, and ``False`` otherwise.
     621
     622            EXAMPLES::
     623
     624                sage: P = Poset((divisors(12), attrcall("divides")), facade=True, linear_extension=True)
     625                sage: sorted(P.list())
     626                [1, 2, 3, 4, 6, 12]
     627                sage: P.is_antichain_of_poset([1, 3])
     628                False
     629                sage: P.is_antichain_of_poset([3, 1])
     630                False
     631                sage: P.is_antichain_of_poset([1, 1, 3])
     632                False
     633                sage: P.is_antichain_of_poset([])
     634                True
     635                sage: P.is_antichain_of_poset([1])
     636                True
     637                sage: P.is_antichain_of_poset([1, 1])
     638                True
     639                sage: P.is_antichain_of_poset([3, 4])
     640                True
     641                sage: P.is_antichain_of_poset([3, 4, 12])
     642                False
     643                sage: P.is_antichain_of_poset([6, 4])
     644                True
     645                sage: P.is_antichain_of_poset(i for i in divisors(12) if (2 < i and i < 6))
     646                True
     647                sage: P.is_antichain_of_poset(i for i in divisors(12) if (2 <= i and i < 6))
     648                False
     649
     650                sage: Q = Poset({2: [3, 1], 3: [4], 1: [4]})
     651                sage: Q.is_antichain_of_poset((1, 2))
     652                False
     653                sage: Q.is_antichain_of_poset((2, 4))
     654                False
     655                sage: Q.is_antichain_of_poset((4, 2))
     656                False
     657                sage: Q.is_antichain_of_poset((2, 2))
     658                True
     659                sage: Q.is_antichain_of_poset((3, 4))
     660                False
     661                sage: Q.is_antichain_of_poset((3, 1))
     662                True
     663                sage: Q.is_antichain_of_poset((1, ))
     664                True
     665                sage: Q.is_antichain_of_poset(())
     666                True
     667
     668            An infinite poset::
     669
     670                sage: from sage.categories.examples.posets import FiniteSetsOrderedByInclusion
     671                sage: R = FiniteSetsOrderedByInclusion()
     672                sage: R.is_antichain_of_poset([R(set([3, 1, 2])), R(set([1, 4])), R(set([4, 5]))])
     673                True
     674                sage: R.is_antichain_of_poset([R(set([3, 1, 2, 4])), R(set([1, 4])), R(set([4, 5]))])
     675                False
     676            """
     677            list_o = list(o)
     678            for (i, x) in enumerate(list_o):
     679                for y in list_o[:i]:
     680                    if self.lt(x, y) or self.gt(x, y):
     681                        return False
     682            return True
     683
    494684    class ElementMethods:
    495685        pass
    496686        # TODO: implement x<y, x<=y, x>y, x>=y appropriately once #10130 is resolved
  • sage/combinat/posets/posets.py

    diff --git a/sage/combinat/posets/posets.py b/sage/combinat/posets/posets.py
    a b class FinitePoset(UniqueRepresentation,  
    19491949        """
    19501950        return self._hasse_diagram.is_chain()
    19511951
     1952    def is_chain_of_poset(self, o, ordered=False):
     1953        """
     1954        Return whether an iterable ``o`` is a chain of ``self``,
     1955        including a check for ``o`` being ordered from smallest
     1956        to largest element if the keyword ``ordered`` is set to
     1957        ``True``.
     1958
     1959        INPUT:
     1960
     1961        - ``o`` -- an iterable (e. g., list, set, or tuple)
     1962          containing some elements of ``self``
     1963
     1964        - ``ordered`` -- a Boolean (default: ``False``) which
     1965          decides whether the notion of a chain includes being
     1966          ordered
     1967
     1968        OUTPUT:
     1969
     1970        If ``ordered`` is set to ``False``, the truth value of
     1971        the following assertion is returned: The subset of ``self``
     1972        formed by the elements of ``o`` is a chain in ``self``.
     1973
     1974        If ``ordered`` is set to ``True``, the truth value of
     1975        the following assertion is returned: Every element of the
     1976        list ``o`` is (strictly!) smaller than its successor in
     1977        ``self``. (This makes no sense if ``ordered`` is a set.)
     1978
     1979        EXAMPLES::
     1980
     1981            sage: P = Poset((divisors(12), attrcall("divides")))
     1982            sage: sorted(P.list())
     1983            [1, 2, 3, 4, 6, 12]
     1984            sage: P.is_chain_of_poset([2, 4])
     1985            True
     1986            sage: P.is_chain_of_poset([12, 6])
     1987            True
     1988            sage: P.is_chain_of_poset([12, 6], ordered=True)
     1989            False
     1990            sage: P.is_chain_of_poset([6, 12], ordered=True)
     1991            True
     1992            sage: P.is_chain_of_poset(())
     1993            True
     1994            sage: P.is_chain_of_poset((), ordered=True)
     1995            True
     1996            sage: P.is_chain_of_poset((3, 4, 12))
     1997            False
     1998            sage: P.is_chain_of_poset((3, 6, 12, 1))
     1999            True
     2000            sage: P.is_chain_of_poset((3, 6, 12, 1), ordered=True)
     2001            False
     2002            sage: P.is_chain_of_poset((3, 6, 12), ordered=True)
     2003            True
     2004            sage: P.is_chain_of_poset((1, 1, 3))
     2005            True
     2006            sage: P.is_chain_of_poset((1, 1, 3), ordered=True)
     2007            True
     2008            sage: P.is_chain_of_poset((6, 1, 1, 3))
     2009            True
     2010            sage: P.is_chain_of_poset((2, 1, 1, 3))
     2011            False
     2012        """
     2013        if ordered:
     2014            sorted_o = o
     2015        else:
     2016            sorted_o = sorted(o, key=self._element_to_vertex)
     2017        return all(self.le(a, b) for a, b in zip(sorted_o, sorted_o[1:]))
     2018
    19522019    def is_EL_labelling(self, f, return_raising_chains=False):
    19532020        r"""
    19542021        Returns ``True`` if ``f`` is an EL labelling of ``self``.