quadratic forms signature_vector() gives different results for real cyclotomics and for reals

103 views
Skip to first unread message

Ignat Soroko

unread,
Oct 17, 2019, 8:12:02 PM10/17/19
to sage-devel
I am computing the signature of a quadratic form having entries 0, 1, -1/2, -sqrt(2)/2. I noticed that the result of signature_vector() is different if we treat the number sqrt(2) as a cyclotomic or as a real number. Please look at the example:

sage: K.<z>=CyclotomicField(8)
sage: a=z-z^3  # a is a square root of 2
sage: a-sqrt(2)
0
sage: Q=QuadraticForm(K,8,[1/2,-a/2,0,0,0,0,0,0,1/2,-a/2,0,0,0,0,0,1/2,-1/2,0,0,
....: 0,0,1/2,-1/2,0,0,0,1/2,-1/2,0,0,1/2,-a/2,0,1/2,-a/2,1/2])
sage: Q.signature_vector()
(8, 0, 0)

this cannot be true since there exists an isotropic vector:

sage: v=vector([1,a,1,0,0,0,0,0])
sage: v*Q.matrix()*v
0

Let's try it over reals:

sage: a=sqrt(2)
sage: Q=QuadraticForm(RR,8,[1/2,-a/2,0,0,0,0,0,0,1/2,-a/2,0,0,0,0,0,1/2,-1/2,0,0
....: ,0,0,1/2,-1/2,0,0,0,1/2,-1/2,0,0,1/2,-a/2,0,1/2,-a/2,1/2])
sage: Q.signature_vector()
(6, 2, 0)

however, the isotropic vector above is not isotropic anymore:

sage: v=vector([1,a,1,0,0,0,0,0])
sage: v*Q.matrix()*v
sqrt(2)*(1.00000000000000*sqrt(2) - 1.41421356237310) - 1.41421356237310*sqrt(2) + 2.00000000000000

I also tried to define 

sage: a=sqrt(AA(2))
sage: Q=QuadraticForm(AA,8,[1/2,-a/2,0,0,0,0,0,0,1/2,-a/2,0,0,0,0,0,1/2,-1/2,0,0
....: ,0,0,1/2,-1/2,0,0,0,1/2,-1/2,0,0,1/2,-a/2,0,1/2,-a/2,1/2])

but Q.signature_vector() gives a runtime error with many lines of code ending in:

RuntimeError: maximum recursion depth exceeded


Questions:
1) is Q.signature_vector() over cyclotomic field is interpreted in some other way than for reals, thus making the result (8,0,0) somehow correct?

2) Which setting would guarantee both the correct result for signature_vector() using the exact arithmetic and at the same time show that v is actually an isotropic vector?

Thank you!



Frédéric Chapoton

unread,
Oct 18, 2019, 7:24:51 AM10/18/19
to sage-devel
This works (in sage 8.9) when using

K.<z>=QuadraticField(2)

Frédéric Chapoton

unread,
Oct 18, 2019, 7:38:50 AM10/18/19
to sage-devel
The bug over the cyclotomic field is caused by


sage
: K = CyclotomicField(8)
sage
: K(-1/16) > 0
True

Ignat Soroko

unread,
Oct 19, 2019, 12:24:14 AM10/19/19
to sage-devel
Thank you for figuring that out! Shall we alert the developers about it? It is my first time on that forum, I am not sure I know how to do that...

And what about the behavior that occurs when we try to use the field AA:


sage: a=sqrt(AA(2))
sage: Q=QuadraticForm(AA,8,[1/2,-a/2,0,0,0,0,0,0,1/2,-a/2,0,0,0,0,0,1/2,-1/2,0,0
....: ,0,0,1/2,-1/2,0,0,0,1/2,-1/2,0,0,1/2,-a/2,0,1/2,-a/2,1/2])
sage: Q.signature_vector()
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-146-fedf8894b12c> in <module>()
----> 1 Q.signature_vector()

