class AnalyticType(FiniteLatticePoset): r""" Container for all possible analytic types of forms and/or spaces The ``analytic type`` of forms spaces or rings describes all possible occuring basic ``analytic properties`` of elements in the space/ring (or more). For ambient spaces/rings this means that all elements with those properties (and the restrictions of the space/ring) are contained in the space/ring. The analytic type of an element is the analytic type of its minimal ambient space/ring. The basic ``analytic properties`` are: - ``quasi`` - Whether the element is quasi modular (and not modular) or modular. - ``mero`` - ``meromorphic``: If the element is meromorphic and meromorphic at infinity. - ``weak`` - ``weakly holomorphic``: If the element is holomorphic and meromorphic at infinity. - ``holo`` - ``holomorphic``: If the element is holomorphic and holomorphic at infinity. - ``cusp`` - ``cuspidal``: If the element additionally has a positive order at infinity. The ``zero`` elements/property have no analytic properties (or only ``quasi``). For ring elements the property describes whether one of its homogeneous components satisfies that property and the "union" of those properties is returned as the ``analytic type``. Similarly for quasi forms the property describes whether one of its quasi components satisfies that property. There is a (natural) partial order between the basic properties (and analytic types) given by "inclusion". We name the analytic type according to its maximal analytic properties. EXAMPLES:: For n=3 the quasi form ``el = E6 - E2^3`` has the quasi components ``E6`` which is ``holomorphic`` and ``E2^3`` which is ``quasi holomorphic``. So the analytic type of ``el`` is ``quasi holomorphic`` despite the fact that the sum (``el``) describes a function which is zero at infinity. sage: from space import QModularForms sage: x,y,z,d = var("x,y,z,d") sage: el = QModularForms(group=3, k=6, ep=-1)(y-z^3) sage: el.analytic_type() quasi modular Similarly the type of the ring element ``el2 = E4/Delta - E6/Delta`` is ``weakly holomorphic`` despite the fact that the sum (``el2``) describes a function which is holomorphic at infinity. sage: from graded_ring import WeakModularFormsRing sage: x,y,z,d = var("x,y,z,d") sage: el2 = WeakModularFormsRing(group=3)(x/(x^3-y^2)-y/(x^3-y^2)) sage: el2.analytic_type() weakly holomorphic modular """ Element = AnalyticTypeElement @staticmethod def __classcall__(cls): r""" Directly return the classcall of UniqueRepresentation (skipping the classcalls of the other superclasses). That's because ``self`` is supposed to be used as a Singleton. It initializes the FinitelatticePoset with the proper arguments by itself in ``self.__init__()``. EXAMPLES:: sage: AT = AnalyticType() sage: AT2 = AnalyticType() sage: AT == AT2 True """ return super(FinitePoset, cls).__classcall__(cls) def __init__(self): r""" Container for all possible analytic types of forms and/or spaces. This class is supposed to be used as a Singleton. It first creates a ``Poset`` that contains all basic analytic properties to be modeled by the AnalyticType. Then the order ideals lattice of that Poset is taken as the underlying FiniteLatticePoset of ``self``. In particular elements of ``self`` describe what basic analytic properties are contained/included in that element. EXAMPLES:: sage: AT = AnalyticType() sage: AT Analytic Type sage: isinstance(AT, FiniteLatticePoset) True sage: AT.is_lattice() True sage: AT.is_finite() True sage: AT.cardinality() 10 sage: AT.is_modular() True sage: AT.is_bounded() True sage: AT.is_distributive() True sage: AT.list() [zero, zero, cuspidal, modular, weakly holomorphic modular, quasi cuspidal, quasi modular, quasi weakly holomorphic modular, meromorphic modular, quasi meromorphic modular] sage: len(AT.relations()) 45 sage: AT.cover_relations() [[zero, zero], [zero, cuspidal], [zero, quasi cuspidal], [cuspidal, modular], [cuspidal, quasi cuspidal], [modular, weakly holomorphic modular], [modular, quasi modular], [weakly holomorphic modular, quasi weakly holomorphic modular], [weakly holomorphic modular, meromorphic modular], [quasi cuspidal, quasi modular], [quasi modular, quasi weakly holomorphic modular], [quasi weakly holomorphic modular, quasi meromorphic modular], [meromorphic modular, quasi meromorphic modular]] sage: AT.has_top() True sage: AT.has_bottom() True sage: AT.top() quasi meromorphic modular sage: AT.bottom() zero """ # We (arbitrarily) choose to model by inclusion instead of restriction P_elements = [ "cusp", "holo", "weak", "mero", "quasi"] P_relations = [["cusp", "holo"], ["holo", "weak"], ["weak", "mero"]] self._base_poset = Poset([P_elements, P_relations], cover_relations=True, facade=False) L = self._base_poset.order_ideals_lattice() L = FiniteLatticePoset(L, facade=False) FiniteLatticePoset.__init__(self, hasse_diagram=L._hasse_diagram, elements=L._elements, category=L.category(), facade=L._is_facade, key=None) def _repr_(self): r""" Return the string representation of ``self``. EXAMPLES:: sage: AnalyticType() Analytic Type """ return "Analytic Type" def __call__(self, *args, **kwargs): r""" Return the result of the corresponding call function of ``FiniteLatticePoset``. If more than one argument is given it is called with the list of those arguments instead. EXAMPLES:: sage: AT = AnalyticType() sage: AT("holo", "quasi") == AT(["holo", "quasi"]) True """ if len(args)>1: return super(AnalyticType,self).__call__([arg for arg in args], **kwargs) else: return super(AnalyticType,self).__call__(*args, **kwargs) def _element_constructor_(self, element): r""" Return ``element`` coerced into an element of ``self``. INPUT: - ``element`` - Either something which coerces in the ``FiniteLatticePoset`` of ``self`` or a string or a list of strings of basic properties that should be contained in the new element. OUTPUT: An element of ``self`` corresponding to ``element`` (resp. containing all specified basic analytic properties). EXAMPLES:: sage: AT = AnalyticType() sage: AT("holo") == AT(["holo"]) True sage: el = AT(["quasi", "holo"]) sage: el quasi modular sage: el == AT(("holo", "quasi")) True sage: el.parent() == AT True sage: isinstance(el, AnalyticTypeElement) True sage: el.element {holo, cusp, quasi} """ if type(element)==str: element=[element] if isinstance(element,list) or isinstance(element,tuple): element = Set(self._base_poset.order_ideal([self._base_poset(s) for s in element])) return super(AnalyticType, self)._element_constructor_(element) #res = self.first() #for element in args: # if type(element)==str: # element=[element] # if isinstance(element,list) or isinstance(element,tuple): # element = Set(self._base_poset.order_ideal([self._base_poset(s) for s in element])) # element = super(AnalyticType,self)._element_constructor_(element) # res += element #return res def base_poset(self): r""" Return the base poset from which everything of ``self`` was constructed. Elements of the base poset correspond to the basic ``analytic properties``. EXAMPLES:: sage: AT = AnalyticType() sage: P = AT.base_poset() sage: P Finite poset containing 5 elements sage: isinstance(P, FinitePoset) True sage: P.is_lattice() False sage: P.is_finite() True sage: P.cardinality() 5 sage: P.is_bounded() False sage: P.list() [quasi, cusp, holo, weak, mero] sage: len(P.relations()) 11 sage: P.cover_relations() [[cusp, holo], [holo, weak], [weak, mero]] sage: P.has_top() False sage: P.has_bottom() False """ return self._base_poset def lattice_poset(self): r""" Return the underlying lattice poset of ``self``. EXAMPLES:: sage: AnalyticType().lattice_poset() Finite lattice containing 10 elements """ return FiniteLatticePoset(self._base_poset.order_ideals_lattice(), facade=False)
class AnalyticType(FiniteLatticePoset): r""" Container for all possible analytic types of forms and/or spaces. The ``analytic type`` of forms spaces or rings describes all possible occuring basic ``analytic properties`` of elements in the space/ring (or more). For ambient spaces/rings this means that all elements with those properties (and the restrictions of the space/ring) are contained in the space/ring. The analytic type of an element is the analytic type of its minimal ambient space/ring. The basic ``analytic properties`` are: - ``quasi`` - Whether the element is quasi modular (and not modular) or modular. - ``mero`` - ``meromorphic``: If the element is meromorphic and meromorphic at infinity. - ``weak`` - ``weakly holomorphic``: If the element is holomorphic and meromorphic at infinity. - ``holo`` - ``holomorphic``: If the element is holomorphic and holomorphic at infinity. - ``cusp`` - ``cuspidal``: If the element additionally has a positive order at infinity. The ``zero`` elements/property have no analytic properties (or only ``quasi``). For ring elements the property describes whether one of its homogeneous components satisfies that property and the "union" of those properties is returned as the ``analytic type``. Similarly for quasi forms the property describes whether one of its quasi components satisfies that property. There is a (natural) partial order between the basic properties (and analytic types) given by "inclusion". We name the analytic type according to its maximal analytic properties. EXAMPLES: For `n=3` the quasi form ``el = E6 - E2^3`` has the quasi components ``E6`` which is ``holomorphic`` and ``E2^3`` which is ``quasi holomorphic``. So the analytic type of ``el`` is ``quasi holomorphic`` despite the fact that the sum (``el``) describes a function which is zero at infinity. :: sage: from sage.modular.modform_hecketriangle.space import QuasiModularForms sage: x,y,z,d = var("x,y,z,d") sage: el = QuasiModularForms(n=3, k=6, ep=-1)(y-z^3) sage: el.analytic_type() quasi modular Similarly the type of the ring element ``el2 = E4/Delta - E6/Delta`` is ``weakly holomorphic`` despite the fact that the sum (``el2``) describes a function which is holomorphic at infinity. sage: from sage.modular.modform_hecketriangle.graded_ring import WeakModularFormsRing sage: x,y,z,d = var("x,y,z,d") sage: el2 = WeakModularFormsRing(n=3)(x/(x^3-y^2)-y/(x^3-y^2)) sage: el2.analytic_type() weakly holomorphic modular """ Element = AnalyticTypeElement @staticmethod def __classcall__(cls): r""" Directly return the classcall of UniqueRepresentation (skipping the classcalls of the other superclasses). That's because ``self`` is supposed to be used as a Singleton. It initializes the FinitelatticePoset with the proper arguments by itself in ``self.__init__()``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.analytic_type import AnalyticType sage: AT = AnalyticType() sage: AT2 = AnalyticType() sage: AT is AT2 True """ return super(FinitePoset, cls).__classcall__(cls) def __init__(self): r""" Container for all possible analytic types of forms and/or spaces. This class is supposed to be used as a Singleton. It first creates a ``Poset`` that contains all basic analytic properties to be modeled by the AnalyticType. Then the order ideals lattice of that Poset is taken as the underlying FiniteLatticePoset of ``self``. In particular elements of ``self`` describe what basic analytic properties are contained/included in that element. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.analytic_type import AnalyticType sage: from sage.combinat.posets.lattices import FiniteLatticePoset sage: AT = AnalyticType() sage: AT Analytic Type sage: isinstance(AT, FiniteLatticePoset) True sage: AT.is_lattice() True sage: AT.is_finite() True sage: AT.cardinality() 10 sage: AT.is_modular() True sage: AT.is_bounded() True sage: AT.is_distributive() True sage: AT.list() [zero, cuspidal, zero, modular, weakly holomorphic modular, meromorphic modular, quasi cuspidal, quasi modular, quasi weakly holomorphic modular, quasi meromorphic modular] sage: len(AT.relations()) 45 sage: AT.cover_relations() [[zero, cuspidal], [zero, zero], [cuspidal, modular], [cuspidal, quasi cuspidal], [zero, quasi cuspidal], [modular, weakly holomorphic modular], [modular, quasi modular], [weakly holomorphic modular, meromorphic modular], [weakly holomorphic modular, quasi weakly holomorphic modular], [meromorphic modular, quasi meromorphic modular], [quasi cuspidal, quasi modular], [quasi modular, quasi weakly holomorphic modular], [quasi weakly holomorphic modular, quasi meromorphic modular]] sage: AT.has_top() True sage: AT.has_bottom() True sage: AT.top() quasi meromorphic modular sage: AT.bottom() zero """ # We (arbitrarily) choose to model by inclusion instead of restriction P_elements = ["cusp", "holo", "weak", "mero", "quasi"] P_relations = [["cusp", "holo"], ["holo", "weak"], ["weak", "mero"]] self._base_poset = Poset([P_elements, P_relations], cover_relations=True, linear_extension=True, facade=False) L = self._base_poset.order_ideals_lattice() H = L._hasse_diagram.relabel({i: x for i, x in enumerate(L._elements)}, inplace=False) FiniteLatticePoset.__init__(self, hasse_diagram=H, elements=L._elements, category=L.category(), facade=False, key=None) def _repr_(self): r""" Return the string representation of ``self``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.analytic_type import AnalyticType sage: AnalyticType() Analytic Type """ return "Analytic Type" def __call__(self, *args, **kwargs): r""" Return the result of the corresponding call function of ``FiniteLatticePoset``. If more than one argument is given it is called with the list of those arguments instead. .. NOTE:: The function just extends the ``__call__`` function to allow multiple arguments (see the example below). EXAMPLES:: sage: from sage.modular.modform_hecketriangle.analytic_type import AnalyticType sage: AT = AnalyticType() sage: AT("holo", "quasi") == AT(["holo", "quasi"]) True """ if len(args) > 1: return super(AnalyticType, self).__call__([arg for arg in args], **kwargs) else: return super(AnalyticType, self).__call__(*args, **kwargs) def _element_constructor_(self, element): r""" Return ``element`` coerced into an element of ``self``. INPUT: - ``element`` -- Either something which coerces in the ``FiniteLatticePoset`` of ``self`` or a string or a list of strings of basic properties that should be contained in the new element. OUTPUT: An element of ``self`` corresponding to ``element`` (resp. containing all specified basic analytic properties). EXAMPLES:: sage: from sage.modular.modform_hecketriangle.analytic_type import (AnalyticType, AnalyticTypeElement) sage: AT = AnalyticType() sage: AT("holo") == AT(["holo"]) True sage: el = AT(["quasi", "holo"]) sage: el quasi modular sage: el == AT(("holo", "quasi")) True sage: el.parent() == AT True sage: isinstance(el, AnalyticTypeElement) True sage: el.element {holo, cusp, quasi} """ if isinstance(element, str): element = [element] if isinstance(element, list) or isinstance(element, tuple): element = Set( self._base_poset.order_ideal( [self._base_poset(s) for s in element])) return super(AnalyticType, self)._element_constructor_(element) #res = self.first() #for element in args: # if type(element)==str: # element=[element] # if isinstance(element,list) or isinstance(element,tuple): # element = Set(self._base_poset.order_ideal([self._base_poset(s) for s in element])) # element = super(AnalyticType,self)._element_constructor_(element) # res += element #return res def base_poset(self): r""" Return the base poset from which everything of ``self`` was constructed. Elements of the base poset correspond to the basic ``analytic properties``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.analytic_type import AnalyticType sage: from sage.combinat.posets.posets import FinitePoset sage: AT = AnalyticType() sage: P = AT.base_poset() sage: P Finite poset containing 5 elements with distinguished linear extension sage: isinstance(P, FinitePoset) True sage: P.is_lattice() False sage: P.is_finite() True sage: P.cardinality() 5 sage: P.is_bounded() False sage: P.list() [cusp, holo, weak, mero, quasi] sage: len(P.relations()) 11 sage: P.cover_relations() [[cusp, holo], [holo, weak], [weak, mero]] sage: P.has_top() False sage: P.has_bottom() False """ return self._base_poset def lattice_poset(self): r""" Return the underlying lattice poset of ``self``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.analytic_type import AnalyticType sage: AnalyticType().lattice_poset() Finite lattice containing 10 elements """ return FiniteLatticePoset(self._base_poset.order_ideals_lattice(), facade=False)