Skip to content

Commit

Permalink
gh-37112: Tests to see if ideal in quaternion algebra is primitive (c…
Browse files Browse the repository at this point in the history
…yclic)

    
New methods for `QuaternionFractionalIdeal_rational`:

- `QuaternionFractionalIdeal_rational.is_integral()`
- `QuaternionFractionalIdeal_rational.is_primitive()`
- `QuaternionFractionalIdeal_rational.primitive_decomposition()`

These methods verify if an ideal in quaternion rational algebra is
integral, primitive (cyclic) and decompose it as a primitive ideal. Part
of the code came from
[https://learningtosqi.github.io](https://learningtosqi.github.io).
Also added the _Quaternion Algebras_ book by J. Voight in the
bibliography.

Done with @gioella

#sd123
    
URL: #37112
Reported by: Giacomo Borin
Reviewer(s): Lorenz Panny
  • Loading branch information
Release Manager committed Feb 1, 2024
2 parents b720abc + 09d352e commit 2c6ebe5
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/doc/en/reference/references/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6347,6 +6347,8 @@ REFERENCES:
.. [Voi2012] \J. Voight. Identifying the matrix ring: algorithms for
quaternion algebras and quadratic forms, to appear.
.. [Voi2021] \J. Voight. Quaternion algebras, Springer Nature (2021).
.. [VS06] \G.D. Villa Salvador. Topics in the Theory of Algebraic Function
Fields. Birkh\"auser, 2006.
Expand Down
106 changes: 106 additions & 0 deletions src/sage/algebras/quatalg/quaternion_algebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -3033,6 +3033,112 @@ def cyclic_right_subideals(self, p, alpha=None):
ans.append(J)
return ans

def is_integral(self):
r"""
Check if a quaternion fractional ideal is integral. An ideal in a quaternion algebra is
said integral if it is contained in its left order. If the left order is already defined it just
check the definition, otherwise it uses one of the alternative definition of Lemma 16.2.8 of
[Voi2021]_.
OUTPUT: a boolean.
EXAMPLES::
sage: R.<i,j,k> = QuaternionAlgebra(QQ, -1,-11)
sage: I = R.ideal([2 + 2*j + 140*k, 2*i + 4*j + 150*k, 8*j + 104*k, 152*k])
sage: I.is_integral()
True
sage: O = I.left_order()
sage: I.is_integral()
True
sage: I = R.ideal([1/2 + 2*j + 140*k, 2*i + 4*j + 150*k, 8*j + 104*k, 152*k])
sage: I.is_integral()
False
"""
if self.__left_order is not None:
return self.free_module() <= self.left_order().free_module()
elif self.__right_order is not None:
return self.free_module() <= self.right_order().free_module()
else:
self_square = self**2
return self_square.free_module() <= self.free_module()

def primitive_decomposition(self):
r"""
Let `I` = ``self``. If `I` is an integral left `\mathcal{O}`-ideal return its decomposition
as an equivalent primitive ideal and an integer such that their product is the initial ideal.
OUTPUTS: and quivalent primitive ideal to `I`, i.e. equivalent ideal not contained in `n\mathcal{O}` for any `n>0`, and the smallest integer such that `I \subset g\mathcal{O}`.
EXAMPLES::
sage: A.<i,j,k> = QuaternionAlgebra(QQ, -1,-11)
sage: I = A.ideal([1/2 + 1/2*i + 1/2*j + 3/2*k, i + k, j + k, 2*k])
sage: I.primitive_decomposition()
(Fractional ideal (1/2 + 1/2*i + 1/2*j + 3/2*k, i + k, j + k, 2*k), 1)
sage: J = A.ideal([7/2 + 7/2*i + 49/2*j + 91/2*k, 7*i + 21*k, 35*j + 35*k, 70*k])
sage: Jequiv, g = J.primitive_decomposition()
sage: Jequiv*g == J
True
sage: Jequiv, g
(Fractional ideal (1/2 + 1/2*i + 7/2*j + 13/2*k, i + 3*k, 5*j + 5*k, 10*k), 7)
TESTS:
Checks on random crafted ideals that they decompose as expected::
sage: for d in ( m for m in range(400, 750) if is_squarefree(m) ):
....: A = QuaternionAlgebra(d)
....: O = A.maximal_order()
....: for _ in range(10):
....: a = O.random_element()
....: if not a.is_constant(): # avoids a = 0
....: I = a*O + a.reduced_norm()*O
....: if I.is_integral():
....: J,g = I.primitive_decomposition()
....: assert J*g == I
....: assert J.is_primitive()
"""
if not self.is_integral():
raise ValueError("primitive ideals are defined only for integral ideals")

I_basis = self.basis_matrix()
O_basis = self.left_order().basis_matrix()

# Write I in the basis of its left order via rref
M = O_basis.solve_left(I_basis)
g = Integer(gcd(M.list()))

# If g is 1 then the ideal is primitive
if g.is_one():
return self, g

J = self.scale(1/g)

return J, g

def is_primitive(self):
r"""
Check if the quaternion fractional ideal is primitive. An integral left
$O$-ideal for some order $O$ is said primitive if for all integers $n > 1$
$I$ is not contained in $nO$.
OUTPUT: a boolean.
EXAMPLES::
sage: A.<i,j,k> = QuaternionAlgebra(QQ, -1,-11)
sage: I = A.ideal([1/2 + 1/2*i + 1/2*j + 3/2*k, i + k, j + k, 2*k])
sage: I.is_primitive()
True
sage: (2*I).is_primitive()
False
"""
_,g = self.primitive_decomposition()
return g.is_one()

#######################################################################
# Some utility functions that are needed here and are too
# specialized to go elsewhere.
Expand Down

0 comments on commit 2c6ebe5

Please sign in to comment.