# HG changeset patch
# User William Stein
# Date 1275034943 25200
# Node ID e939d56d831b78429f2c72a707d0a1c27c6fd6ca
# Parent 10779925917f5495f8676539c674099bc6eef9c2
trac 9054 (part 9): inverses of fractional ideals; hermite form for general matrices; some little function field bugfixes.
diff r 10779925917f r e939d56d831b sage/matrix/matrix2.pyx
 a/sage/matrix/matrix2.pyx Thu May 27 23:28:15 2010 0700
+++ b/sage/matrix/matrix2.pyx Fri May 28 01:22:23 2010 0700
@@ 6771,6 +6771,66 @@
dp, up, vp = _smith_diag(d)
return dp,up*u,v*vp
+ def hermite_form(self, include_zero_rows=True, transformation=False):
+ """
+ Return the Hermite form of self, if it is defined.
+
+ INPUT:
+
+  ``include_zero_rows``  bool (default: True); if False
+ the zero rows in the output matrix are deleted.
+
+  ``transformation``  bool (default: False) a matrix U such that U*self == H.
+
+ OUTPUT:
+
+  matrix H
+  (optional) transformation matrix U such that U*self == H, possibly with zero
+ rows deleted...
+
+
+ EXAMPLES::
+
+ sage: M = FunctionField(GF(7),'x').maximal_order()
+ sage: K. = FunctionField(GF(7)); M = K.maximal_order()
+ sage: A = matrix(M, 2, 3, [x, 1, 2*x, x, 1+x, 2])
+ sage: A.hermite_form()
+ [ x 1 2*x]
+ [ 0 x 5*x + 2]
+ sage: A.hermite_form(transformation=True)
+ (
+ [ x 1 2*x] [1 0]
+ [ 0 x 5*x + 2], [6 1]
+ )
+ sage: A = matrix(M, 2, 3, [x, 1, 2*x, 2*x, 2, 4*x])
+ sage: A.hermite_form(transformation=True, include_zero_rows=False)
+ ([ x 1 2*x], [1 0])
+ sage: H, U = A.hermite_form(transformation=True, include_zero_rows=True); H, U
+ (
+ [ x 1 2*x] [1 0]
+ [ 0 0 0], [5 1]
+ )
+ sage: U*A == H
+ True
+ sage: H, U = A.hermite_form(transformation=True, include_zero_rows=False)
+ sage: U*A
+ [ x 1 2*x]
+ sage: U*A == H
+ True
+ """
+ left, H, pivots = self._echelon_form_PID()
+ if not include_zero_rows:
+ i = H.nrows()  1
+ while H.row(i) == 0:
+ i = 1
+ H = H[:i+1]
+ if transformation:
+ left = left[:i+1]
+ if transformation:
+ return H, left
+ else:
+ return H
+
def _echelon_form_PID(self):
r"""
Return a triple (left, a, pivots) where left*self == a and a is row
diff r 10779925917f r e939d56d831b sage/rings/function_field/function_field_ideal.py
 a/sage/rings/function_field/function_field_ideal.py Thu May 27 23:28:15 2010 0700
+++ b/sage/rings/function_field/function_field_ideal.py Fri May 28 01:22:23 2010 0700
@@ 174,15 +174,32 @@
def __invert__(self):
"""
Return the inverse of this fractional ideal.
+
+ EXAMPLES::
+
+ sage: R. = FunctionField(GF(7)); S. = R[]
+ sage: L. = R.extension(y^2  x^3  1); M = L.equation_order()
+ sage: I = M.ideal(y)
+ sage: I.__invert__()
+ Ideal (1, (6/(x^3 + 1))*y) of Order in Function field in y defined by y^2 + 6*x^3 + 6
+ sage: I^(1)
+ Ideal (1, (6/(x^3 + 1))*y) of Order in Function field in y defined by y^2 + 6*x^3 + 6
+ sage: I.__invert__() * I
+ Ideal (1, 6*y) of Order in Function field in y defined by y^2 + 6*x^3 + 6
"""
 # If I is this fractional ideal, then the inverse
 # of I is the set of elements x such that x*I is
 # in the unit ideal. Our straightforward algorithm to
 # compute this is to take the homomorphism defined
 # by multiplication by generators of self, and compute
 # the inverse image something under it.
+ if len(self.gens()) == 0:
+ raise ZeroDivisionError
+
+ # NOTE: If I = (g0, ..., gn), then {x : x*I is in R}
+ # is the intersection over i of {x : x*gi is in R}
+ # Thus (I + J)^(1) = I^(1) intersect J^(1).

+ G = self.gens()
+ R = self.ring()
+ inv = R.ideal(~G[0])
+ for g in G[1:]:
+ inv = inv.intersection(R.ideal(~g))
+ return inv
def ideal_with_gens(R, gens):
"""
@@ 196,7 +213,8 @@
sage: sage.rings.function_field.function_field_ideal.ideal_with_gens(M, [y])
Ideal (x^3 + 1, y) of Order in Function field in y defined by y^2  x^3  1
"""
 return ideal_with_gens_over_base(R, [b*g for b in R.basis() for g in gens])
+ K = R.fraction_field()
+ return ideal_with_gens_over_base(R, [b*K(g) for b in R.basis() for g in gens])
def ideal_with_gens_over_base(R, gens):
diff r 10779925917f r e939d56d831b sage/rings/function_field/todo.txt
 a/sage/rings/function_field/todo.txt Thu May 27 23:28:15 2010 0700
+++ b/sage/rings/function_field/todo.txt Fri May 28 01:22:23 2010 0700
@@ 1,10 +1,8 @@
TODO:
[x] factor for elements of the rational function field

[ ] ideals
[ ] isomorphisms between function fields:
K.hom([top gen, next one down, etc.])
+ make sure you include easy way to gens all the way down.
[ ] Hess's algorithm
[ ] reduction algorithm
@@ 25,6 +23,9 @@
DONE:
+[x] inverses of fractional ideals
+[x] factor for elements of the rational function field
+[x] ideals
[x] polynomial factoring of any univariate poly over a rational function field: reduce to bivariate over constant field?
[x] conversion back and forth between a free module over base
[x] random element