# Ticket #8800: some_ideas.patch

File some_ideas.patch, 32.0 KB (added by lftabera, 12 years ago)

Ideas to consider merging

• ## doc/en/reference/categories.rst

```# HG changeset patch
# Parent 74c911071a9a7ea5e77000bc00f3de2a9f0fdb07

diff -r 74c911071a9a doc/en/reference/categories.rst```
 a sage/categories/homset sage/categories/morphism sage/categories/functor sage/categories/pushout Functorial constructions ========================
• ## sage/categories/functor.pyx

`diff -r 74c911071a9a sage/categories/functor.pyx`
 a result is a homomorphism that is defined on the base ring:: sage: F = QQ['t'].construction()[0] sage: F Poly[t] sage: F(f) Ring morphism: From: Univariate Polynomial Ring in t over Univariate Polynomial Ring in x over Integer Ring def _apply_functor(self, x): """ Apply the functor to an object of ``self``'s domain Apply the functor to an object of ``self``'s domain. NOTE: def _apply_functor_to_morphism(self, f): """ Apply the functor to a morphism between two objects of ``self``'s domain Apply the functor to a morphism between two objects of ``self``'s domain. NOTE: def _coerce_into_domain(self, x): """ Interprete the argument as an object of self's domain Interprete the argument as an object of self's domain. NOTE: ... TypeError: x (=Integer Ring) is not in Category of fields """ if not (x in  self.__domain): raise TypeError, "x (=%s) is not in %s"%(x, self.__domain) ... TypeError: x (=Integer Ring) is not in Category of fields TESTS:: sage: R = IdentityFunctor(Rings()) sage: P, _ = QQ['t'].construction() sage: R == P False sage: P == R False sage: R == QQ False """ def __init__(self, C): """ def _apply_functor(self, x): """ Apply the functor to an object of ``self``'s domain. TESTS:: sage: fields = Fields()
• ## sage/categories/pushout.py

`diff -r 74c911071a9a sage/categories/pushout.py`
 a class ConstructionFunctor(Functor): """ Base class for construction functors Base class for construction functors. A construction functor is a functorial algebraic construction, such as the construction of a matrix ring over a given ring :: sage: F1,R = QQ.construction() sage: F1, R = QQ.construction() sage: F1 FractionField sage: R Integer Ring sage: F2,R = (ZZ['x']).construction() sage: F2, R = (ZZ['x']).construction() sage: F2 Poly[x] sage: R Univariate Polynomial Ring in x over Rational Field When composing two construction functors, they are sometimes merged into one, as is the case in the Quotient construction. :: sage: Q15,R = (ZZ.quo(15*ZZ)).construction() merged into one, as is the case in the Quotient construction:: sage: Q15, R = (ZZ.quo(15*ZZ)).construction() sage: Q15 QuotientFunctor sage: Q35,R = (ZZ.quo(35*ZZ)).construction() sage: Q35, R = (ZZ.quo(35*ZZ)).construction() sage: Q35 QuotientFunctor sage: Q15.merge(Q35) def pushout(self, other): """ Return the composition of two construction functors, in an order given by their ranks Return the composition of two construction functors, in an order given by their ranks. NOTE: - This method seems not to be used in the coercion model - By default, the functor with smaller rank is applied first - This method seems not to be used in the coercion model. - By default, the functor with smaller rank is applied first. TESTS:: NOTE: By default, it returns the name of the construction functor's class. Usually, this method will be overloaded Usually, this method will be overloaded. TEST:: NOTE: By default, it returns the name of the construction functor's class. Usually, this method will be overloaded Usually, this method will be overloaded. TEST:: def merge(self, other): """ Merge ``self`` with another construction functor, or return None Merge ``self`` with another construction functor, or return None. NOTE: def commutes(self, other): """ Determine whether ``self`` commutes with another construction functor Determine whether ``self`` commutes with another construction functor. NOTE: def expand(self): """ Decompose ``self`` into a list of construction functors Decompose ``self`` into a list of construction functors. NOTE: sage: Q = ZZ.quo(2).construction()[0] sage: Q.expand() [QuotientFunctor] sage: P = ZZ['t'].construction()[0] sage: FP = F*P sage: FP.expand() [FractionField, Poly[t]] """ return [self] class CompositeConstructionFunctor(ConstructionFunctor): """ A Construction Functor composed by other Construction Functors A Construction Functor composed by other Construction Functors. INPUT: ``F1,F2,...``: A list of Construction Functors. The result is the ``F1, F2,...``: A list of Construction Functors. The result is the composition ``F1`` followed by ``F2`` followed by ... EXAMPLES:: def _apply_functor_to_morphism(self, f): """ Apply the functor to an object of ``self``'s domain. TESTS:: sage: from sage.categories.pushout import CompositeConstructionFunctor def _apply_functor(self, R): """ Apply the functor to an object of ``self``'s domain. TESTS:: sage: from sage.categories.pushout import CompositeConstructionFunctor def __mul__(self, other): """ Convention: ``(F1*F2)(X) == F1(F2(X))``. Compose construction functors to a composit construction functor, unless one of them is the identity. NOTE: The product is in functorial notation, i.e., when applying the product to an object then the second factor is applied first. EXAMPLES:: class IdentityConstructionFunctor(ConstructionFunctor): """ A construction functor that is the identity functor A construction functor that is the identity functor. TESTS:: def _apply_functor(self, x): """ Return the argument unaltered Return the argument unaltered. TESTS:: def _apply_functor_to_morphism(self, f): """ Return the argument unaltered Return the argument unaltered. TESTS:: def __mul__(self, other): """ Compose construction functors to a composit construction functor, unless one of them is the identity. NOTE: The product is in functorial notation, i.e., when applying the product to an object then the second factor is applied first. TESTS:: sage: from sage.categories.pushout import IdentityConstructionFunctor class PolynomialFunctor(ConstructionFunctor): """ Construction functor for univariate polynomial rings Construction functor for univariate polynomial rings. EXAMPLE: def _apply_functor(self, R): """ Apply the functor to an object of ``self``'s domain. TEST:: sage: P = ZZ['x'].construction()[0] def merge(self, other): """ Merge ``self`` with another construction functor, or return None. NOTE: Internally, the merging is delegated to the merging of def _apply_functor(self, R): """ Apply the functor to an object of ``self``'s domain. EXAMPLES:: sage: R. = QQ[] def merge(self, other): """ Merge ``self`` with another construction functor, or return None. EXAMPLES:: sage: F = sage.categories.pushout.MultiPolynomialFunctor(['x','y'], None) def expand(self): """ Decompose ``self`` into a list of construction functors. EXAMPLES:: sage: F = QQ['x,y,z,t'].construction()[0]; F class InfinitePolynomialFunctor(ConstructionFunctor): """ A Construction Functor for Infinite Polynomial Rings (see :mod:`~sage.rings.polynomial.infinite_polynomial_ring`) A Construction Functor for Infinite Polynomial Rings (see :mod:`~sage.rings.polynomial.infinite_polynomial_ring`). AUTHOR: CoercionException: Overlapping variables (('a', 'b'),['a_3', 'a_1']) are incompatible Since the construction functors are actually used to construct infinite polynomial rings, the following result is no surprise: result is no surprise:: sage: C. = InfinitePolynomialRing(B); C Infinite polynomial ring in a, b over Multivariate Polynomial Ring in x, y over Rational Field `X` and `Y` have an overlapping generators `x_\\ast, y_\\ast`. Since the default lexicographic order is used in both rings, it gives rise to isomorphic sub-monoids in both `X` and `Y`. They are merged in the pushout, which also yields a common parent for doing arithmetic. pushout, which also yields a common parent for doing arithmetic:: sage: P = sage.categories.pushout.pushout(Y,X); P Infinite polynomial ring in w, x, y, z over Rational Field def _apply_functor(self, R): """ Apply the functor to an object of ``self``'s domain. TEST:: sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F def __mul__(self, other): """ Compose construction functors to a composit construction functor, unless one of them is the identity. NOTE: The product is in functorial notation, i.e., when applying the product to an object then the second factor is applied first. TESTS:: sage: F1 = QQ['a','x_2','x_1','y_3','y_2'].construction()[0]; F1 def expand(self): """ Decompose the functor `F` into sub-functors, whose product returns `F` Decompose the functor `F` into sub-functors, whose product returns `F`. EXAMPLES:: class MatrixFunctor(ConstructionFunctor): """ A construction functor for matrices over rings A construction functor for matrices over rings. EXAMPLES:: sage: MS = MatrixSpace(ZZ,2) sage: MS = MatrixSpace(ZZ,2, 3) sage: F = MS.construction()[0]; F MatrixFunctor sage: MS = MatrixSpace(ZZ,2) True sage: F.codomain() Category of commutative additive groups sage: MatrixSpace(ZZ,2,2).construction()[0].codomain() sage: R = MatrixSpace(ZZ,2,2).construction()[0] sage: R.codomain() Category of rings sage: F(ZZ) Full MatrixSpace of 2 by 3 dense matrices over Integer Ring sage: F(ZZ) in F.codomain() True sage: R(GF(2)) Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 2 sage: R(GF(2)) in R.codomain() True """ if nrows == ncols: Functor.__init__(self, Rings(), Rings()) # Algebras() takes a base ring self.nrows = nrows self.ncols = ncols self.is_sparse = is_sparse def _apply_functor(self, R): """ Apply the functor to an object of ``self``'s domain. TEST: The following is a test against a bug discussed at ticket #8800 """ from sage.matrix.matrix_space import MatrixSpace return MatrixSpace(R, self.nrows, self.ncols, sparse=self.is_sparse) def __cmp__(self, other): """ TEST:: if c == 0: c = cmp((self.nrows, self.ncols), (other.nrows, other.ncols)) return c def merge(self, other): """ Merging is only happening if both functors are matrix functors of the same dimension. class LaurentPolynomialFunctor(ConstructionFunctor): """ Construction functor for Laurent polynomial rings Construction functor for Laurent polynomial rings. EXAMPLES:: if not isinstance(var, (basestring,tuple,list)): raise TypeError, "variable name or list of variable names expected" self.var = var self.multi_variate = multi_variate or not isinstance(var,basestring) self.multi_variate = multi_variate or not isinstance(var, basestring) def _apply_functor(self, R): """ Apply the functor to an object of ``self``'s domain. TESTS:: sage: from sage.categories.pushout import LaurentPolynomialFunctor else: from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing return LaurentPolynomialRing(R, self.var) def __cmp__(self, other): """ TESTS:: if c == 0: c = cmp(self.var, other.var) return c def merge(self, other): """ Two Laurent polynomial construction functors merge if the variable names coincide. class VectorFunctor(ConstructionFunctor): """ A construction functor for free modules over commutative rings A construction functor for free modules over commutative rings. EXAMPLE:: """ INPUT: - ``n``, the rank of the to-be-created modules (non-neg. integer) - ``n``, the rank of the to-be-created modules (non-negative integer) - ``is_sparse`` (optional bool, default ``False``), create sparse implementation of modules - ``inner_product_matrix``: ``n`` by ``n`` matrix, used to compute inner products in the to-be-created modules sage: from sage.categories.pushout import VectorFunctor sage: F1 = VectorFunctor(3, inner_product_matrix = Matrix(3,3,range(9))) sage: F1.domain() Category of commutative rings sage: F1.codomain() Category of commutative additive groups sage: M1 = F1(ZZ) sage: M1.is_sparse() False self.n = n self.is_sparse = is_sparse self.inner_product_matrix = inner_product_matrix def _apply_functor(self, R): """ Apply the functor to an object of ``self``'s domain. TESTS:: sage: from sage.categories.pushout import VectorFunctor """ from sage.modules.free_module import FreeModule return FreeModule(R, self.n, sparse=self.is_sparse, inner_product_matrix=self.inner_product_matrix) def _apply_functor_to_morphism(self, f): """ This is not implemented yet. """ ## TODO: Implement this! raise NotImplementedError, "Can not create induced morphisms of free modules yet" def __cmp__(self, other): """ Only the rank of the to-be-created modules is compared, *not* the inner product matrix Only the rank of the to-be-created modules is compared, *not* the inner product matrix. TESTS:: if c == 0: c = cmp(self.n, other.n) return c def merge(self, other): """ Two constructors of free modules merge, if the module ranks coincide. If both have explicitly given inner product matrices, they must coincide as well have explicitly given inner product matrices, they must coincide as well. EXAMPLE: else: return VectorFunctor(self.n, self.is_sparse and other.is_sparse, self.inner_product_matrix) class SubspaceFunctor(ConstructionFunctor): """ Constructing a subspace of an ambient free module, given by a basis. """ rank = 11 # ranking of functor, not rank of module def __init__(self, basis): """ INPUT: ``basis``: a list of elements of a free module ``basis``: a list of elements of a free module. TEST:: ## contains in- and output Functor.__init__(self, CommutativeAdditiveGroups(), CommutativeAdditiveGroups()) self.basis = basis def _apply_functor(self, ambient): """ Apply the functor to an object of ``self``'s domain. TESTS:: sage: M = ZZ^3 [0 1 0] """ return ambient.span_of_basis(self.basis) def _apply_functor_to_morphism(self, f): """ This is not implemented yet. NotImplementedError: Can not create morphisms of free sub-modules yet """ raise NotImplementedError, "Can not create morphisms of free sub-modules yet" def __cmp__(self, other): """ TEST:: if c == 0: c = cmp(self.basis, other.basis) return c def merge(self, other): """ Two Subspace Functors are merged into a construction functor of the sum of two subspaces Two Subspace Functors are merged into a construction functor of the sum of two subspaces. EXAMPLE:: else: return None class FractionField(ConstructionFunctor): """ Construction functor for fraction fields Construction functor for fraction fields. EXAMPLE:: Fraction Field of Univariate Polynomial Ring in t over Integer Ring """ Functor.__init__(self, Rings(), Fields()) def _apply_functor(self, R): """ Apply the functor to an object of ``self``'s domain. TEST:: sage: F = QQ.construction()[0] #            c = cmp(self.t, other.t) #        return c class CompletionFunctor(ConstructionFunctor): """ Completion of a ring with respect to a given prime (including infinity) Completion of a ring with respect to a given prime (including infinity). EXAMPLES:: """ rank = 4 def __init__(self, p, prec, extras=None): """ INPUT: self.p = p self.prec = prec self.extras = extras def __str__(self): """ TEST:: (Completion[7], Integer Ring) """ return 'Completion[%s]'%repr(self.p) def _apply_functor(self, R): """ Apply the functor to an object of ``self``'s domain. TEST:: sage: R = Zp(5) if c == 0: c = cmp(self.p, other.p) return c def merge(self, other): """ Two Completion functors are merged, if they are equal. If the precisions of ##   both commute. This is used in the call method, ##   since some fraction fields have no completion method ##   implemented. def commutes(self,other): """ Completion commutes with fraction fields Completion commutes with fraction fields. EXAMPLE:: False sage: C(R) is Frac(C(P)) True sage: F = R.construction()[0] sage: (C*F)(ZZ['x']) is (F*C)(ZZ['x']) True """ return isinstance(other,(FractionField,CompletionFunctor)) class QuotientFunctor(ConstructionFunctor): """ Construction functor for quotient rings Construction functor for quotient rings. NOTE: self.I = I if names is None: self.names = None elif isinstance(names,basestring): elif isinstance(names, basestring): self.names = (names,) else: self.names = tuple(names) self.as_field = as_field def _apply_functor(self, R): """ Apply the functor to an object of ``self``'s domain. TESTS:: sage: P. = ZZ[] if self.as_field and hasattr(Q, 'field'): Q = Q.field() return Q def __cmp__(self, other): """ The types, the names and the moduli are compared. if c == 0: c = cmp(self.I, other.I) return c def merge(self, other): """ Two quotient functors with coinciding names are merged by taking the gcd of their moduli Two quotient functors with coinciding names are merged by taking the gcd of their moduli. EXAMPLE:: """ if type(self)!=type(other): return return None if self.names != other.names: return return None if self == other: if self.as_field == other.as_field: return self return QuotientFunctor(self.I,names=self.names, as_field=True) # one of them yields a field! return QuotientFunctor(self.I, names=self.names, as_field=True) # one of them yields a field! try: gcd = self.I + other.I except (TypeError, NotImplementedError): raise TypeError, "Trivial quotient intersection." # GF(p) has a coercion from Integers(p). Hence, merging should # yield a field if either self or other yields a field. return QuotientFunctor(gcd,names=self.names, as_field=self.as_field or other.as_field) return QuotientFunctor(gcd, names=self.names, as_field=self.as_field or other.as_field) class AlgebraicExtensionFunctor(ConstructionFunctor): """ Algebraic extension (univariate polynomial ring modulo principal ideal) Algebraic extension (univariate polynomial ring modulo principal ideal). EXAMPLE:: extension will be constructed as the quotient of a univariate polynomial ring:: sage: F(CC) Univariate Quotient Polynomial Ring in a over Complex Field with 53 bits of precision with modulus a^3 + a^2 + 1.00000000000000 sage: F(RR) Univariate Quotient Polynomial Ring in a over Real Field with 53 bits of precision with modulus a^3 + a^2 + 1.00000000000000 Order in Number Field in a with defining polynomial x^3 - x^2 + 1 The cyclotomic fields form a special case of number fields with prescribed embeddings. :: with prescribed embeddings:: sage: C = CyclotomicField(8) sage: F,R = C.construction() def _apply_functor(self, R): """ Apply the functor to an object of ``self``'s domain. TESTS:: sage: K.=NumberField(x^3+x^2+1) def merge(self,other): """ Merging two :class:`AlgebraicExtensionFunctor`s Merging two :class:`AlgebraicExtensionFunctor`s. INPUT: ``other`` -- Construction Functor ``other`` -- Construction Functor. OUTPUT: """ if not isinstance(other,AlgebraicExtensionFunctor): return return None if self == other: return self # This method is supposed to be used in pushout(), # assume that both functors have a single variable. # But for being on the safe side...: if len(self.names)!=1 or len(other.names)!=1: return return None ##       We don't accept a forgetful coercion, since, together ##       with bidirectional coercions between two embedded ##       number fields, it would yield to contradictions in def __mul__(self, other): """ Functor composition. The last factor is applied first. Compose construction functors to a composit construction functor, unless one of them is the identity. NOTE: The product is in functorial notation, i.e., when applying the product to an object then the second factor is applied first. TESTS:: def expand(self): """ Decompose the functor `F` into sub-functors, whose product returns `F` Decompose the functor `F` into sub-functors, whose product returns `F`. EXAMPLES:: sage: F,R = L.construction() sage: prod(F.expand())(R) == L True sage: K = NumberField([x^2-2, x^2-3],'a') sage: F, R = K.construction() sage: F AlgebraicExtensionFunctor sage: L = F.expand(); L [AlgebraicExtensionFunctor, AlgebraicExtensionFunctor] sage: L[-1](QQ) Number Field in a1 with defining polynomial x^2 - 3 """ if len(self.polys)==1: return [self] class AlgebraicClosureFunctor(ConstructionFunctor): """ Algebraic Closure Algebraic Closure. EXAMPLE:: """ Functor.__init__(self, Rings(), Rings()) def _apply_functor(self, R): """ Apply the functor to an object of ``self``'s domain. TEST:: sage: F = CDF.construction()[0] if c is not None and c[0]==self: return R return R.algebraic_closure() def merge(self, other): """ Mathematically, Algebraic Closure subsumes Algebraic Extension. """ if self==other: return self return None # Mathematically, Algebraic Closure subsumes Algebraic Extension. # However, it seems that people do want to work with # algebraic extensions of RR (namely RR/poly*RR). So, we don't do: def merge(self, other): """ Merge ``self`` with another construction functor, or return None. EXAMPLES:: sage: P1 = PermutationGroup([[(1,2)]]) class BlackBoxConstructionFunctor(ConstructionFunctor): """ Construction functor obtained from any callable object Construction functor obtained from any callable object. EXAMPLES:: if not callable(box): raise TypeError, "input must be callable" self.box = box def _apply_functor(self, R): """ Apply the functor to an object of ``self``'s domain. TESTS:: sage: from sage.categories.pushout import BlackBoxConstructionFunctor """ return self.box(R) def __cmp__(self, other): """ TESTS:: c = cmp(self.box, other.box) #return self.box == other.box return c def pushout(R, S): """ Given a pair of Objects R and S, try and construct a
