def extra_super_categories(self): """ Implement the fact that a `J`-trivial semigroup is `L` and `R`-trivial. EXAMPLES:: sage: Semigroups().JTrivial().extra_super_categories() [Category of l trivial semigroups, Category of r trivial semigroups] """ return [Semigroups().LTrivial(), Semigroups().RTrivial()]
def example(self): r""" EXAMPLES:: sage: Semigroups().FinitelyGenerated().example() An example of a semigroup: the free semigroup generated by ('a', 'b', 'c', 'd') """ return Semigroups().example("free")
def extra_super_categories(self): r""" Implement the fact that an aperiodic semigroup is `H`-trivial. EXAMPLES:: sage: Semigroups().Aperiodic().extra_super_categories() [Category of h trivial semigroups] """ return [Semigroups().HTrivial()]
def super_categories(self): r""" Returns a list of the (immediate) super categories of ``self``. EXAMPLES:: sage: FiniteSemigroups().super_categories() [Category of semigroups, Category of finite enumerated sets] """ return [Semigroups(), FiniteEnumeratedSets()]
def super_categories(self): """ Returns a list of the immediate super categories of ``self``. EXAMPLES:: sage: Monoids().super_categories() [Category of semigroups] """ return [Semigroups()]
def Finite_extra_super_categories(self): r""" Implement the fact that a finite `H`-trivial is aperiodic EXAMPLES:: sage: Semigroups().HTrivial().Finite_extra_super_categories() [Category of aperiodic semigroups] sage: Semigroups().HTrivial().Finite() is Semigroups().Aperiodic().Finite() True """ return [Semigroups().Aperiodic()]
def extra_super_categories(self): """ EXAMPLES:: sage: from sage.categories.additive_semigroups import AdditiveSemigroups sage: AdditiveSemigroups().Algebras(QQ).extra_super_categories() [Category of semigroups] sage: CommutativeAdditiveSemigroups().Algebras(QQ).super_categories() [Category of additive semigroup algebras over Rational Field, Category of additive commutative additive magma algebras over Rational Field] """ from sage.categories.semigroups import Semigroups return [Semigroups()]
def __init__(self, alphabet=('a','b','c','d')): r""" A left regular band. EXAMPLES:: sage: S = FiniteSemigroups().example(); S An example of a finite semigroup: the left regular band generated by ('a', 'b', 'c', 'd') sage: S = FiniteSemigroups().example(alphabet=('x','y')); S An example of a finite semigroup: the left regular band generated by ('x', 'y') sage: TestSuite(S).run() """ self.alphabet = alphabet Parent.__init__(self, category = Semigroups().Finite().FinitelyGenerated())
def _repr_(self): """ Return the string representation for ``self``. EXAMPLES:: sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup sage: R = IntegerModRing(12) sage: AutomaticSemigroup(Family({1: R(3), 2: R(5)}), one=R.one()) A submonoid of (Ring of integers modulo 12) with 2 generators sage: AutomaticSemigroup(Family({1: R(3), 2: R(5)})) A subsemigroup of (Ring of integers modulo 12) with 2 generators sage: AutomaticSemigroup(Family({1: R(3), 2: R(5)}), mul=operator.add) A semigroup with 2 generators sage: AutomaticSemigroup(Family({1: R(3), 2: R(5)}), mul=operator.add, one=R.zero()) A semigroup with 2 generators sage: S5 = SymmetricGroup(5); S5.rename("S5") sage: AutomaticSemigroup(Family({1: S5((1,2))}), category=Groups().Finite().Subobjects()) A subgroup of (S5) with 1 generators """ categories = [Groups(), Monoids(), Semigroups()] for category in categories: if self in category: typ = "A " + category._repr_object_names()[:-1] for category in [Groups(), Monoids(), Semigroups()]: if self.ambient() in category and self in category.Subobjects(): typ = "A sub" + category._repr_object_names()[:-1] break if self._mul is operator.mul: of = " of (%s)" % self.ambient() else: of = "" return "%s%s with %s generators" % (typ, of, len(self._generators))
def example(self, alphabet=('a', 'b', 'c')): """ Returns an example of (finite) right trivial semigroup .. SEEALSO:: :meth:`Category.example` EXAMPLES:: sage: S = Semigroups().RTrivial().example(); S An example of a finite semigroup: the left regular band generated by ('a', 'b', 'c', 'd') sage: S.category() Category of finite r trivial semigroups """ from sage.categories.examples.finite_semigroups import LeftRegularBand return LeftRegularBand( alphabet=alphabet, category=Semigroups().RTrivial().Finite().FinitelyGenerated())
def extra_super_categories(self): r""" EXAMPLES: Any aperiodic monoid is H-trivial:: sage: Semigroups().Aperiodic().super_categories() [Category of h trivial semigroups] This methods implements the fact that reciprocally any finite H-trivial semigroup is aperiodic:: sage: Semigroups().HTrivial().Finite().extra_super_categories() [Category of aperiodic semigroups] sage: Semigroups().HTrivial().Finite().super_categories() [Category of finite semigroups, Category of aperiodic semigroups] .. seealso:: :meth:`sage.categories.adjective_category.AdjectiveCategory.extra_super_category` """ return [Semigroups().Aperiodic()]
def __init__(self, Q): """ Initialize ``self``. INPUT: - a :class:`~sage.graphs.digraph.DiGraph`. EXAMPLES: Note that usually a path semigroup is created using :meth:`sage.graphs.digraph.DiGraph.path_semigroup`. Here, we demonstrate the direct construction:: sage: Q = DiGraph({1:{2:['a','b'], 3:['c']}, 2:{3:['d']}}, immutable=True) sage: from sage.quivers.path_semigroup import PathSemigroup sage: P = PathSemigroup(Q) sage: P is DiGraph({1:{2:['a','b'], 3:['c']}, 2:{3:['d']}}).path_semigroup() # indirect doctest True sage: P Partial semigroup formed by the directed paths of Multi-digraph on 3 vertices While hardly of any use, it is possible to construct the path semigroup of an empty quiver (it is, of course, empty):: sage: D = DiGraph({}) sage: A = D.path_semigroup(); A Partial semigroup formed by the directed paths of Digraph on 0 vertices sage: A.list() [] .. TODO:: When the graph has more than one edge, the proper category would be a "partial semigroup" or a "semigroupoid" but definitely not a semigroup! """ ######### ## Verify that the graph labels are acceptable for this implementation ## # Check that edges are labelled with nonempty strings and don't begin # with 'e_' or contain '*' labels = Q.edge_labels() if len(set(labels)) != len(labels): raise ValueError("edge labels of the digraph must be unique") for x in labels: if not isinstance(x, str) or x == '': raise ValueError("edge labels of the digraph must be nonempty strings") if x[0:2] == 'e_': raise ValueError("edge labels of the digraph must not begin with 'e_'") if x.find('*') != -1: raise ValueError("edge labels of the digraph must not contain '*'") # Check validity of input: vertices have to be labelled 1,2,3,... and # edge labels must be unique for v in Q: if not isinstance(v, integer_types + (Integer,)): raise ValueError("vertices of the digraph must be labelled by integers") ## Determine the category which this (partial) semigroup belongs to if Q.is_directed_acyclic(): cat = FiniteEnumeratedSets() else: cat = InfiniteEnumeratedSets() self._sorted_edges = tuple(sorted(Q.edges(), key=lambda x:x[2])) self._labels = tuple([x[2] for x in self._sorted_edges]) self._label_index = {s[2]: i for i,s in enumerate(self._sorted_edges)} self._nb_arrows = max(len(self._sorted_edges), 1) names = ['e_{0}'.format(v) for v in Q.vertices()] + list(self._labels) self._quiver = Q if Q.num_verts() == 1: cat = cat.join([cat,Monoids()]) else: cat = cat.join([cat,Semigroups()]) Parent.__init__(self, names=names, category=cat)
def __classcall_private__(cls, generators, ambient=None, one=None, mul=operator.mul, category=None): """ Parse and straighten the arguments; figure out the category. TESTS:: sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup sage: R = IntegerModRing(9) sage: M = AutomaticSemigroup((), one=R.one()) sage: M.ambient() == R True sage: AutomaticSemigroup((0,)).category() Join of Category of finitely generated semigroups and Category of subquotients of semigroups and Category of commutative magmas and Category of subobjects of sets sage: AutomaticSemigroup((0,), one=1).category() Join of Category of subquotients of monoids and Category of commutative monoids and Category of finitely generated semigroups and Category of subobjects of sets sage: AutomaticSemigroup((0,), one=0).category() Join of Category of commutative monoids and Category of finitely generated semigroups and Category of subquotients of semigroups and Category of subobjects of sets sage: AutomaticSemigroup((0,), mul=operator.add).category() Join of Category of semigroups and Category of subobjects of sets sage: AutomaticSemigroup((0,), one=0, mul=operator.add).category() Join of Category of monoids and Category of subobjects of sets sage: S5 = SymmetricGroup(5) sage: AutomaticSemigroup([S5((1,2))]).category() Join of Category of finite groups and Category of subquotients of monoids and Category of finite finitely generated semigroups and Category of subquotients of finite sets and Category of subobjects of sets .. TODO:: One would want a subsemigroup of a group to be automatically a subgroup (in ``Groups().Subobjects()``). """ generators = Family(generators) if ambient is None: # Try to guess the ambient semigroup from the generators or the unit if generators.cardinality() > 0: ambient = generators.first().parent() elif one is not None: ambient = one.parent() else: raise ValueError( "AutomaticSemigroup requires at least one generator or `one` to determine the ambient space" ) elif ambient not in Sets: raise ValueError("ambient (=%s) should be a set" % ambient) # if mul is not operator.mul and category.is_subcategory(Monoids().Subobjects()) error if one is None and category is not None: if category.is_subcategory(Monoids().Subobjects()): one = ambient.one() elif category.is_subcategory(Monoids()): raise ValueError( "For a monoid which is just a subsemigroup, the unit should be specified" ) # Try to determine the most specific category # This logic should be in the categories if mul is operator.mul: default_category = Semigroups().FinitelyGenerated() if one is not None and one == ambient.one(): default_category = default_category.Unital() if ambient in Semigroups().Commutative(): default_category = default_category.Commutative() if ambient in Groups().Finite(): default_category = default_category & Groups() else: default_category = Sets() if ambient in Sets().Finite(): default_category = default_category.Finite() default_category = default_category.Subobjects() & Semigroups() if one is not None: default_category = default_category.Unital() cls = AutomaticMonoid if category is None: category = default_category else: category = default_category & category return super(AutomaticSemigroup, cls).__classcall__(cls, generators, ambient=ambient, one=one, mul=mul, category=category)
def super_categories(self): return [Semigroups()]
class Subobjects(SubobjectsCategory): class ParentMethods: def domain(self): return self.ambient().domain() class ElementMethods: def __call__(self, *args): return self.lift()(*args) def image_set(self): return self.lift().image_set() def rank(self): return self.lift().rank() def fibers(self): return self.lift().fibers() def domain(self): return self.lift().domain() def codomain(self): return self.lift().codomain() Semigroups.Transformation = TransformationSemigroups Semigroups().subcategory_class.Transformation = lambda self: self._with_axiom( "Transformation")
def __init__(self, jmonoid): assert (jmonoid in Monoids().JTrivial().Finite()) self.jmonoid = jmonoid Parent.__init__(self, category=Semigroups().Finite())
def __init__(self, Q): """ Initialize ``self``. INPUT: - a :class:`~sage.graphs.digraph.DiGraph`. EXAMPLES: Note that usually a path semigroup is created using :meth:`sage.graphs.digraph.DiGraph.path_semigroup`. Here, we demonstrate the direct construction:: sage: Q = DiGraph({1:{2:['a','b'], 3:['c']}, 2:{3:['d']}}, immutable=True) sage: from sage.quivers.path_semigroup import PathSemigroup sage: P = PathSemigroup(Q) sage: P is DiGraph({1:{2:['a','b'], 3:['c']}, 2:{3:['d']}}).path_semigroup() # indirect doctest True sage: P Partial semigroup formed by the directed paths of Multi-digraph on 3 vertices While hardly of any use, it is possible to construct the path semigroup of an empty quiver (it is, of course, empty):: sage: D = DiGraph({}) sage: A = D.path_semigroup(); A Partial semigroup formed by the directed paths of Digraph on 0 vertices sage: A.list() [] """ ######### ## Verify that the graph labels are acceptable for this implementation ## # Check that edges are labelled with nonempty strings and don't begin # with 'e_' or contain '*' for x in Q.edge_labels(): if not isinstance(x, str) or x == '': raise ValueError( "edge labels of the digraph must be nonempty strings") if x[0:2] == 'e_': raise ValueError( "edge labels of the digraph must not begin with 'e_'") if x.find('*') != -1: raise ValueError( "edge labels of the digraph must not contain '*'") # Check validity of input: vertices have to be labelled 1,2,3,... and # edge labels must be unique for v in Q: if v not in ZZ: raise ValueError( "vertices of the digraph must be labelled by integers") if len(set(Q.edge_labels())) != Q.num_edges(): raise ValueError("edge labels of the digraph must be unique") nvert = len(Q.vertices()) ## Determine the category which this (partial) semigroup belongs to if Q.is_directed_acyclic() and not Q.has_loops(): cat = FiniteEnumeratedSets() else: cat = InfiniteEnumeratedSets() names = ['e_{0}'.format(v) for v in Q.vertices()] + [e[2] for e in Q.edges()] self._quiver = Q if nvert == 1: cat = cat.join([cat, Monoids()]) else: # TODO: Make this the category of "partial semigroups" cat = cat.join([cat, Semigroups()]) Parent.__init__(self, names=names, category=cat)