/opt/sagemath-8.6/local/lib/python2.7/site-packages/sage/quadratic_forms/quadratic_form__local_field_invariants.pyc in signature_vector(self)
    329
    330     """
--> 331     diag = self.rational_diagonal_form()
    332     p = 0
    333     n = 0

/opt/sagemath-8.6/local/lib/python2.7/site-packages/sage/quadratic_forms/quadratic_form__local_field_invariants.pyc in rational_diagonal_form(self, return_matrix)
    175     # Quadratic forms do not support immutability, so we need to make
    176     # a copy to be safe.
--> 177     Q = deepcopy(Q)
    178
    179     if return_matrix:

/opt/sagemath-8.6/local/lib/python2.7/copy.pyc in deepcopy(x, memo, _nil)
    188                             raise Error(
    189                                 "un(deep)copyable object of type %s" % cls)
--> 190                 y = _reconstruct(x, rv, 1, memo)
    191
    192     memo[d] = y

/opt/sagemath-8.6/local/lib/python2.7/copy.pyc in _reconstruct(x, info, deep, memo)
    332     if state is not None:
    333         if deep:
--> 334             state = deepcopy(state, memo)
    335         if hasattr(y, '__setstate__'):
    336             y.__setstate__(state)

/opt/sagemath-8.6/local/lib/python2.7/copy.pyc in deepcopy(x, memo, _nil)
    161     copier = _deepcopy_dispatch.get(cls)
    162     if copier:
--> 163         y = copier(x, memo)
    164     else:
    165         try:

/opt/sagemath-8.6/local/lib/python2.7/copy.pyc in _deepcopy_dict(x, memo)
    255     memo[id(x)] = y
    256     for key, value in x.iteritems():
--> 257         y[deepcopy(key, memo)] = deepcopy(value, memo)
    258     return y
    259 d[dict] = _deepcopy_dict

/opt/sagemath-8.6/local/lib/python2.7/copy.pyc in deepcopy(x, memo, _nil)
    161     copier = _deepcopy_dispatch.get(cls)
    162     if copier:
--> 163         y = copier(x, memo)
    164     else:
    165         try:

/opt/sagemath-8.6/local/lib/python2.7/copy.pyc in _deepcopy_list(x, memo)
    228     memo[id(x)] = y
    229     for a in x:
--> 230         y.append(deepcopy(a, memo))
    231     return y
    232 d[list] = _deepcopy_list

/opt/sagemath-8.6/local/lib/python2.7/copy.pyc in deepcopy(x, memo, _nil)
    188                             raise Error(
    189                                 "un(deep)copyable object of type %s" % cls)
--> 190                 y = _reconstruct(x, rv, 1, memo)
    191
    192     memo[d] = y

/opt/sagemath-8.6/local/lib/python2.7/copy.pyc in _reconstruct(x, info, deep, memo)
    326         dictiter = None
    327     if deep:
--> 328         args = deepcopy(args, memo)
    329     y = callable(*args)
    330     memo[id(x)] = y

/opt/sagemath-8.6/local/lib/python2.7/copy.pyc in deepcopy(x, memo, _nil)
    161     copier = _deepcopy_dispatch.get(cls)
    162     if copier:
--> 163         y = copier(x, memo)
    164     else:
    165         try:

/opt/sagemath-8.6/local/lib/python2.7/copy.pyc in _deepcopy_tuple(x, memo)
    235     y = []
    236     for a in x:
--> 237         y.append(deepcopy(a, memo))
    238     d = id(x)
    239     try:

... last 4 frames repeated, from the frame below ...

/opt/sagemath-8.6/local/lib/python2.7/copy.pyc in deepcopy(x, memo, _nil)
    188                             raise Error(
    189                                 "un(deep)copyable object of type %s" % cls)
--> 190                 y = _reconstruct(x, rv, 1, memo)
    191
    192     memo[d] = y

RuntimeError: maximum recursion depth exceeded
sage:

Dima Pasechnik

unread,
Oct 19, 2019, 9:00:40 AM10/19/19
to sage-devel
On Fri, Oct 18, 2019 at 12:38 PM Frédéric Chapoton <fchap...@gmail.com> wrote:
>
> The bug over the cyclotomic field is caused by
>
>
> sage: K = CyclotomicField(8)
> sage: K(-1/16) > 0
> True
>
This is not a bug, as the ordering of K has nothing to do with the ordering on
the real elements of K.

Note that

sage: K(-1/16).sign()
-1
sage: K(-1/16).sign()>0
False

works as it should. I have a pile of homeworks on my desk
and no time to look in the code now, but if indeed it can be fixed by
using `sign()` in appropriate places, it should be done.

I have opened https://trac.sagemath.org/ticket/28635
> --
> 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 sage-devel+...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sage-devel/710cf4ab-c782-4ad0-a195-fcd47ed1abc5%40googlegroups.com.

Simon Brandhorst

unread,
Oct 20, 2019, 6:38:38 AM10/20/19
to sage-devel
Dear Ignat Soroko,

the quadratic forms code was written with quadratic forms over QQ and over ZZ in mind. So I would be very sceptic about any functionality over number fields.
For instance the signature vector you mention does not make sense of the F.<a> =CyclotomicField(8). Instead of a single signature vector, over a number field you should
obtain a signature for each real embedding F. Since F has no real places it does not really have signatures. All infinite places are complex and all regular quadratic forms over CC are equivalent. So basically

sage: Q=QuadraticForm(K,8,[1/2,-a/2,0,0,0,0,0,0,1/2,-a/2,0,0,0,0,0,1/2,-1/2,0,0,
....: 0,0,1/2,-1/2,0,0,0,1/2,-1/2,0,0,1/2,-a/2,0,1/2,-a/2,1/2])
sage: Q.signature_vector()

should either raise a value error, or
be called signature_vectors() and return a dictionary of real places and signature vectors.

Best,
Simon

Dima Pasechnik

unread,
Oct 20, 2019, 8:09:17 AM10/20/19
to sage-...@googlegroups.com
On Sun, 20 Oct 2019 at 11:38, Simon Brandhorst <sbran...@web.de> wrote:
Dear Ignat Soroko,

the quadratic forms code was written with quadratic forms over QQ and over ZZ in mind. So I would be very sceptic about any functionality over number fields.
For instance the signature vector you mention does not make sense of the F.<a> =CyclotomicField(8). Instead of a single signature vector, over a number field you should
obtain a signature for each real embedding F. Since F has no real places it does not really have signatures. All infinite places are complex and all regular quadratic forms over CC are equivalent. So basically

sage: Q=QuadraticForm(K,8,[1/2,-a/2,0,0,0,0,0,0,1/2,-a/2,0,0,0,0,0,1/2,-1/2,0,0,
....: 0,0,1/2,-1/2,0,0,0,1/2,-1/2,0,0,1/2,-a/2,0,1/2,-a/2,1/2])
sage: Q.signature_vector()

should either raise a value error, or
be called signature_vectors() and return a dictionary of real places and signature vectors.

I thought at some point it was agreed that it makes sense for number fields to come with a default embedding. Is this already the case? Otherwise the meaning of sign() is not clear...
There is also a possibility of the signature being the same for every embedding, at least for a class of forms.

--
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 sage-devel+...@googlegroups.com.

Dima Pasechnik

unread,
Oct 21, 2019, 9:35:28 AM10/21/19
to sage-devel
On Sun, Oct 20, 2019 at 11:38 AM Simon Brandhorst <sbran...@web.de> wrote:
>
> Dear Ignat Soroko,
>
> the quadratic forms code was written with quadratic forms over QQ and over ZZ in mind. So I would be very sceptic about any functionality over number fields.
> For instance the signature vector you mention does not make sense of the F.<a> =CyclotomicField(8). Instead of a single signature vector, over a number field you should
> obtain a signature for each real embedding F.
CyclotomicField(8) has no real embedding.

Cyclotomic fields come with a default embedding:

The default embedding sends the generator to the complex primitive
n^{th} root of unity of least argument.

sage: CC(k.gen())
0.623489801858734 + 0.781831482468030*I

which is not real (and in general cyclotomic fields have no real embedding)

However, having a real embedding seems to be an unnecessary restriction, as
a symmetric matrix of real cyclotomics will have real eigenvalues, and
it has a signature.
(I don't know whether the signature will stay invariant if the
embedding changes - it should be either
easy to prove or easy to give a counterexample...)


Thanks,
Dima

Nils Bruin

unread,
Oct 21, 2019, 12:34:36 PM10/21/19
to sage-devel
On Monday, October 21, 2019 at 6:35:28 AM UTC-7, Dima Pasechnik wrote:
However, having a real embedding seems to be an unnecessary restriction, as
a symmetric matrix of real cyclotomics will have real eigenvalues, and
it has a signature.
(I don't  know whether the signature will stay invariant if the
embedding changes - it should be either
easy  to prove or easy to give a counterexample...)

The signature need not be galois-invariant for a form over a totally real field, since totally real algebraic numbers need not be totally positive/negative. For instance:

X^2+ sqrt(2) * Y^2

(and sqrt(2) is indeed a cyclotomic number)

Dima Pasechnik

unread,
Oct 21, 2019, 12:44:55 PM10/21/19
to sage-devel
ok, fine, but let us fix a complex embedding, and compute the signature.
 why does one need a real embedding for it?

--
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 sage-devel+...@googlegroups.com.

Simon Brandhorst

unread,
Oct 21, 2019, 4:48:40 PM10/21/19
to sage-devel
A quadratic form is a map F^n ---> F. The signature is supposed to be independent of the choice of basis.
So the number of positve/negative eigenvalues makes sense only for F = the reals.
For instance in the complex numbers you can always find an orthogonal basis with gram matrix diag(1,....,1,0,...0).
So here the invariant would be the rank.
If you want a signature over another field, you have to fix an embedding F--> RR and consider the quadratic form as a real quadratic form.

Reply all
Reply to author
Forward
0 new messages