• ## sage/groups/perm_gps/permgroup.py

`diff -r 74c911071a9a sage/groups/perm_gps/permgroup.py`
 a if gens is None: self._gap_string = gap_group if isinstance(gap_group, str) else str(gap_group) self._gens = self._gens_from_gap() return return None gens = [self._element_class()(x, check=False).list() for x in gens] self._deg = max([0]+[max(g) for g in gens])
• ## sage/rings/number_field/number_field.py

`diff -r 74c911071a9a sage/rings/number_field/number_field.py`
 a sage: P. = QQ[] sage: K. = NumberField(x^3-5,embedding=0) sage: L. = K.extension(x^2+a) sage: F,R = L.construction() sage: F, R = L.construction() sage: F(R) == L    # indirect doctest True sage: S.coerce(y) is y True Fields with embeddings into an ambient field coerce naturally by the given embedding. :: Fields with embeddings into an ambient field coerce naturally by the given embedding:: sage: CyclotomicField(15).coerce(CyclotomicField(5).0 - 17/3) zeta15^3 - 17/3 # R is embedded, self isn't. So, we could only have # the forgetful coercion. But this yields to non-commuting # coercions, as was pointed out at ticket #8800 return return None def _magma_init_(self, magma): """
• ## sage/rings/number_field/number_field_ideal.py

`diff -r 74c911071a9a sage/rings/number_field/number_field_ideal.py`
 a sage: L. = NumberField(x^8-x^4+1) sage: F_2 = L.fractional_ideal(b^2-1) sage: F_4 = L.fractional_ideal(b^4-1) sage: F_2==F_4 sage: F_2 == F_4 True """
• ## sage/rings/polynomial/polynomial_quotient_ring.py

`diff -r 74c911071a9a sage/rings/polynomial/polynomial_quotient_ring.py`
 a sage: P.=ZZ[] sage: Q = P.quo(5+t^2) sage: F,R = Q.construction() sage: F, R = Q.construction() sage: F(R) == Q True sage: P. = GF(3)[] sage: Q = P.quo([2+t^2]) sage: F,R = Q.construction() sage: F, R = Q.construction() sage: F(R) == Q True