Skip to content

Commit 7c8861c

Browse files
committed
check isomorphisms between Drinfeld modules
1 parent 14b5a1b commit 7c8861c

File tree

2 files changed

+118
-2
lines changed

2 files changed

+118
-2
lines changed

src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,123 @@ def height(self):
10351035
except NotImplementedError:
10361036
raise NotImplementedError('height not implemented in this case')
10371037

1038+
def is_isomorphic(self, other, absolutely=False):
1039+
r"""
1040+
Return ``True`` is this Drinfeld module is isomorphic to
1041+
``other``.
1042+
1043+
INPUT:
1044+
1045+
- ``absolutely`` -- a boolean (default: ``False``); if ``True``,
1046+
check the existence of an isomorphism defined on the base
1047+
field; if ``False`` check over an algebraic closure.
1048+
1049+
EXAMPLES::
1050+
1051+
sage: Fq = GF(5)
1052+
sage: A.<T> = Fq[]
1053+
sage: K.<z> = Fq.extension(3)
1054+
sage: phi = DrinfeldModule(A, [z, 0, 1, z])
1055+
sage: t = phi.ore_variable()
1056+
1057+
We create a second Drinfeld module, which is isomorphic to `\phi`
1058+
and then check that they are indeed isomorphic::
1059+
1060+
sage: psi = phi.velu(z)
1061+
sage: phi.is_isomorphic(psi)
1062+
True
1063+
1064+
In the example below, `\phi` and `\psi` are isogeneous but not
1065+
isomorphic::
1066+
1067+
sage: psi = phi.velu(t + 1)
1068+
sage: phi.is_isomorphic(psi)
1069+
False
1070+
1071+
Here is an example of two Drinfeld modules which are isomorphic
1072+
on an algebraic closure but not on the base field::
1073+
1074+
sage: phi = DrinfeldModule(A, [z, 1])
1075+
sage: psi = DrinfeldModule(A, [z, z])
1076+
sage: phi.is_isomorphic(psi)
1077+
False
1078+
sage: phi.is_isomorphic(psi, absolutely=True)
1079+
True
1080+
1081+
On certain fields, testing isomorphisms on the base field may
1082+
fail::
1083+
1084+
sage: K = A.fraction_field()
1085+
sage: T = K.gen()
1086+
sage: phi = DrinfeldModule(A, [T, 0, 1])
1087+
sage: psi = DrinfeldModule(A, [T, 0, T])
1088+
sage: psi.is_isomorphic(phi)
1089+
Traceback (most recent call last):
1090+
...
1091+
NotImplementedError: cannot solve the equation u^24 == T
1092+
1093+
However, it never fails over the algebraic closure::
1094+
1095+
sage: psi.is_isomorphic(phi, absolutely=True)
1096+
True
1097+
1098+
TESTS::
1099+
1100+
A Drifeld module is always isomorphic to itself::
1101+
1102+
sage: phi = DrinfeldModule(A, [T] + [K.random_element() for _ in range(3)] + [1])
1103+
sage: phi.is_isomorphic(phi)
1104+
True
1105+
1106+
Two Drinfeld modules of different ranks are never isomorphic::
1107+
1108+
sage: psi = DrinfeldModule(A, [T] + [K.random_element() for _ in range(5)] + [1])
1109+
sage: phi.is_isomorphic(psi)
1110+
False
1111+
1112+
"""
1113+
if self.category() is not other.category():
1114+
raise ValueError("Drinfeld modules are not in the same category")
1115+
if self is other:
1116+
return True
1117+
r = self.rank()
1118+
if other.rank() != r:
1119+
return False
1120+
q = self._Fq.cardinality()
1121+
A = self.gen()
1122+
B = other.gen()
1123+
e = Integer(0)
1124+
ue = self._base(1)
1125+
for i in range(1, r+1):
1126+
ai = A[i]
1127+
bi = B[i]
1128+
if ai == 0 and bi == 0:
1129+
continue
1130+
if ai == 0 or bi == 0:
1131+
return False
1132+
if e != q - 1:
1133+
# u^e = ue
1134+
# u^(q^i - 1) = ai/bi
1135+
e, s, t = e.xgcd(q**i - 1)
1136+
ue = ue**s * (ai/bi)**t
1137+
for i in range(1, r+1):
1138+
if A[i]:
1139+
f = (q**i - 1) // e
1140+
if A[i] != B[i] * ue**f:
1141+
return False
1142+
if absolutely:
1143+
return True
1144+
else:
1145+
ue = ue.backend(force=True)
1146+
try:
1147+
_ = ue.nth_root(e)
1148+
except ValueError:
1149+
return False
1150+
except (AttributeError, NotImplementedError):
1151+
raise NotImplementedError("cannot solve the equation u^%s == %s" % (e, ue))
1152+
return True
1153+
1154+
10381155
def is_supersingular(self):
10391156
r"""
10401157
Return ``True`` whether the Drinfeld module is supersingular.

src/sage/rings/function_field/drinfeld_modules/morphism.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -771,8 +771,7 @@ def charpoly(self, var='X'):
771771
is the rank::
772772
773773
sage: g = phi.hom(T^2 + 1)
774-
sage: chi = g.charpoly()
775-
sage: chi.factor()
774+
sage: g.charpoly().factor()
776775
(X + 4*T^2 + 4)^3
777776
778777
An example with another variable name::

0 commit comments

Comments
 (0)