def quiver(self, edge_labels=True, index=False): """ Returns the quiver of ``self`` INPUT: - ``edges_labels`` -- whether to use the quiver element as label for the edges between the idempotents; if False, this may lead to multiple edges when the monoid is not generated by idempotents (default: True) - ``index`` -- whether to index the vertices of the graph by the indices of the simple modules rather than the corresponding idempotents (default: False) OUTPUT: the quiver of ``self``, as a graph with the idempotents of this monoid as vertices .. todo:: should index default to True? .. todo:: use a meaningful example EXAMPLES:: sage: import sage_semigroups.monoids.catalog as semigroups sage: M = semigroups.NDPFMonoidPoset(Posets(3)[3]) sage: G = M.quiver() sage: G Digraph on 4 vertices sage: G.edges() [([1], [2], [3])] sage: M.quiver(edge_labels=False).edges() [([1], [2], None)] sage: M.quiver(index=True).edges() [(2, 1, [3])] sage: M.quiver(index=True, edge_labels=False).edges() [(2, 1, None)] """ from sage.graphs.graph import DiGraph res = DiGraph() if index: res.add_vertices(self.simple_modules_index_set()) symbol = attrcall("symbol_index") else: res.add_vertices(self.idempotents()) symbol = attrcall("symbol") for x in self.quiver_elements(): res.add_edge(symbol(x,"left"), symbol(x, "right"), x if edge_labels else None) return res
def test_attrcall(name, L): """ Return a function by name. This is a helper function for test_finite_lattice(). This will unify all Boolean-valued functions to a function without parameters. EXAMPLES:: sage: from sage.tests.finite_poset import test_attrcall sage: N5 = posets.PentagonPoset() sage: N5.is_modular() == test_attrcall('is_modular', N5) True sage: N5.is_constructible_by_doublings('convex') == test_attrcall('is_doubling_convex', N5) True """ from sage.misc.misc import attrcall if name == 'is_doubling_any': return L.is_constructible_by_doublings('any') if name == 'is_doubling_lower': return L.is_constructible_by_doublings('upper') if name == 'is_doubling_upper': return L.is_constructible_by_doublings('lower') if name == 'is_doubling_convex': return L.is_constructible_by_doublings('convex') if name == 'is_doubling_interval': return L.is_constructible_by_doublings('interval') if name == 'is_uniq_orthocomplemented': return L.is_orthocomplemented(unique=True) return attrcall(name)(L)
def symmetric_derivatives(list_deg, row_symmetry=None): """ Return the symmetric derivative functions for the degree listed in `list_deg`. INPUT: - `r` -- a integer - `list_deg` -- a list of tuples - `row_symmetry` -- "permutation" (only implemented case) EXAMPLES:: sage: list_deg = [(i,j) for i in range(3) for j in range(3) if i+j>0] sage: list_deg [(0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] sage: symmetric_derivatives(list_deg) {(-2, -2): [*.symmetric_derivative(row_symmetry=None, d=(2, 2))], (-2, -1): [*.symmetric_derivative(row_symmetry=None, d=(2, 1))], (-2, 0): [*.symmetric_derivative(row_symmetry=None, d=(2, 0))], (-1, -2): [*.symmetric_derivative(row_symmetry=None, d=(1, 2))], (-1, -1): [*.symmetric_derivative(row_symmetry=None, d=(1, 1))], (-1, 0): [*.symmetric_derivative(row_symmetry=None, d=(1, 0))], (0, -2): [*.symmetric_derivative(row_symmetry=None, d=(0, 2))], (0, -1): [*.symmetric_derivative(row_symmetry=None, d=(0, 1))]} """ r = len(list_deg[0]) D = cartesian_product([ZZ for i in range(r)]) return { D(-i for i in d): [attrcall("symmetric_derivative", d=d, row_symmetry=row_symmetry)] for d in list_deg }
def fill_allignment_database(cls): """ Fill the database mapping gap categories / properties to their corresponding (super) Sage categories from the semantic information stored in the category class """ assert issubclass(cls, Category) gap = cls._semantic.get("gap") gap_sub = cls._semantic.get("gap_sub", gap) gap_negation = cls._semantic.get("gap_negation") if gap_sub is not None: gap_category_to_structure[gap_sub] = attrcall("add_category", cls) if gap_negation is not None: false_properties_to_structure[gap_negation] = attrcall( "add_category", cls)
def test_attrcall(name, L): """ Return a function by name. This is a helper function for test_finite_lattice(). This will unify all Boolean-valued functions to a function without parameters. EXAMPLES:: sage: from sage.tests.finite_poset import test_attrcall sage: N5 = posets.PentagonPoset() sage: N5.is_modular() == test_attrcall('is_modular', N5) True sage: N5.is_constructible_by_doublings('convex') == test_attrcall('is_doubling_convex', N5) True """ if name == 'is_doubling_any': return L.is_constructible_by_doublings('any') if name == 'is_doubling_lower': return L.is_constructible_by_doublings('upper') if name == 'is_doubling_upper': return L.is_constructible_by_doublings('lower') if name == 'is_doubling_convex': return L.is_constructible_by_doublings('convex') if name == 'is_doubling_interval': return L.is_constructible_by_doublings('interval') if name == 'is_uniq_orthocomplemented': return L.is_orthocomplemented(unique=True) return attrcall(name)(L)
def order_ideals_lattice(self): r""" Returns the lattice of order ideals of a poset `P`, ordered by inclusion. The usual notation is `J(P)`. EXAMPLES:: sage: P = Posets.PentagonPoset(facade = True) sage: P.cover_relations() [[0, 1], [0, 2], [1, 4], [2, 3], [3, 4]] sage: J = P.order_ideals_lattice(); J Finite lattice containing 8 elements sage: list(J) [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 2, 3}, {0, 1, 2, 3}, {0, 1, 2, 3, 4}] TESTS:: sage: J = Posets.DiamondPoset(4, facade = True).order_ideals_lattice(); J Finite lattice containing 6 elements sage: list(J) [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 1, 2, 3}] sage: J.cover_relations() [[{}, {0}], [{0}, {0, 2}], [{0}, {0, 1}], [{0, 2}, {0, 1, 2}], [{0, 1}, {0, 1, 2}], [{0, 1, 2}, {0, 1, 2, 3}]] .. note:: we use facade posets in the examples above just to ensure a nicer ordering in the output. """ from sage.misc.misc import attrcall from sage.sets.set import Set from sage.combinat.posets.lattices import LatticePoset ideals = [Set( self.order_ideal(antichain) ) for antichain in self.antichains()] return LatticePoset((ideals,attrcall("issubset")))
def order_ideals_lattice(self): r""" Returns the lattice of order ideals of a poset `P`, ordered by inclusion. The usual notation is `J(P)`. EXAMPLES:: sage: P = Posets.PentagonPoset(facade = True) sage: P.cover_relations() [[0, 1], [0, 2], [1, 4], [2, 3], [3, 4]] sage: J = P.order_ideals_lattice(); J Finite lattice containing 8 elements sage: list(J) [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 2, 3}, {0, 1, 2, 3}, {0, 1, 2, 3, 4}] TESTS:: sage: J = Posets.DiamondPoset(4, facade = True).order_ideals_lattice(); J Finite lattice containing 6 elements sage: list(J) [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 1, 2, 3}] sage: J.cover_relations() [[{}, {0}], [{0}, {0, 2}], [{0}, {0, 1}], [{0, 2}, {0, 1, 2}], [{0, 1}, {0, 1, 2}], [{0, 1, 2}, {0, 1, 2, 3}]] .. note:: we use facade posets in the examples above just to ensure a nicer ordering in the output. """ from sage.misc.misc import attrcall from sage.sets.set import Set from sage.combinat.posets.lattices import LatticePoset ideals = [ Set(self.order_ideal(antichain)) for antichain in self.antichains() ] return LatticePoset((ideals, attrcall("issubset")))
def cartesian_projection(self, i): """ Return the natural projection onto the `i`-th Cartesian factor of ``self`` as per :meth:`Sets.CartesianProducts.ParentMethods.cartesian_projection() <sage.categories.sets_cat.Sets.CartesianProducts.ParentMethods.cartesian_projection>`. INPUT: - ``i`` -- the index of a Cartesian factor of ``self`` EXAMPLES:: sage: C = Sets().CartesianProducts().example(); C The Cartesian product of (Set of prime numbers (basic implementation), An example of an infinite enumerated set: the non negative integers, An example of a finite enumerated set: {1,2,3}) sage: x = C.an_element(); x (47, 42, 1) sage: pi = C.cartesian_projection(1) sage: pi(x) 42 sage: C.cartesian_projection('hey') Traceback (most recent call last): ... ValueError: i (=hey) must be in {0, 1, 2} """ if i not in self._sets_keys(): raise ValueError("i (={}) must be in {}".format(i, self._sets_keys())) return attrcall("cartesian_projection", i)
def order_ideals_lattice(self, as_ideals=True): r""" Returns the lattice of order ideals of a poset `P`, ordered by inclusion. The usual notation is `J(P)`. The underlying set is by default the set of order ideals of `P`. It can be alternatively chosen to be the set of antichains of `P`. INPUT: - ``as_ideals`` -- Boolean, if ``True`` (default) returns a poset on the set of order ideals, otherwise on the set of antichains EXAMPLES:: sage: P = Posets.PentagonPoset(facade = True) sage: P.cover_relations() [[0, 1], [0, 2], [1, 4], [2, 3], [3, 4]] sage: J = P.order_ideals_lattice(); J Finite lattice containing 8 elements sage: list(J) [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 2, 3}, {0, 1, 2, 3}, {0, 1, 2, 3, 4}] As a lattice on antichains:: sage: J2 = P.order_ideals_lattice(False); J2 Finite lattice containing 8 elements sage: list(J2) [(0,), (1, 2), (1, 3), (1,), (2,), (3,), (4,), ()] TESTS:: sage: J = Posets.DiamondPoset(4, facade = True).order_ideals_lattice(); J Finite lattice containing 6 elements sage: list(J) [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 1, 2, 3}] sage: J.cover_relations() [[{}, {0}], [{0}, {0, 2}], [{0}, {0, 1}], [{0, 2}, {0, 1, 2}], [{0, 1}, {0, 1, 2}], [{0, 1, 2}, {0, 1, 2, 3}]] .. NOTE:: we use facade posets in the examples above just to ensure a nicer ordering in the output. """ from sage.combinat.posets.lattices import LatticePoset if as_ideals: from sage.misc.misc import attrcall from sage.sets.set import Set ideals = [Set( self.order_ideal(antichain) ) for antichain in self.antichains()] return LatticePoset((ideals,attrcall("issubset"))) else: from sage.misc.cachefunc import cached_function antichains = [tuple(a) for a in self.antichains()] @cached_function def is_above(a,xb): return any(self.is_lequal(xa,xb) for xa in a) def cmp(a,b): return all(is_above(a,xb) for xb in b) return LatticePoset((antichains,cmp))
def __reduce__(self): """ TESTS:: sage: CartanType(['F', 4, 1]).dual().__reduce__() (*.dual(), (['F', 4, 1],)) """ return (attrcall("dual"), (self._type,))
def __reduce__(self): """ TESTS:: sage: CartanType(['F', 4, 1]).dual().__reduce__() (*.dual(), (['F', 4, 1],)) """ return (attrcall("dual"), (self._type, ))
def polarization_operators(r, max_deg=1, side=None, row_symmetry=None): """ Return the polarization operator functions in `r` sets of variables with maximum degree `max_deg`. The polarization operator $P_{x,y}^k$ in defined by $$P_{x,y}^k := \sum_i y_i \partial_{x_i}^k$$ where X and y are two sets of variables and $\partial_{x_i}^k$ stand for the $k$-th partial derivative in $x_i$. The option `side` allows to specify keywork "down" to return only polarization operators $P_{x_i,x_j}^k$ such that $i<j$. INPUT: - `r` -- an integer - `max_deg` -- an integer - `row_symmetry` -- "permutation" (only implemented case) EXAMPLES:: sage: polarization_operators(2) {(-1, 1): [*.polarization(i1=0, row_symmetry=None, i2=1, d=1)], (1, -1): [*.polarization(i1=1, row_symmetry=None, i2=0, d=1)]} sage: polarization_operators(2, max_deg=3) {(-3, 1): [*.polarization(i1=0, row_symmetry=None, i2=1, d=3)], (-2, 1): [*.polarization(i1=0, row_symmetry=None, i2=1, d=2)], (-1, 1): [*.polarization(i1=0, row_symmetry=None, i2=1, d=1)], (1, -3): [*.polarization(i1=1, row_symmetry=None, i2=0, d=3)], (1, -2): [*.polarization(i1=1, row_symmetry=None, i2=0, d=2)], (1, -1): [*.polarization(i1=1, row_symmetry=None, i2=0, d=1)]} sage: polarization_operators(2, max_deg=3, side="down") {(-3, 1): [*.polarization(i1=0, row_symmetry=None, i2=1, d=3)], (-2, 1): [*.polarization(i1=0, row_symmetry=None, i2=1, d=2)], (-1, 1): [*.polarization(i1=0, row_symmetry=None, i2=1, d=1)]} sage: v = vandermonde(Partition([2,1]), 2) sage: gen = {v.multidegree() : [v]} sage: op = partial_derivatives(v.parent()) sage: S = Subspace(gen, op) sage: polarizators = polarization_operators(2, max_deg=v.degree()) sage: Subspace(S.basis(), polarizators).basis() {(0, 0): (-theta00 + theta01, -theta00 + theta02), (0, 1): (-x11*theta00 + x12*theta00 + x10*theta01 - x12*theta01 - x10*theta02 + x11*theta02,), (1, 0): (x01*theta00 - x02*theta00 - x00*theta01 + x02*theta01 + x00*theta02 - x01*theta02,)} """ D = cartesian_product([ZZ for i in range(r)]) return { D([-d if i == i1 else 1 if i == i2 else 0 for i in range(r)]): [ attrcall("polarization", i1=i1, i2=i2, d=d, row_symmetry=row_symmetry) ] for d in range(1, max_deg + 1) for i1 in range(0, r) for i2 in range(0, r) if (i1 < i2 if side == 'down' else i1 != i2) }
def multipolarization(r, list_deg, i2, row_symmetry=None): """ """ D = cartesian_product([ZZ for i in range(r)]) op = {} for deg in list_deg: op[D(-deg[i] + 1 if i == i2 else -deg[i] for i in range(len(deg)))] = [ attrcall("multi_polarization", D=deg, i2=i2, row_symmetry=row_symmetry) ] return op
def transition_module(self, alphabet=None, monoid=None, side="right"): r""" Constructs a transformation module whose Cayley graph is ``self``. INPUT: - ``alphabet`` -- a list of index of the operators (default: the set of labels of the edges of the graph) - ``monoid`` -- the monoid that is acting (default: the transition monoid of this automaton); - ``side`` -- 'left' or 'right' (default: 'right'); on which side the action is considered .. warning:: At this point only the transition monoid is actually supported! One should support instead any monoid of whom the transition monoid is a quotient of, by going through reduced words. EXAMPLES:: sage: automaton = DiGraph( [ (1, 1, "b"), (1, 2, "a"), ... (2, 2, "a"), (2, 2, "c"), (2, 3, "b"), ... (3, 2, "a"), (3, 3, "b"), (3, 3, "c") ] ) sage: M = automaton.transition_module() sage: M.cayley_graph().edges() == automaton.edges() # todo: not implemented (some edges are repeated!!!) True sage: set(M.cayley_graph().edges()) == set(automaton.edges()) True Its semigroup is the transition monoid of ``self``:: sage: M.semigroup() The transition monoid of Looped multi-digraph on 3 vertices sage: M.semigroup() is automaton.transition_monoid() True sage: TestSuite(M).run() # todo: several tests fail here """ from sage.misc.misc import attrcall from sage.monoids.representations import SetWithAction if monoid is None: monoid = self.transition_monoid(alphabet=alphabet, side=side) else: assert monoid.automaton().vertices() == self.vertices() return SetWithAction(monoid, self.vertices(), attrcall("__call__"), side=side)
def category_graph(categories=None, relabel="object_names"): """ Return the graph of the categories in Sage. INPUT: - ``categories`` -- a list (or iterable) of categories If ``categories`` is specified, then the graph contains the mentioned categories together with all their super categories. Otherwise the graph contains (an instance of) each category in :mod:`sage.categories.all` (e.g. ``Algebras(QQ)`` for algebras). For readability, the names of the category are shortened. .. TODO:: Further remove the base ring (see also :trac:`15801`). EXAMPLES:: sage: G = sage.categories.category.category_graph(categories = [Groups()]) sage: G.vertices() ['groups', 'inverse unital magmas', 'magmas', 'monoids', 'objects', 'semigroups', 'sets', 'sets with partial maps', 'unital magmas'] sage: G.plot() Graphics object consisting of 20 graphics primitives sage: sage.categories.category.category_graph().plot() Graphics object consisting of ... graphics primitives """ from sage import graphs if categories is None: categories = category_sample() # Include all the super categories # Get rid of join categories categories = set(cat for category in categories for cat in category.all_super_categories( proper=isinstance(category, JoinCategory))) g = graphs.digraph.DiGraph() for cat in categories: g.add_vertex(cat) for source in categories: # Don't use super_categories() since it might contain join categories for target in source._super_categories: g.add_edge([source, target]) if relabel == "object_names": g.relabel(attrcall("_repr_object_names")) return g
def j_classes_of_idempotents(self): r""" Returns all the idempotents of self, grouped by J-class. OUTPUT: a list of lists. EXAMPLES:: sage: S = FiniteSemigroups().example(alphabet=('a','b', 'c')) sage: sorted(map(sorted, S.j_classes_of_idempotents())) [['a'], ['ab', 'ba'], ['abc', 'acb', 'bac', 'bca', 'cab', 'cba'], ['ac', 'ca'], ['b'], ['bc', 'cb'], ['c']] """ return [l for l in ([x for x in cl if attrcall('is_idempotent')(x)] for cl in self.j_classes()) if len(l) > 0]
def transition_module(self, alphabet = None, monoid=None, side="right"): r""" Constructs a transformation module whose Cayley graph is ``self``. INPUT: - ``alphabet`` -- a list of index of the operators (default: the set of labels of the edges of the graph) - ``monoid`` -- the monoid that is acting (default: the transition monoid of this automaton); - ``side`` -- 'left' or 'right' (default: 'right'); on which side the action is considered .. warning:: At this point only the transition monoid is actually supported! One should support instead any monoid of whom the transition monoid is a quotient of, by going through reduced words. EXAMPLES:: sage: automaton = DiGraph( [ (1, 1, "b"), (1, 2, "a"), ... (2, 2, "a"), (2, 2, "c"), (2, 3, "b"), ... (3, 2, "a"), (3, 3, "b"), (3, 3, "c") ] ) sage: M = automaton.transition_module() sage: M.cayley_graph().edges() == automaton.edges() # todo: not implemented (some edges are repeated!!!) True sage: set(M.cayley_graph().edges()) == set(automaton.edges()) True Its semigroup is the transition monoid of ``self``:: sage: M.semigroup() The transition monoid of Looped multi-digraph on 3 vertices sage: M.semigroup() is automaton.transition_monoid() True sage: TestSuite(M).run() # todo: several tests fail here """ from sage.misc.misc import attrcall from sage.monoids.representations import SetWithAction if monoid is None: monoid = self.transition_monoid(alphabet = alphabet, side=side) else: assert monoid.automaton().vertices() == self.vertices() return SetWithAction(monoid, self.vertices(), attrcall("__call__"), side=side)
def j_classes_of_idempotents(self): r""" Returns all the idempotents of self, grouped by J-class. OUTPUT: a list of lists. EXAMPLES:: sage: S = FiniteSemigroups().example(alphabet=('a','b', 'c')) sage: sorted(map(sorted, S.j_classes_of_idempotents())) [['a'], ['ab', 'ba'], ['abc', 'acb', 'bac', 'bca', 'cab', 'cba'], ['ac', 'ca'], ['b'], ['bc', 'cb'], ['c']] """ return [ l for l in map(lambda cl: list(filter(attrcall("is_idempotent"), cl)), self.j_classes()) if len(l) > 0 ]
def j_classes_of_idempotents(self): r""" Returns all the idempotents of self, grouped by J-class. OUTPUT: a list of lists. EXAMPLES:: sage: S = FiniteSemigroups().example(alphabet=('a','b', 'c')) sage: sorted(map(sorted, S.j_classes_of_idempotents())) [['a'], ['ab', 'ba'], ['abc', 'acb', 'bac', 'bca', 'cab', 'cba'], ['ac', 'ca'], ['b'], ['bc', 'cb'], ['c']] """ return filter(lambda l: len(l) > 0, map(lambda cl: filter(attrcall('is_idempotent'), cl), self.j_classes()))
def steenrod_operators(r, degree=1, row_symmetry=None): """ Return the Steenrod operator functions in `r` sets of variables of degree `degree`. The Steenrod operator $S_{x}^k$ in defined for $k>1$ by $$S_{x}^k := \sum_i x_i \partial_{x_i}^k$$ where X and y are two sets of variables and $\partial_{x_i}^k$ stand for the $k$-th partial derivative in $x_i$. INPUT: - `r` -- a integer - `degree` -- an integer - `row_symmetry` -- "permutation" (only implemented case) EXAMPLES :: sage: steenrod_operators(2) {(-1, 0): [*.steenrod_op(i=0, row_symmetry=None, k=2)], (0, -1): [*.steenrod_op(i=1, row_symmetry=None, k=2)]} sage: steenrod_operators(2, 2) {(-2, 0): [*.steenrod_op(i=0, row_symmetry=None, k=3)], (0, -2): [*.steenrod_op(i=1, row_symmetry=None, k=3)]} sage: v = vandermonde(Diagram([(0,0),(1,0),(3,0)])) sage: v -x00^3*x01 + x00*x01^3 + x00^3*x02 - x01^3*x02 - x00*x02^3 + x01*x02^3 sage: gen = {v.multidegree() : [v]} sage: op = merge(steenrod_operators(1,1), steenrod_operators(1,2)) sage: Subspace(gen, op).basis() {(3,): (-x00^2*x01 + x00*x01^2 + x00^2*x02 - x01^2*x02 - x00*x02^2 + x01*x02^2,), (4,): (-x00^3*x01 + x00*x01^3 + x00^3*x02 - x01^3*x02 - x00*x02^3 + x01*x02^3,)} """ if degree < 1: degree = 1 D = cartesian_product([ZZ for i in range(r)]) op = {} for i in range(r): op[D((-degree if j == i else 0 for j in range(r)))] = [ attrcall("steenrod_op", i=i, k=degree + 1, row_symmetry=row_symmetry) ] return op
def __init__(self, predicate, property, code=None, section=None): """ EXAMPLES:: """ active_property_displayers.append(self) self._property = property if isinstance(predicate, Category): predicate = predicate.__contains__ elif isinstance(predicate, type): predicate = predicate.__instancecheck__ self._predicate = predicate if code is not None: if isinstance(code, str): self.result = attrcall(code) else: self.result=code else: self._method = property.lower().replace(" ", "_")
def elements(self): r""" Returns the elements of ``self`` Those are constructed as the elements below the maximal elements of ``self`` in Bruhat order. OUTPUT: a :class:`TransitiveIdeal` object EXAMPLES:: sage: PF = WeylGroup(['A',3]).pieri_factors() sage: [w.reduced_word() for w in PF.elements()] [[3, 2, 1], [2, 1], [1], [], [3, 1], [3], [3, 2], [2]] ..seealso:: :meth:`maximal_elements` TODO: possibly remove this method and instead have this class inherit from :class:`TransitiveIdeal`. """ return TransitiveIdeal(attrcall('bruhat_lower_covers'), self.maximal_elements())
def partial_derivatives(P): """ Return the partial derivative functions in all the variables of `P` allowed for derivation (ie not in the inert variables). INPUT: - `P` -- a diagonal polynomial ring EXAMPLES:: sage: P = DiagonalPolynomialRing(QQ, 3, 1) sage: partial_derivatives(P) {(-1,): [*.derivative(x00), *.derivative(x01), *.derivative(x02)]} sage: P = DiagonalPolynomialRing(QQ, 3, 2) sage: partial_derivatives(P) {(-1, 0): [*.derivative(x00), *.derivative(x01), *.derivative(x02)], (0, -1): [*.derivative(x10), *.derivative(x11), *.derivative(x12)]} sage: P = DiagonalPolynomialRing(QQ, 3, 1, inert=1) sage: partial_derivatives(P) {(-1,): [*.derivative(x00), *.derivative(x01), *.derivative(x02)]} sage: v = vandermonde(Partition([2,1])) sage: gen = {v.multidegree() : [v]} sage: op = partial_derivatives(v.parent()) sage: Subspace(gen, op).basis() {(0,): (theta01 - theta02, theta00 - theta02), (1,): (x01*theta00 - x02*theta00 - x00*theta01 + x02*theta01 + x00*theta02 - x01*theta02,)} """ n = P.ncols() r = P.nrows() D = P.grading_set() X = P.multivar_pol_ring_variables() op = {} for i in range(r): op[D((-1 if j == i else 0 for j in range(r)))] = [ attrcall("derivative", X[i, k]) for k in range(n) ] return op
def cartesian_projection(self, i): """ Return the natural projection onto the `i`-th cartesian factor of ``self`` as per :meth:`Sets.CartesianProducts.ParentMethods.cartesian_projection() <sage.categories.sets_cat.Sets.CartesianProducts.ParentMethods.cartesian_projection>`. INPUT: - ``i`` -- the index of a cartesian factor of ``self`` EXAMPLES:: sage: C = Sets().CartesianProducts().example(); C The cartesian product of (Set of prime numbers (basic implementation), An example of an infinite enumerated set: the non negative integers, An example of a finite enumerated set: {1,2,3}) sage: x = C.an_element(); x (47, 42, 1) sage: pi = C.cartesian_projection(1) sage: pi(x) 42 """ assert i in self._sets_keys() return attrcall("cartesian_projection", i)
def summand_projection(self, i): """ Returns the natural projection onto the `i`-th summand of self as per :meth:`Sets.CartesianProducts.ParentMethods.summand_projection() <sage.categories.sets_cat.Sets.CartesianProducts.ParentMethods.summand_projection>`. INPUTS: - ``i`` -- the index of a summand of self EXAMPLES:: sage: C = Sets().CartesianProducts().example(); C The cartesian product of (Set of prime numbers (basic implementation), An example of an infinite enumerated set: the non negative integers, An example of a finite enumerated set: {1,2,3}) sage: x = C.an_element(); x (47, 42, 1) sage: pi = C.summand_projection(1) sage: pi(x) 42 """ assert i in self._sets_keys() return attrcall("summand_projection", i)
def order_ideals_lattice(self, as_ideals=True): r""" Return the lattice of order ideals of a poset ``self``, ordered by inclusion. The lattice of order ideals of a poset `P` is usually denoted by `J(P)`. Its underlying set is the set of order ideals of `P`, and its partial order is given by inclusion. The order ideals of `P` are in a canonical bijection with the antichains of `P`. The bijection maps every order ideal to the antichain formed by its maximal elements. By setting the ``as_ideals`` keyword variable to ``False``, one can make this method apply this bijection before returning the lattice. INPUT: - ``as_ideals`` -- Boolean, if ``True`` (default) returns a poset on the set of order ideals, otherwise on the set of antichains EXAMPLES:: sage: P = Posets.PentagonPoset(facade = True) sage: P.cover_relations() [[0, 1], [0, 2], [1, 4], [2, 3], [3, 4]] sage: J = P.order_ideals_lattice(); J Finite lattice containing 8 elements sage: list(J) [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 2, 3}, {0, 1, 2, 3}, {0, 1, 2, 3, 4}] As a lattice on antichains:: sage: J2 = P.order_ideals_lattice(False); J2 Finite lattice containing 8 elements sage: list(J2) [(0,), (1, 2), (1, 3), (1,), (2,), (3,), (4,), ()] TESTS:: sage: J = Posets.DiamondPoset(4, facade = True).order_ideals_lattice(); J Finite lattice containing 6 elements sage: list(J) [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 1, 2, 3}] sage: J.cover_relations() [[{}, {0}], [{0}, {0, 2}], [{0}, {0, 1}], [{0, 2}, {0, 1, 2}], [{0, 1}, {0, 1, 2}], [{0, 1, 2}, {0, 1, 2, 3}]] .. NOTE:: we use facade posets in the examples above just to ensure a nicer ordering in the output. """ from sage.combinat.posets.lattices import LatticePoset if as_ideals: from sage.misc.misc import attrcall from sage.sets.set import Set ideals = [ Set(self.order_ideal(antichain)) for antichain in self.antichains() ] return LatticePoset((ideals, attrcall("issubset"))) else: from sage.misc.cachefunc import cached_function antichains = [tuple(a) for a in self.antichains()] @cached_function def is_above(a, xb): return any(self.is_lequal(xa, xb) for xa in a) def cmp(a, b): return all(is_above(a, xb) for xb in b) return LatticePoset((antichains, cmp))
EXAMPLES:: sage: from mygap import Structure, GAPObject, GAPMorphism sage: s = Structure(GAPObject, Objects()) sage: s.add_class(GAPMorphism) sage: s.category Category of objects sage: s.cls <class 'mygap.GAPMorphism'> """ assert issubclass(cls, self.cls) self.cls = cls gap_category_to_structure = { "IsIterator": attrcall("add_class", GAPIterator), # Cheating a bit: this should be IsMapping, which further requires IsTotal and IsSingleValued "IsGeneralMapping": attrcall("add_class", GAPMorphism), } true_properties_to_structure = { #"IsGroupAsSemigroup": add_axiom("Inverse"), # Useful? } false_properties_to_structure = {} def fill_allignment_database(cls): """ Fill the database mapping gap categories / properties to their corresponding (super) Sage categories from the semantic
def order_ideals_lattice(self, as_ideals=True): r""" Return the lattice of order ideals of a poset ``self``, ordered by inclusion. The lattice of order ideals of a poset `P` is usually denoted by `J(P)`. Its underlying set is the set of order ideals of `P`, and its partial order is given by inclusion. The order ideals of `P` are in a canonical bijection with the antichains of `P`. The bijection maps every order ideal to the antichain formed by its maximal elements. By setting the ``as_ideals`` keyword variable to ``False``, one can make this method apply this bijection before returning the lattice. INPUT: - ``as_ideals`` -- Boolean, if ``True`` (default) returns a poset on the set of order ideals, otherwise on the set of antichains EXAMPLES:: sage: P = Posets.PentagonPoset(facade = True) sage: P.cover_relations() [[0, 1], [0, 2], [1, 4], [2, 3], [3, 4]] sage: J = P.order_ideals_lattice(); J Finite lattice containing 8 elements sage: list(J) [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 2, 3}, {0, 1, 2, 3}, {0, 1, 2, 3, 4}] As a lattice on antichains:: sage: J2 = P.order_ideals_lattice(False); J2 Finite lattice containing 8 elements sage: list(J2) [(0,), (1, 2), (1, 3), (1,), (2,), (3,), (4,), ()] TESTS:: sage: J = Posets.DiamondPoset(4, facade = True).order_ideals_lattice(); J Finite lattice containing 6 elements sage: list(J) [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 1, 2, 3}] sage: J.cover_relations() [[{}, {0}], [{0}, {0, 2}], [{0}, {0, 1}], [{0, 2}, {0, 1, 2}], [{0, 1}, {0, 1, 2}], [{0, 1, 2}, {0, 1, 2, 3}]] .. NOTE:: we use facade posets in the examples above just to ensure a nicer ordering in the output. """ from sage.combinat.posets.lattices import LatticePoset if as_ideals: from sage.misc.misc import attrcall from sage.sets.set import Set ideals = [Set( self.order_ideal(antichain) ) for antichain in self.antichains()] return LatticePoset((ideals,attrcall("issubset"))) else: from sage.misc.cachefunc import cached_function antichains = [tuple(a) for a in self.antichains()] @cached_function def is_above(a,xb): return any(self.is_lequal(xa,xb) for xa in a) def cmp(a,b): return all(is_above(a,xb) for xb in b) return LatticePoset((antichains,cmp))
def test_finite_poset(P): """ Test several functions on a given finite poset. The function contains tests of different kinds, for example - Numerical properties jump number, dimension etc. can't be a bigger in a subposet with one element less. - "Dual tests", for example the dual of meet-semilattice must be a join-semilattice. - Random tries: for example if the dimension of a poset is `k`, then it can't be the intersection of `k-1` random linear extensions. EXAMPLES:: sage: from sage.tests.finite_poset import test_finite_poset sage: P = posets.RandomPoset(10, 0.15) sage: test_finite_poset(P) is None # Long time True """ from sage.combinat.posets.posets import Poset from sage.combinat.subset import Subsets from sage.misc.prandom import shuffle from sage.misc.misc import attrcall e = P.random_element() P_one_less = P.subposet([x for x in P if x != e]) # Cardinality if len(P) != P.cardinality(): raise ValueError("error 1 in cardinality") if P.cardinality() - 1 != P_one_less.cardinality(): raise ValueError("error 5 in cardinality") # Height h1 = P.height() h2, chain = P.height(certificate=True) if h1 != h2: raise ValueError("error 1 in height") if h1 != len(chain): raise ValueError("error 2 in height") if not P.is_chain_of_poset(chain): raise ValueError("error 3 in height") if len(P.random_maximal_chain()) > h1: raise ValueError("error 4 in height") if h1 - P_one_less.height() not in [0, 1]: raise ValueError("error 5 in height") # Width w1 = P.width() w2, antichain = P.width(certificate=True) if w1 != w2: raise ValueError("error 1 in width") if w1 != len(antichain): raise ValueError("error 2 in width") if not P.is_antichain_of_poset(antichain): raise ValueError("error 3 in width") if len(P.random_maximal_antichain()) > w1: raise ValueError("error 4 in width") if w1 - P_one_less.width() not in [0, 1]: raise ValueError("error 5 in width") # Dimension dim1 = P.dimension() dim2, linexts = P.dimension(certificate=True) if dim1 != dim2: raise ValueError("error 1 in dimension") if dim1 != len(linexts): raise ValueError("error 2 in dimension") P_ = Poset((P.list(), lambda a, b: all( linext.index(a) < linext.index(b) for linext in linexts))) if P_ != Poset(P.hasse_diagram()): raise ValueError("error 3 in dimension") x = [P.random_linear_extension() for _ in range(dim1 - 1)] P_ = Poset( (P.list(), lambda a, b: all(linext.index(a) < linext.index(b) for linext in x))) if P_ == Poset(P.hasse_diagram()): raise ValueError("error 4 in dimension") if dim1 - P_one_less.dimension() < 0: raise ValueError("error 5 in dimension") # Jump number j1 = P.jump_number() j2, linext = P.jump_number(certificate=True) if j1 != j2: raise ValueError("error 1 in jump number") if P.linear_extension(linext).jump_count() != j1: raise ValueError("error 2 in jump number") if not P.is_linear_extension(linext): raise ValueError("error 3 in jump number") if P.linear_extension(P.random_linear_extension()).jump_count() < j1: raise ValueError("error 4 in jump number") if j1 - P_one_less.jump_number() not in [0, 1]: raise ValueError("error 5 in jump number") P_dual = P.dual() selfdual_properties = [ 'chain', 'bounded', 'connected', 'graded', 'ranked', 'series_parallel', 'slender', 'lattice' ] for prop in selfdual_properties: f = attrcall('is_' + prop) if f(P) != f(P_dual): raise ValueError("error in self-dual property %s" % prop) if P.is_graded(): if P.is_bounded(): if P.is_eulerian() != P_dual.is_eulerian(): raise ValueError("error in self-dual property eulerian") if P.is_eulerian(): P_ = P.star_product(P) if not P_.is_eulerian(): raise ("error in star product / eulerian") chain1 = P.random_maximal_chain() if len(chain1) != h1: raise ValueError("error in is_graded") if not P.is_ranked(): raise ValueError("error in is_ranked / is_graded") if P.is_meet_semilattice() != P_dual.is_join_semilattice(): raise ValueError("error in meet/join semilattice") if set(P.minimal_elements()) != set(P_dual.maximal_elements()): raise ValueError("error in min/max elements") if P.top() != P_dual.bottom(): raise ValueError("error in top/bottom element") parts = P.connected_components() P_ = Poset() for part in parts: P_ = P_.disjoint_union(part) if not P.is_isomorphic(P_): raise ValueError("error in connected components / disjoint union") parts = P.ordinal_summands() P_ = Poset() for part in parts: P_ = P_.ordinal_sum(part) if not P.is_isomorphic(P_): raise ValueError("error in ordinal summands / ordinal sum") P_ = P.with_bounds().without_bounds() if not P.is_isomorphic(P_): raise ValueError("error in with bounds / without bounds") P_ = P.completion_by_cuts().irreducibles_poset() if not P.has_isomorphic_subposet(P_): raise ValueError("error in completion by cuts / irreducibles poset") P_ = P.subposet(Subsets(P).random_element()) if not P_.is_induced_subposet(P): raise ValueError("error in subposet / is induced subposet") if not P.is_linear_extension(P.random_linear_extension()): raise ValueError("error in is linear extension") x = list(P) shuffle(x) if not P.is_linear_extension(P.sorted(x)): raise ValueError("error in sorted") dil = P.dilworth_decomposition() chain = dil[randint(0, len(dil) - 1)] if not P.is_chain_of_poset(chain): raise ValueError("error in Dilworth decomposition") lev = P.level_sets() level = lev[randint(0, len(lev) - 1)] if not P.is_antichain_of_poset(level): raise ValueError("error in level sets") # certificate=True must return a pair bool_with_cert = [ 'eulerian', 'greedy', 'join_semilattice', 'jump_critical', 'meet_semilattice', 'slender' ] for p in bool_with_cert: try: # some properties are not always defined for all posets res1 = attrcall('is_' + p)(P) except ValueError: continue res2 = attrcall('is_' + p, certificate=True)(P) if type(res2) != type((1, 2)) or len(res2) != 2: raise ValueError( "certificate-option does not return a pair in %s" % p) if res1 != res2[0]: raise ValueError("certificate-option changes result in %s" % p)
def test_finite_lattice(L): """ Test several functions on a given finite lattice. The function contains tests of different kinds: - Implications of Boolean properties. Examples: a distributive lattice is modular, a dismantlable and distributive lattice is planar, a simple lattice can not be constructible by Day's doublings. - Dual and self-dual properties. Examples: Dual of a modular lattice is modular, dual of an atomic lattice is co-atomic. - Certificate tests. Example: certificate for a non-complemented lattice must be an element without a complement. - Verification of some property by known property or by a random test. Examples: A lattice is distributive iff join-primes are exactly join-irreducibles and an interval of a relatively complemented lattice is complemented. - Set inclusions. Example: Every co-atom must be meet-irreducible. - And several other tests. Example: The skeleton of a pseudocomplemented lattice must be Boolean. EXAMPLES:: sage: from sage.tests.finite_poset import test_finite_lattice sage: L = posets.RandomLattice(10, 0.98) sage: test_finite_lattice(L) is None # Long time True """ from sage.combinat.posets.lattices import LatticePoset from sage.sets.set import Set from sage.combinat.subset import Subsets from sage.misc.prandom import randint from sage.misc.flatten import flatten from sage.misc.misc import attrcall from sage.misc.sageinspect import sage_getargspec if L.cardinality() < 4: # Special cases should be tested in specific TESTS-sections. return None all_props = set(list(implications) + flatten(implications.values())) P = {x: test_attrcall('is_' + x, L) for x in all_props} ### Relations between boolean-valued properties ### # Direct one-property implications for prop1 in implications: if P[prop1]: for prop2 in implications[prop1]: if not P[prop2]: raise ValueError("error: %s should implicate %s" % (prop1, prop2)) # Impossible combinations for p1, p2 in mutually_exclusive: if P[p1] and P[p2]: raise ValueError( "error: %s and %s should be impossible combination" % (p1, p2)) # Two-property implications for p1, p2, p3 in two_to_one: if P[p1] and P[p2] and not P[p3]: raise ValueError("error: %s and %s, so should be %s" % (p1, p2, p3)) Ldual = L.dual() # Selfdual properties for p in selfdual_properties: if P[p] != test_attrcall('is_' + p, Ldual): raise ValueError("selfdual property %s error" % p) # Dual properties and elements for p1, p2 in dual_properties: if P[p1] != test_attrcall('is_' + p2, Ldual): raise ValueError("dual properties error %s" % p1) for e1, e2 in dual_elements: if set(attrcall(e1)(L)) != set(attrcall(e2)(Ldual)): raise ValueError("dual elements error %s" % e1) ### Certificates ### # Return value must be a pair with correct result as first element. for p_ in all_props: # Dirty fix first if p_[:9] == 'doubling_' or p_[:5] == 'uniq_': continue p = "is_" + p_ if 'certificate' in sage_getargspec(getattr(L, p)).args: res = attrcall(p, certificate=True)(L) if type(res) != type((1, 2)) or len(res) != 2: raise ValueError( "certificate-option does not return a pair in %s" % p) if P[p_] != res[0]: raise ValueError("certificate-option changes result in %s" % p) # Test for "yes"-certificates if P['supersolvable']: a = L.is_supersolvable(certificate=True)[1] S = Subsets(L).random_element() if L.is_chain_of_poset(S): if not L.sublattice(a + list(S)).is_distributive(): raise ValueError("certificate error in is_supersolvable") if P['dismantlable']: elms = L.is_dismantlable(certificate=True)[1] if len(elms) != L.cardinality(): raise ValueError("certificate error 1 in is_dismantlable") elms = elms[:randint(0, len(elms) - 1)] L_ = L.sublattice([x for x in L if x not in elms]) if L_.cardinality() != L.cardinality() - len(elms): raise ValueError("certificate error 2 in is_dismantlable") if P['vertically_decomposable']: c = L.is_vertically_decomposable(certificate=True)[1] if c == L.bottom() or c == L.top(): raise ValueError( "certificate error 1 in is_vertically_decomposable") e = L.random_element() if L.compare_elements(c, e) is None: raise ValueError( "certificate error 2 in is_vertically_decomposable") # Test for "no"-certificates if not P['atomic']: a = L.is_atomic(certificate=True)[1] if a in L.atoms() or a not in L.join_irreducibles(): raise ValueError("certificate error in is_atomic") if not P['coatomic']: a = L.is_coatomic(certificate=True)[1] if a in L.coatoms() or a not in L.meet_irreducibles(): raise ValueError("certificate error in is_coatomic") if not P['complemented']: a = L.is_complemented(certificate=True)[1] if L.complements(a) != []: raise ValueError("compl. error 1") if not P['sectionally_complemented']: a, b = L.is_sectionally_complemented(certificate=True)[1] L_ = L.sublattice(L.interval(L.bottom(), a)) if L_.is_complemented(): raise ValueError("sec. compl. error 1") if len(L_.complements(b)) > 0: raise ValueError("sec. compl. error 2") if not P['cosectionally_complemented']: a, b = L.is_cosectionally_complemented(certificate=True)[1] L_ = L.sublattice(L.interval(a, L.top())) if L_.is_complemented(): raise ValueError("cosec. compl. error 1") if len(L_.complements(b)) > 0: raise ValueError("cosec. compl. error 2") if not P['relatively_complemented']: a, b, c = L.is_relatively_complemented(certificate=True)[1] I = L.interval(a, c) if len(I) != 3 or b not in I: raise ValueError("rel. compl. error 1") if not P['upper_semimodular']: a, b = L.is_upper_semimodular(certificate=True)[1] if not set(L.lower_covers(a)).intersection(set( L.lower_covers(b))) or set(L.upper_covers(a)).intersection( set(L.upper_covers(b))): raise ValueError("certificate error in is_upper_semimodular") if not P['lower_semimodular']: a, b = L.is_lower_semimodular(certificate=True)[1] if set(L.lower_covers(a)).intersection(set( L.lower_covers(b))) or not set(L.upper_covers(a)).intersection( set(L.upper_covers(b))): raise ValueError("certificate error in is_lower_semimodular") if not P['distributive']: x, y, z = L.is_distributive(certificate=True)[1] if L.meet(x, L.join(y, z)) == L.join(L.meet(x, y), L.meet(x, z)): raise ValueError("certificate error in is_distributive") if not P['modular']: x, a, b = L.is_modular(certificate=True)[1] if not L.is_less_than(x, b) or L.join(x, L.meet(a, b)) == L.meet( L.join(x, a), b): raise ValueError("certificate error in is_modular") if not P['pseudocomplemented']: a = L.is_pseudocomplemented(certificate=True)[1] L_ = L.subposet([e for e in L if L.meet(e, a) == L.bottom()]) if L_.has_top(): raise ValueError("certificate error in is_pseudocomplemented") if not P['join_pseudocomplemented']: a = L.is_join_pseudocomplemented(certificate=True)[1] L_ = L.subposet([e for e in L if L.join(e, a) == L.top()]) if L_.has_bottom(): raise ValueError("certificate error in is_join_pseudocomplemented") if not P['join_semidistributive']: e, x, y = L.is_join_semidistributive(certificate=True)[1] if L.join(e, x) != L.join(e, y) or L.join(e, x) == L.join( e, L.meet(x, y)): raise ValueError("certificate error in is_join_semidistributive") if not P['meet_semidistributive']: e, x, y = L.is_meet_semidistributive(certificate=True)[1] if L.meet(e, x) != L.meet(e, y) or L.meet(e, x) == L.meet( e, L.join(x, y)): raise ValueError("certificate error in is_meet_semidistributive") if not P['simple']: c = L.is_simple(certificate=True)[1] if len(L.congruence([c[randint(0, len(c) - 1)]])) == 1: raise ValueError("certificate error in is_simple") if not P['isoform']: c = L.is_isoform(certificate=True)[1] if len(c) == 1: raise ValueError("certificate error in is_isoform") if all( L.subposet(c[i]).is_isomorphic(L.subposet(c[i + 1])) for i in range(len(c) - 1)): raise ValueError("certificate error in is_isoform") if not P['uniform']: c = L.is_uniform(certificate=True)[1] if len(c) == 1: raise ValueError("certificate error in is_uniform") if all(len(c[i]) == len(c[i + 1]) for i in range(len(c) - 1)): raise ValueError("certificate error in is_uniform") if not P['regular']: c = L.is_regular(certificate=True)[1] if len(c[0]) == 1: raise ValueError("certificate error 1 in is_regular") if Set(c[1]) not in c[0]: raise ValueError("certificate error 2 in is_regular") if L.congruence([c[1]]) == c[0]: raise ValueError("certificate error 3 in is_regular") if not P['subdirectly_reducible']: x, y = L.is_subdirectly_reducible(certificate=True)[1] a = L.random_element() b = L.random_element() c = L.congruence([[a, b]]) if len(c) != L.cardinality(): for c_ in c: if x in c_: if y not in c_: raise ValueError( "certificate error 1 in is_subdirectly_reducible") break else: raise ValueError( "certificate error 2 in is_subdirectly_reducible") if not P['join_distributive']: a = L.is_join_distributive(certificate=True)[1] L_ = L.sublattice(L.interval(a, L.join(L.upper_covers(a)))) if L_.is_distributive(): raise ValueError("certificate error in is_join_distributive") if not P['meet_distributive']: a = L.is_meet_distributive(certificate=True)[1] L_ = L.sublattice(L.interval(L.meet(L.lower_covers(a)), a)) if L_.is_distributive(): raise ValueError("certificate error in is_meet_distributive") ### Other ### # Other ways to recognize some boolean property if P['distributive'] != (set(L.join_primes()) == set( L.join_irreducibles())): raise ValueError( "every join-irreducible of a distributive lattice should be join-prime" ) if P['distributive'] != (set(L.meet_primes()) == set( L.meet_irreducibles())): raise ValueError( "every meet-irreducible of a distributive lattice should be meet-prime" ) if P['join_semidistributive'] != all( L.canonical_joinands(e) is not None for e in L): raise ValueError( "every element of join-semidistributive lattice should have canonical joinands" ) if P['meet_semidistributive'] != all( L.canonical_meetands(e) is not None for e in L): raise ValueError( "every element of meet-semidistributive lattice should have canonical meetands" ) # Random verification of a Boolean property if P['relatively_complemented']: a = L.random_element() b = L.random_element() if not L.sublattice(L.interval(a, b)).is_complemented(): raise ValueError("rel. compl. error 3") if P['sectionally_complemented']: a = L.random_element() if not L.sublattice(L.interval(L.bottom(), a)).is_complemented(): raise ValueError("sec. compl. error 3") if P['cosectionally_complemented']: a = L.random_element() if not L.sublattice(L.interval(a, L.top())).is_complemented(): raise ValueError("cosec. compl. error 2") # Element set inclusions for s1, s2 in set_inclusions: if not set(attrcall(s1)(L)).issubset(set(attrcall(s2)(L))): raise ValueError("%s should be a subset of %s" % (s1, s2)) # Sublattice-closed properties L_ = L.sublattice(Subsets(L).random_element()) for p in sublattice_closed: if P[p] and not test_attrcall('is_' + p, L_): raise ValueError("property %s should apply to sublattices" % p) # Some sublattices L_ = L.center() # Center is a Boolean lattice if not L_.is_atomic() or not L_.is_distributive(): raise ValueError("error in center") if P['pseudocomplemented']: L_ = L.skeleton() # Skeleton is a Boolean lattice if not L_.is_atomic() or not L_.is_distributive(): raise ValueError("error in skeleton") L_ = L.frattini_sublattice() S = Subsets(L).random_element() if L.sublattice(S) == L and L.sublattice([e for e in S if e not in L_]) != L: raise ValueError("error in Frattini sublattice") L_ = L.maximal_sublattices() L_ = L_[randint(0, len(L_) - 1)] e = L.random_element() if e not in L_ and L.sublattice(list(L_) + [e]) != L: raise ValueError("error in maximal_sublattices") # Reverse functions: vertical composition and decomposition L_ = reduce(lambda a, b: a.vertical_composition(b), L.vertical_decomposition(), LatticePoset()) if not L.is_isomorphic(L_): raise ValueError("error in vertical [de]composition") # Meet and join a = L.random_element() b = L.random_element() m = L.meet(a, b) j = L.join(a, b) m_ = L.subposet([ e for e in L.principal_lower_set(a) if e in L.principal_lower_set(b) ]).top() j_ = L.subposet([ e for e in L.principal_upper_set(a) if e in L.principal_upper_set(b) ]).bottom() if m != m_ or m != Ldual.join(a, b): raise ValueError("error in meet") if j != j_ or j != Ldual.meet(a, b): raise ValueError("error in join") # Misc misc e = L.neutral_elements() e = e[randint(0, len(e) - 1)] a = L.random_element() b = L.random_element() if not L.sublattice([e, a, b]).is_distributive(): raise ValueError("error in neutral_elements")
""" if hasattr(type, "specialize"): return type.specialize(value) else: return type def GenericMeta_specialize(self, value): return self.copy_with(tuple(specialize(a, value) for a in self.__args__)) _GenericAlias.specialize = GenericMeta_specialize Family = _GenericAlias(sage.sets.family.TrivialFamily, typing.T) class _Facade: pass Facade = _GenericAlias(_Facade, typing.T) Sage = attrcall("sage") # Class for dependent types constructed from a callable value -> type # class DependentType:#(typing._TypingBase): # Singleton #__metaclass__ = typing.TypingMeta __slots__ = ("name", "specialize") # Should be callable? def __init__(self, specialize, name): self.name = name self.specialize = specialize def __instancecheck__(self, object): raise TypeError("Unspecialized {} cannot be used with isinstance()".format(self)) def __repr__(self): return self.name def __call__(self, o):
def test_finite_lattice(L): """ Test several functions on a given finite lattice. The function contains tests of different kinds: - Implications of Boolean properties. Examples: a distributive lattice is modular, a dismantlable and distributive lattice is planar, a simple lattice can not be constructible by Day's doublings. - Dual and self-dual properties. Examples: Dual of a modular lattice is modular, dual of an atomic lattice is co-atomic. - Certificate tests. Example: certificate for a non-complemented lattice must be an element without a complement. - Verification of some property by known property or by a random test. Examples: A lattice is distributive iff join-primes are exactly join-irreducibles and an interval of a relatively complemented lattice is complemented. - Set inclusions. Example: Every co-atom must be meet-irreducible. - And several other tests. Example: The skeleton of a pseudocomplemented lattice must be Boolean. EXAMPLES:: sage: from sage.tests.finite_poset import test_finite_lattice sage: L = posets.RandomLattice(10, 0.98) sage: test_finite_lattice(L) is None # Long time True """ from sage.combinat.posets.lattices import LatticePoset from sage.sets.set import Set from sage.combinat.subset import Subsets from sage.misc.prandom import randint from sage.misc.flatten import flatten from sage.misc.misc import attrcall if L.cardinality() < 4: # Special cases should be tested in specific TESTS-sections. return None all_props = set(list(implications) + flatten(implications.values())) P = {x: test_attrcall('is_' + x, L) for x in all_props} ### Relations between boolean-valued properties ### # Direct one-property implications for prop1 in implications: if P[prop1]: for prop2 in implications[prop1]: if not P[prop2]: raise ValueError("error: %s should implicate %s" % (prop1, prop2)) # Impossible combinations for p1, p2 in mutually_exclusive: if P[p1] and P[p2]: raise ValueError("error: %s and %s should be impossible combination" % (p1, p2)) # Two-property implications for p1, p2, p3 in two_to_one: if P[p1] and P[p2] and not P[p3]: raise ValueError("error: %s and %s, so should be %s" % (p1, p2, p3)) Ldual = L.dual() # Selfdual properties for p in selfdual_properties: if P[p] != test_attrcall('is_'+p, Ldual): raise ValueError("selfdual property %s error" % p) # Dual properties and elements for p1, p2 in dual_properties: if P[p1] != test_attrcall('is_'+p2, Ldual): raise ValueError("dual properties error %s" % p1) for e1, e2 in dual_elements: if set(attrcall(e1)(L)) != set(attrcall(e2)(Ldual)): raise ValueError("dual elements error %s" % e1) ### Certificates ### # Test for "yes"-certificates if P['supersolvable']: a = L.is_supersolvable(certificate=True)[1] S = Subsets(L).random_element() if L.is_chain_of_poset(S): if not L.sublattice(a+list(S)).is_distributive(): raise ValueError("certificate error in is_supersolvable") if P['dismantlable']: elms = L.is_dismantlable(certificate=True)[1] if len(elms) != L.cardinality(): raise ValueError("certificate error 1 in is_dismantlable") elms = elms[:randint(0, len(elms)-1)] L_ = L.sublattice([x for x in L if x not in elms]) if L_.cardinality() != L.cardinality() - len(elms): raise ValueError("certificate error 2 in is_dismantlable") if P['vertically_decomposable']: c = L.is_vertically_decomposable(certificate=True)[1] if c == L.bottom() or c == L.top(): raise ValueError("certificate error 1 in is_vertically_decomposable") e = L.random_element() if L.compare_elements(c, e) is None: raise ValueError("certificate error 2 in is_vertically_decomposable") # Test for "no"-certificates if not P['atomic']: a = L.is_atomic(certificate=True)[1] if a in L.atoms() or a not in L.join_irreducibles(): raise ValueError("certificate error in is_atomic") if not P['coatomic']: a = L.is_coatomic(certificate=True)[1] if a in L.coatoms() or a not in L.meet_irreducibles(): raise ValueError("certificate error in is_coatomic") if not P['complemented']: a = L.is_complemented(certificate=True)[1] if L.complements(a) != []: raise ValueError("compl. error 1") if not P['sectionally_complemented']: a, b = L.is_sectionally_complemented(certificate=True)[1] L_ = L.sublattice(L.interval(L.bottom(), a)) if L_.is_complemented(): raise ValueError("sec. compl. error 1") if len(L_.complements(b)) > 0: raise ValueError("sec. compl. error 2") if not P['cosectionally_complemented']: a, b = L.is_cosectionally_complemented(certificate=True)[1] L_ = L.sublattice(L.interval(a, L.top())) if L_.is_complemented(): raise ValueError("cosec. compl. error 1") if len(L_.complements(b)) > 0: raise ValueError("cosec. compl. error 2") if not P['relatively_complemented']: a, b, c = L.is_relatively_complemented(certificate=True)[1] I = L.interval(a, c) if len(I) != 3 or b not in I: raise ValueError("rel. compl. error 1") if not P['upper_semimodular']: a, b = L.is_upper_semimodular(certificate=True)[1] if not set(L.lower_covers(a)).intersection(set(L.lower_covers(b))) or set(L.upper_covers(a)).intersection(set(L.upper_covers(b))): raise ValueError("certificate error in is_upper_semimodular") if not P['lower_semimodular']: a, b = L.is_lower_semimodular(certificate=True)[1] if set(L.lower_covers(a)).intersection(set(L.lower_covers(b))) or not set(L.upper_covers(a)).intersection(set(L.upper_covers(b))): raise ValueError("certificate error in is_lower_semimodular") if not P['distributive']: x, y, z = L.is_distributive(certificate=True)[1] if L.meet(x, L.join(y, z)) == L.join(L.meet(x, y), L.meet(x, z)): raise ValueError("certificate error in is_distributive") if not P['modular']: x, a, b = L.is_modular(certificate=True)[1] if not L.is_less_than(x, b) or L.join(x, L.meet(a, b)) == L.meet(L.join(x, a), b): raise ValueError("certificate error in is_modular") if not P['pseudocomplemented']: a = L.is_pseudocomplemented(certificate=True)[1] L_ = L.subposet([e for e in L if L.meet(e, a) == L.bottom()]) if L_.has_top(): raise ValueError("certificate error in is_pseudocomplemented") if not P['join_pseudocomplemented']: a = L.is_join_pseudocomplemented(certificate=True)[1] L_ = L.subposet([e for e in L if L.join(e, a) == L.top()]) if L_.has_bottom(): raise ValueError("certificate error in is_join_pseudocomplemented") if not P['join_semidistributive']: e, x, y = L.is_join_semidistributive(certificate=True)[1] if L.join(e, x) != L.join(e, y) or L.join(e, x) == L.join(e, L.meet(x, y)): raise ValueError("certificate error in is_join_semidistributive") if not P['meet_semidistributive']: e, x, y = L.is_meet_semidistributive(certificate=True)[1] if L.meet(e, x) != L.meet(e, y) or L.meet(e, x) == L.meet(e, L.join(x, y)): raise ValueError("certificate error in is_meet_semidistributive") if not P['simple']: c = L.is_simple(certificate=True)[1] if len(L.congruence([c[randint(0, len(c)-1)]])) == 1: raise ValueError("certificate error in is_simple") if not P['isoform']: c = L.is_isoform(certificate=True)[1] if len(c) == 1: raise ValueError("certificate error in is_isoform") if all(L.subposet(c[i]).is_isomorphic(L.subposet(c[i+1])) for i in range(len(c)-1)): raise ValueError("certificate error in is_isoform") if not P['uniform']: c = L.is_uniform(certificate=True)[1] if len(c) == 1: raise ValueError("certificate error in is_uniform") if all(len(c[i]) == len(c[i+1]) for i in range(len(c)-1)): raise ValueError("certificate error in is_uniform") if not P['regular']: c = L.is_regular(certificate=True)[1] if len(c[0]) == 1: raise ValueError("certificate error 1 in is_regular") if Set(c[1]) not in c[0]: raise ValueError("certificate error 2 in is_regular") if L.congruence([c[1]]) == c[0]: raise ValueError("certificate error 3 in is_regular") if not P['subdirectly_reducible']: x, y = L.is_subdirectly_reducible(certificate=True)[1] a = L.random_element(); b = L.random_element() c = L.congruence([[a, b]]) if len(c) != L.cardinality(): for c_ in c: if x in c_: if y not in c_: raise ValueError("certificate error 1 in is_subdirectly_reducible") break else: raise ValueError("certificate error 2 in is_subdirectly_reducible") if not P['join_distributive']: a = L.is_join_distributive(certificate=True)[1] L_ = L.sublattice(L.interval(a, L.join(L.upper_covers(a)))) if L_.is_distributive(): raise ValueError("certificate error in is_join_distributive") if not P['meet_distributive']: a = L.is_meet_distributive(certificate=True)[1] L_ = L.sublattice(L.interval(L.meet(L.lower_covers(a)), a)) if L_.is_distributive(): raise ValueError("certificate error in is_meet_distributive") ### Other ### # Other ways to recognize some boolean property if P['distributive'] != (set(L.join_primes()) == set(L.join_irreducibles())): raise ValueError("every join-irreducible of a distributive lattice should be join-prime") if P['distributive'] != (set(L.meet_primes()) == set(L.meet_irreducibles())): raise ValueError("every meet-irreducible of a distributive lattice should be meet-prime") if P['join_semidistributive'] != all(L.canonical_joinands(e) is not None for e in L): raise ValueError("every element of join-semidistributive lattice should have canonical joinands") if P['meet_semidistributive'] != all(L.canonical_meetands(e) is not None for e in L): raise ValueError("every element of meet-semidistributive lattice should have canonical meetands") # Random verification of a Boolean property if P['relatively_complemented']: a = L.random_element() b = L.random_element() if not L.sublattice(L.interval(a, b)).is_complemented(): raise ValueError("rel. compl. error 3") if P['sectionally_complemented']: a = L.random_element() if not L.sublattice(L.interval(L.bottom(), a)).is_complemented(): raise ValueError("sec. compl. error 3") if P['cosectionally_complemented']: a = L.random_element() if not L.sublattice(L.interval(a, L.top())).is_complemented(): raise ValueError("cosec. compl. error 2") # Element set inclusions for s1, s2 in set_inclusions: if not set(attrcall(s1)(L)).issubset(set(attrcall(s2)(L))): raise ValueError("%s should be a subset of %s" % (s1, s2)) # Sublattice-closed properties L_ = L.sublattice(Subsets(L).random_element()) for p in sublattice_closed: if P[p] and not test_attrcall('is_'+p, L_): raise ValueError("property %s should apply to sublattices" % p) # Some sublattices L_ = L.center() # Center is a Boolean lattice if not L_.is_atomic() or not L_.is_distributive(): raise ValueError("error in center") if P['pseudocomplemented']: L_ = L.skeleton() # Skeleton is a Boolean lattice if not L_.is_atomic() or not L_.is_distributive(): raise ValueError("error in skeleton") L_ = L.frattini_sublattice() S = Subsets(L).random_element() if L.sublattice(S) == L and L.sublattice([e for e in S if e not in L_]) != L: raise ValueError("error in Frattini sublattice") L_ = L.maximal_sublattices() L_ = L_[randint(0, len(L_)-1)] e = L.random_element() if e not in L_ and L.sublattice(list(L_)+[e]) != L: raise ValueError("error in maximal_sublattices") # Reverse functions: vertical composition and decomposition L_ = reduce(lambda a, b: a.vertical_composition(b), L.vertical_decomposition(), LatticePoset()) if not L.is_isomorphic(L_): raise ValueError("error in vertical [de]composition") # Meet and join a = L.random_element() b = L.random_element() m = L.meet(a, b) j = L.join(a, b) m_ = L.subposet([e for e in L.principal_lower_set(a) if e in L.principal_lower_set(b)]).top() j_ = L.subposet([e for e in L.principal_upper_set(a) if e in L.principal_upper_set(b)]).bottom() if m != m_ or m != Ldual.join(a, b): raise ValueError("error in meet") if j != j_ or j != Ldual.meet(a, b): raise ValueError("error in join") # Misc misc e = L.neutral_elements() e = e[randint(0, len(e)-1)] a = L.random_element(); b = L.random_element() if not L.sublattice([e, a, b]).is_distributive(): raise ValueError("error in neutral_elements")
def f(i): """ # TODO NICOLAS add documentation """ return attrcall("polarization", i1=i + 1, i2=i, d=1)
def hom_to_module(self, module): """ INPUT: - ``module`` -- a vector space affording a representation of ``self.semigroup()`` implemented as ``module.action(s, x)`` Assume that this module is cyclic, with generator `g` (see :meth:`module_generator`), and let `S` be the semigroup acting on ``self`` (see :meth:`self.semigroup`). For short, we write `x . s` the action of `s` on `x`. This returns the subspace `M` of all elements `x` of ``module`` such that `g \mapsto x` extends to a morphism of `S`-modules; equivalently `x` must satisfy the following system of linear equations: .. math: g . s = None \Rightarrow x . s = 0, \forall s\in S .. math: g . s == g. t \Rightarrow x . s == x . t, \forall s,t\in S In practice, the system of equation can be reduced to one equation for each pair `u,i` with `u` in ``self`` and `i` index of a semigroup generator of `S`. EXAMPLES:: The cayley graph of the regular left class of the bi-Hecke monoid indexed by 13452:: sage: big = DiGraph([(0, 0, -3), (0, 0, 3), (0, 1, -4), (0, 3, 2), ... (1, 0, 3), (1, 1, -4), (1, 1, 4), ... (2, 1, -4), (2, 2, -3), (2, 2, 3), (2, 3, 2), ... (3, 2, -3), (3, 3, -2), (3, 3, 2) ... ]).transition_module() sage: small = DiGraph([(0, 0, -2), (0, 0, 2)]).transition_module() """ from sage.misc.misc import attrcall alphabet = self.semigroup().semigroup_generators().keys() S = module.semigroup() s = S.semigroup_generators() assert set(alphabet).issubset(set(s.keys())) # Let's see they Cayley graph of ``self`` as an automaton G = self.cayley_graph() # Now we build, for each vertex `u`, a shortest word `w_u` in the # alphabet mapping ``self.module_generator()`` to `u`. # Below we write `s_{w_u}` for the element of the semigroup # corresponding to `w_u`. paths = G.shortest_paths(self.module_generator()) words = dict( (u, tuple( G.edge_label(path[i],path[i+1])[0] for i in range(len(path)-1) )) for u,path in paths.iteritems() ) @cached_function def word_action(word, x): """ INPUT: - ``word`` -- a tuple `i_1,\dots,i_k` in the generators of ``S`` representing a path in ``G`` - ``x`` -- and element of ``module`` Writing x.s for the result of the action of `s\in S` on `x`, this returns ``x.s_{i_1}.\dots.s_{i_k}``. The result is cached over prefixes. This function will only be called for `x` in the basis of ``module``. """ if len(word) == 0: return x else: return module.action(s[word[-1]], word_action(word[:-1], x)) def biword_action(word1, word2, x): """ Return the difference of the action of word1 and word2 on `x` """ return word_action(word1,x) - word_action(word2,x) # Build the equations, encoded as linear morphisms morphisms = [] alphabet = S.semigroup_generators().keys() for u in G.vertices(): for i in alphabet: v = G.transition(u,i) if v is None: # Add morphism `x -> x . s_{w_u} s_i` morphisms.append( functools.partial(word_action, words[u]+(i,) ) ) else: # Add morphism `x -> x . s_{w_u} s_i - x . s_{w_v}` morphisms.append( functools.partial(biword_action, words[u]+(i,), words[v] ) ) # Computes the joint kernel of those morphisms. return module.annihilator( morphisms, action = attrcall("__call__"), side = "left" )