-
-
Notifications
You must be signed in to change notification settings - Fork 481
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Quaternion Algebra Fractional Ideal improvements - equivalence and reduced bases #37100
Conversation
if not self.quaternion_algebra().is_definite(): | ||
if not self.quadratic_form().is_positive_definite(): | ||
raise TypeError("The quaternion algebra must be definite") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aren't these two tests equivalent? Were they duplicated by accident?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, these two should be equivalent - I believe the latter test was originally put in place for the method to also work for "lattices" of non-maximal rank, until it came up that .gram_matrix()
needs a full rank lattice anyway. I'll remove the second test.
""" | ||
# shorthand: let I be self | ||
if not isinstance(self, QuaternionFractionalIdeal_rational): | ||
if not isinstance(J, QuaternionFractionalIdeal_rational): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say in this case we should probably throw a TypeError
. Returning False
is arguably correct, but I can't see any situation in which users will rely on this behaviour wilfully, hence failing visibly is better.
def is_equivalent(self, J, B=10) -> bool: | ||
""" | ||
Return ``True`` if ``self`` and ``J`` are equivalent as right ideals. | ||
def is_equivalent(self, J, B=10, certificate=False, side=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally I would simply deprecate this method in favor of the two new explicitly named one-sided methods: Having it default to .is_right_equivalent()
is arbitrary and ambiguous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So should I add a deprecation warning for now to set it up for future removal, or should I remove it immediately?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to The Rules, we're only allowed to remove things once they've been deprecated for one year, so it has to be the former: Add a deprecation warning. (If you agree, that is: I don't have a strong opinion about this either way.)
raise NotImplementedError('equivalence test of ideals not implemented' | ||
'for indefinite quaternion algebras') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
raise NotImplementedError('equivalence test of ideals not implemented' | |
'for indefinite quaternion algebras') | |
raise NotImplementedError('equivalence test of ideals not implemented' | |
' for indefinite quaternion algebras') |
# Use Pari's qfminim with flag = 1 to find alpha with N(alpha) = N(I) | ||
_,v = self.quadratic_form().__pari__().qfminim(None, None, 1) | ||
return True, sum(ZZ(c)*g for c,g in zip(v, self.basis())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here re: the .minimal_element()
method from #34976.
'implemented in indefinite' | ||
'quaternion algebras') | ||
|
||
if len(self.basis()) < 4: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this fail?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On faulty input, I believe, since calling B.ideal([i,j])
for a quaternion algebra B
gives a "fractional ideal", but it really is just a two-dimensional sublattice with basis (i,j)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, I was expecting the constructor for fractional ideals to check the rank. That should probably be fixed eventually, but it doesn't necessarily have to be done here and now.
raise NotImplementedError('principality test not' | ||
'implemented in indefinite' | ||
'quaternion algebras') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
raise NotImplementedError('principality test not' | |
'implemented in indefinite' | |
'quaternion algebras') | |
raise NotImplementedError('principality test not' | |
' implemented in indefinite' | |
' quaternion algebras') |
# Use Pari's qfminim with flag = 1 to find alpha as above | ||
_,v = IJbar.quadratic_form().__pari__().qfminim(None, None, 1) | ||
alpha = sum(ZZ(c)*g for c,g in zip(v, IJbar.basis())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one could be alpha = IJbar.minimal_element()
once #34976 is merged, but pulling that in as a dependency seems a bit overkill just to deduplicate these two lines. Maybe add a TODO so that eventually someone can replace it later?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it might be a good idea to test definiteness with this PR's .is_definite()
-method as well, it might actually be a good idea to put a dependency on this PR to yours (see also this review comment).
# As explained by Pizer, we now only need to rescale alpha by 1/N(J) | ||
return True, alpha * (1/J.norm()) | ||
|
||
def is_principal(self, certificate=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method duplicates quite some code from the equivalence tests. Perhaps the equivalence tests could/should just end up calling .is_principal()
on IJbar
instead of repeating all the steps on that special case?
b65ec82
to
554e920
Compare
Since beta 7 of Sage 10.3 was just released, I have instead decided to merge #34976 into this branch. In the progress of figuring this out, however, I caused some chaos in the PR; in particular, GitHub now thinks that a lot of files in |
it was not a good idea to merge with the latest develop. One better way if you really want that is to use github's To fix the merge, you could try to rebase your branch on top of develop using |
That's how I did it originally, but then I wrongly assumed that I had to revert it to merge with the other PR's branch, and after that I couldn't do it this way again. Thanks for the suggestion, I'll try to do that. |
I rebased the branch on upstream/develop, but it still lists the |
…(), and is_equivalent certificate
- Removed greek letter alpha in docstrings in hopes of this fixing infinite build loops - Updated `.is_definite()` to fit PR sagemath#37173 (up to the reference to Voight's book) - Other small modifications of docstrings, comments and error warnings - Slightly cleaned up code with respect to intermediately defined variables
- Added deprecation warning for `.is_equivalent` - Removed unnecessary call of `.is_positive_definite()` in `.reduced_basis()` - Reduced `.is_right_equivalent` to `.is_principal` with suitable rescaling - Fixed some error warnings - Modified docstrings, moved examples to non-deprecated methods and randomized test of `.is_principal`
- Modified definiteness check in `.minimal_element()` and `.isomorphism_to`; also added check of the base field in the latter method - Reduced search for a generator in `.is_principal()` to a call to `.minimal_element()`
The merge still seems broken. I've attempted to fix it on a new branch by cherry-picking all non-merge commits from here on top of the current You can get my version by adding my fork as a remote and overwriting your version of this branch with mine:
After that, you should be able to |
Perfect, that worked - thanks for the help! |
This is not a fix for the issue - it just adapts the error warning to be more ambiguous, as suggested in sagemath#34976 (comment)
Documentation preview for this PR (built with commit 8d75358; changes) is ready! 🎉 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me now, thanks!
Includes the following changes
.is_definite()
to quaternion algebras, which performs a check on the invariants..reduced_basis()
to quaternion fractional ideals which uses LLL to find the basis of shortest elements.is_equivalent
to include aside
parameter which can be set to'left'
or'right'
to do left-ideal or right-ideal equivalence, and acertificate
parameter which if true, returns the element a such that I = J*a. Throws aNotImplementedError
for indefinite quaternion algebras which fixes Ideal equivalence in indefinite quaternion algebras #37080 . Backwards compatible..is_left_equivalent
and.is_right_equivalent
..is_principal
to quaternion fractional ideals of rank 4 in definite quaternion algebras. Includescertificate
parameter for finding generator. Finds the shortest norm element in the lattice and checks its norm.isomorphism_to
ofquaternion_algebra.py
does not find an isomorphism of isomorphic maximal orders #37337, bug in quaternion order.isomorphism_to
where it cannot find the isomorphism betweenisomorphism_to
method multiple times on inputsNotImplementedError
in cases not covered.@S17A05 @Jonathke
#sd123