Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Working on p-adic free module isomorphisms
Browse files Browse the repository at this point in the history
  • Loading branch information
roed314 committed Sep 12, 2019
1 parent bdf4b23 commit 7d88f9a
Show file tree
Hide file tree
Showing 2 changed files with 287 additions and 9 deletions.
13 changes: 5 additions & 8 deletions src/sage/rings/number_field/number_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -8124,6 +8124,7 @@ def _order(self, gens, **kwds):
self._order.set_cache(ret, gens)
return ret

@cached_method
def vector_space(self):
"""
Return a vector space V and isomorphisms self --> V and V --> self.
Expand Down Expand Up @@ -8157,14 +8158,10 @@ def vector_space(self):
sage: to_V(from_V(V([0,-1/7,0])))
(0, -1/7, 0)
"""
try:
return self.__vector_space
except AttributeError:
V = QQ**self.degree()
from_V = maps.MapVectorSpaceToNumberField(V, self)
to_V = maps.MapNumberFieldToVectorSpace(self, V)
self.__vector_space = (V, from_V, to_V)
return self.__vector_space
V = QQ**self.degree()
from_V = maps.MapVectorSpaceToNumberField(V, self)
to_V = maps.MapNumberFieldToVectorSpace(self, V)
return (V, from_V, to_V)

