I don't think that in this case there would be a performance penality, the 
computation of the eigenvalues itself is not affected.  Regardless, I think 
that in general, a high level convenience method should be optimized for 
reliability, not for performance.  In fact, removing the optimization we 
could avoid the universe computation in eigenvalues = Sequence(res), which 
might be just as expensive.

Of course, if I know that the eigenvalues will be rational, it would be 
good to be able to tell the method that.  I am a bit unsure how difficult 
that would be.  I am guessing that the default ring cannot be the base 
ring, because that would break existing code, right?

Apart from that, I just found another snippet of the documentation, which 
says:

        The eigenvalues are elements of ``QQbar``, so they really represent
        exact roots of polynomials, not just approximations.

Here is what I would like to change:

diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx 
index 63102fb380b..0b3d2040e80 100644 
--- a/src/sage/matrix/matrix2.pyx 
+++ b/src/sage/matrix/matrix2.pyx 
@@ -7297,7 +7297,7 @@ cdef class Matrix(Matrix1): 
        res = [] 
        for f, e in self.charpoly().change_ring(K).factor(): 
            if f.degree() == 1: 
-                res.extend([-f.constant_coefficient()]*e) 
+                res.extend([A(-f.constant_coefficient())]*e) 
            else: 
                for r, ee in f.change_ring(A).roots(): 
                    res.extend([r]*(e*ee))

On Wednesday, 3 December 2025 at 18:47:23 UTC+1 Nils Bruin wrote:

> Your example hides a lesser consistency: the list of eigenvalues for a 
> matrix over QQ does seem to lie either in Q (if all the eigenvalues lie in 
> QQ) or in QQbar. Putting them in QQbar in all cases is of course the 
> general thing to do, but if you know your matrix has rational eigenvalues 
> and you just want to work with them (take their numerator and denominator 
> perhaps? reduce them mod p?) it could be quite annoying to find them in 
> QQbar. Arithmetic in QQbar is also going to be horribly slow in comparison.
>
> I can see why, with such an expensive general parent, there  might be an 
> argument to put the arguments in a smaller parent when possible (for all of 
> them). There is a practical argument to be made here for why one might want 
> to deviate from the purity of "parent of return value determined by parent 
> of input". 
>
> The documentation is formulated in a confusing way: It can be read as if 
> for matrices over QQ, only *separate* roots are returned: no multiplicity 
> information. I haven't tested this, but I'm pretty sure that's not what is 
> intended.
>
> The documentation also doesn't reflect the "parent optimization". I think 
> that's your main question. As described above, I think there's some 
> practical nuance to that...
>
> In actuality, due to the problem "eigenvalues in what field"? I'd probably 
> steer away from routines like "eigenvalues" in my own code, because I 
> wouldn't dare to trust the choice that's made. I probably instead would 
> just ask for the characteristic poly and determine its roots where I want 
> (that's almost never QQbar unless it's in an interactive situation), and 
> then work with that.
>
>
> On Wednesday, 3 December 2025 at 01:52:39 UTC-8 [email protected] wrote:
>
>> Do we really want that the parent of the result depends on the *value* of 
>> its input here, rather than on the parent of the input?
>>
>> Actually, strictly speaking the documentation promises something else:
>>
>>         Return a sequence of the eigenvalues of a matrix, with
>>         multiplicity. If the eigenvalues are roots of polynomials in 
>> ``QQ``,
>>         then ``QQbar`` elements are returned that represent each separate
>>         root.
>>
>> Do I misunderstand this, or *is* the behaviour a bug?  (If so, it is easy 
>> to fix.)
>>
>> I am guessing that harmonizing the hash of QQbar with the hash of QQ is 
>> expensive.  Also, I don't think it would be the correct fix.
>>
>> Martin
>> On Tuesday, 2 December 2025 at 23:20:30 UTC+1 Martin R wrote:
>>
>>> sage: OZ = lambda P: (ones_matrix(P.cardinality()) - P.lequal_matrix())
>>> sage: set(min(OZ(P).eigenvalues()) for n in range(1, 7) for P in 
>>> posets(n))
>>> {-1, -1, 0}
>>> sage: [type(x) for x in _]
>>> [<class 'sage.rings.rational.Rational'>,
>>>  <class 'sage.rings.rational.Rational'>,
>>>  <class 'sage.rings.qqbar.AlgebraicNumber'>]
>>>
>>>

-- 
You received this message because you are subscribed to the Google Groups 
"sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/sage-devel/6f4f4480-6628-4aa4-945d-6c4894c1649cn%40googlegroups.com.

Reply via email to