def absolute_vector_space(self):
r"""
Expand Down
283 changes: 282 additions & 1 deletion src/sage/rings/padics/padic_extension_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@
from sage.structure.richcmp import op_EQ
from functools import reduce
from sage.categories.morphism import Morphism
from sage.categories.map import Map
from sage.categories.sets_with_partial_maps import SetsWithPartialMaps
from sage.categories.integral_domains import IntegralDomains
from sage.categories.euclidean_domains import EuclideanDomains
from sage.categories.metric_spaces import MetricSpaces
from sage.categories.fields import Fields
from sage.categories.homset import Hom

from sage.categories.modules_with_basis import ModulesWithBasis
from sage.misc.flatten import flatten
from sage.misc.cachefunc import cached_method
from sage.misc.richcmp import richcmp

class pAdicExtensionGeneric(pAdicGeneric):
def __init__(self, poly, prec, print_mode, names, element_class):
Expand Down Expand Up @@ -560,6 +564,51 @@ def random_element(self):
range(self.modulus().degree())],
0)

@cached_method(key=lambda (self, base, map): (base or self.base_ring(), map))
def free_module(self, base=None, map=True):
"""
Returns a free module V over a specified base ring together with maps to and from V.
INPUT:
- ``base`` -- a subring `R` so that this ring/field is isomorphic
to a finite-rank free `R`-module `V`.
- ``maps`` -- boolean (default ``True``), whether to return
`R`-linear maps to and from `V`.
OUTPUT:
- A finite-rank free `R`-module `V`
- An `R`-module isomorphism ``from_V`` from `V` to this ring/field
(only included if ``maps`` is ``True``)
- An `R`-module isomorphism ``to_V`` from this ring/field to `V`
(only included if ``maps`` is ``True``)
EXAMPLES::
"""
B = self.base_ring()
A = B.base_ring()
d = self.relative_degree()
if base is B:
# May eventually want to take advantage of the fact that precision is flat
V = B**d
from_V = MapFreeModuleToOneStep
to_V = MapOneStepToFreeModule
elif base is A:
d *= B.relative_degree()
V = A**d
from_V = MapFreeModuleToTwoStep
to_V = MapTwoStepToFreeModule
else:
raise NotImplementedError
FromV = Hom(V, self)
ToV = Hom(self, V)
from_V = FromV.__make_element_class__(from_V)(FromV)
to_V = ToV.__make_element_class__(to_V)(ToV)
return V, from_V, to_V

#def unit_group(self):
# raise NotImplementedError

Expand All @@ -575,6 +624,238 @@ def random_element(self):
#def zeta_order(self):
# raise NotImplementedError

# We could have used morphisms in the category
# FiniteDimensionalModulesWithBasis over Qp(p)
# But this would require making p-adic fields
# part of this category which has a lot of side
# effects (adding methods which will show up
# in tab completion for example). For now we
# just stick with Map.
class pAdicModuleIsomorphism(Map):
r"""
A base class for various isomorphisms between p-adic rings/fields and free modules
EXAMPLES::
sage: K.<a> = Qq(125)
sage: V, fr, to = K.free_module()
sage: from sage.rings.padics.padic_extension_generic import pAdicModuleIsomorphism
sage: isinstance(fr, pAdicModuleIsomorphism)
True
"""
def _repr_type(self):
r"""
EXAMPLES::
sage: K.<a> = Qq(125)
sage: V, fr, to = K.free_module()
sage: fr._repr_type()
'Isomorphism'
"""
return "Isomorphism"

def is_injective(self):
r"""
EXAMPLES::
sage: K.<a> = Qq(125)
sage: V, fr, to = K.free_module()
sage: fr.is_injective()
True
"""
return True

def is_surjective(self):
r"""
EXAMPLES::
sage: K.<a> = Qq(125)
sage: V, fr, to = K.free_module()
sage: fr.is_surjective()
True
"""
return True

def _richcmp_(self, other, op):
r"""
EXAMPLES::
sage: K.<a> = Qq(125)
sage: V, fr, to = K.free_module()
sage: fr == fr
True
"""
# Equality depends only on the parent
return richcmp(op, 0)

class MapFreeModuleToOneStep(pAdicModuleIsomorphism):
"""
The isomorphism from the underlying module of a one-step p-adic extension
to the extension.
EXAMPLES::
sage: from sage.rings.padics.padic_extension_generic import MapFreeModuleToOneStep
sage: L.<a> = Qq(125)
sage: Q5 = L.base_ring()
sage: V = Q5^3
sage: phi = MapFreeModuleToOneStep(V, L)
sage: TestSuite(phi).run()
"""
def __init__(self, V, L):
pAdicModuleIsomorphism.__init__(self, Hom(V, L))

def _call_(self, x):
"""
EXAMPLES::
sage: from sage.rings.padics.padic_extension_generic import MapFreeModuleToOneStep
sage: L.<a> = Qq(125)
sage: Q5 = L.base_ring()
sage: V = Q5^3
sage: phi = MapFreeModuleToOneStep(V, L)
sage: v = V([1,2,3])
sage: phi(v)
(3*a^2 + 2*a + 1) + O(5^20)
"""
return self.codomain()(list(x))

def _call_with_args(self, x, args=(), kwds={}):
"""
EXAMPLES::
sage: from sage.rings.padics.padic_extension_generic import MapOneStepToFreeModule
sage: L.<a> = Qq(125)
sage: Q5 = L.base_ring()
sage: V = Q5^3
sage: phi = MapFreeModuleToOneStep(V, L)
sage: v = V([1,2,3])
sage: phi(v, 7)
(3*a^2 + 2*a + 1) + O(5^7)
"""
return self.codomain()(list(x), *args, **kwds)

class MapOneStepToFreeModule(pAdicModuleIsomorphism):
"""
The isomorphism from a one-step p-adic extension to its underlying free module
EXAMPLES::
sage: from sage.rings.padics.padic_extension_generic import MapOneStepToFreeModule
sage: L.<a> = Qq(125)
sage: Q5 = L.base_ring()
sage: V = Q5^3
sage: phi = MapOneStepToFreeModule(L, V)
sage: TestSuite(phi).run()
"""
def __init__(self, L, V):
pAdicModuleIsomorphism.__init__(self, Hom(L, V))

def _call_(self, x):
"""
EXAMPLES::
sage: from sage.rings.padics.padic_extension_generic import MapOneStepToFreeModule
sage: Q5 = Qp(5)
sage: R.<x> = ZZ[]
sage: L.<pi> = Q5.extension(x^3 - 5)
sage: V = Q5^3
sage: phi = MapOneStepToFreeModule(L, V)
sage: a = 1 + pi^2 + O(pi^11)
sage: phi(a)
(1 + O(5^4), O(5^4), 1 + O(5^3))
"""
V = self.codomain()
return self.codomain()(x.polynomial().padded_list(V.rank()))

class MapFreeModuleToTwoStep(pAdicModuleIsomorphism):
"""
The isomorphism from the underlying module of a two-step p-adic extension
to the extension.
EXAMPLES::
sage: from sage.rings.padics.padic_extension_generic import MapFreeModuleToTwoStep
sage: L.<a> = Qq(125)
sage: Q5 = L.base_ring()
sage: V = Q5^3
sage: phi = MapFreeModuleToTwoStep(V, L)
sage: TestSuite(phi).run()
"""
def __init__(self, V, L):
pAdicModuleIsomorphism.__init__(self, Hom(V, L))

def _call_(self, x):
"""
EXAMPLES::
sage: from sage.rings.padics.padic_extension_generic import MapFreeModuleToTwoStep
sage: L.<a> = Qq(125)
sage: Q5 = L.base_ring()
sage: V = Q5^3
sage: phi = MapFreeModuleToTwoStep(V, L)
sage: v = V([1,2,3])
sage: phi(v)
(3*a^2 + 2*a + 1) + O(5^20)
"""
L = self.codomain()
d = L.relative_degree()
U = L.base_ring()
x = list(x)
n = len(x)
v = [U(x[i:i+d]) for i in range(0,n,d)]
return L(v)

def _call_with_args(self, x, args=(), kwds={}):
"""
EXAMPLES::
sage: from sage.rings.padics.padic_extension_generic import MapTwoStepToFreeModule
sage: L.<a> = Qq(125)
sage: Q5 = L.base_ring()
sage: V = Q5^3
sage: phi = MapFreeModuleToTwoStep(V, L)
sage: v = V([1,2,3])
sage: phi(v, 7)
(3*a^2 + 2*a + 1) + O(5^7)
"""
return self.codomain()(self._call_(x), *args, **kwds)

class MapTwoStepToFreeModule(pAdicModuleIsomorphism):
"""
The isomorphism from a two-step p-adic extension to its underlying free module
EXAMPLES::
sage: from sage.rings.padics.padic_extension_generic import MapTwoStepToFreeModule
sage: L.<a> = Qq(125)
sage: Q5 = L.base_ring()
sage: V = Q5^3
sage: phi = MapTwoStepToFreeModule(L, V)
sage: TestSuite(phi).run()
"""
def __init__(self, L, V):
pAdicModuleIsomorphism.__init__(self, Hom(L, V))

def _call_(self, x):
"""
EXAMPLES::
sage: from sage.rings.padics.padic_extension_generic import MapTwoStepToFreeModule
sage: Q5 = Qp(5)
sage: R.<x> = ZZ[]
sage: L.<pi> = Q5.extension(x^3 - 5)
sage: V = Q5^3
sage: phi = MapTwoStepToFreeModule(L, V)
sage: a = 1 + pi^2 + O(pi^11)
sage: phi(a)
(1 + O(5^4), O(5^4), 1 + O(5^3))
"""
e = self.domain().relative_degree()
f = self.domain().base_ring().relative_degree()
v = flatten([c.polynomial().padded_list(f) for c in x.polynomial().padded_list(e)])
return self.codomain()(v)

class DefPolyConversion(Morphism):
"""
Conversion map between p-adic rings/fields with the same defining polynomial.
Expand Down

0 comments on commit 7d88f9a

Please sign in to comment.