Ask Your Question
1

How do I "tidy up" error terms in a matrix?

asked 2012-11-12 13:20:49 +0100

GaryMak gravatar image

Hi - I have some calculation results in the form of a complex Gram matrix which are all supposed to be integers (or "obvious" algebraic numbers which I know about). However inevitably in the course of creating them as inner products, some "error" terms arise which are of a size of the order of 10^-16 (real and/or complex). Is there an easy way to "clean up" my matrix with some sort of threshold, so that things which differ from a user-specified list of algebraic numbers by less than a tiny amount like 10^-15, are assumed to be the relevant algebraic number? At the moment I'm having to do it by a bunch of hideous if-statement contortions but I'm sure there's a better way! Many thanks in advance for any help.

edit retag flag offensive close merge delete

Comments

I've wondered similar things myself. It would be nice to have something like `fnormal` in Maple. Can you apply `round` in some way using a `map` command to help. For example, `round(1+10.^(-16),5)` gives `1.0`.

calc314 gravatar imagecalc314 ( 2012-11-12 13:47:18 +0100 )edit

thanks - as an example for future reference, I used John's suggestion below in the following form: mat.apply_map( lambda x: (d*abs(x)^2).round()/d ); where I knew that the largest denominator for the abs values was d (one has to be a little more careful with complex entries)

GaryMak gravatar imageGaryMak ( 2012-11-12 14:24:02 +0100 )edit

2 Answers

Sort by ยป oldest newest most voted
2

answered 2012-11-13 18:13:12 +0100

Volker Braun gravatar image

Matrices over ComplexField don't implement round(), unfortunately. But the following variant of John's answer works:

sage: mat = matrix(3, 3, [2+1e-15+i*1e-15]*9)
sage: mat.change_ring(CDF).round()
[2.0 2.0 2.0]
[2.0 2.0 2.0]
[2.0 2.0 2.0]
edit flag offensive delete link more

Comments

I applied 'real()' and then 'round()' in my answer.

John Palmieri gravatar imageJohn Palmieri ( 2012-11-13 23:34:22 +0100 )edit

Agreed. I just wanted to point out that matrices over some rings have already a round() method.

Volker Braun gravatar imageVolker Braun ( 2012-11-14 00:01:03 +0100 )edit

thanks Volker - that's helpful.

GaryMak gravatar imageGaryMak ( 2012-11-15 05:14:52 +0100 )edit
2

answered 2012-11-12 13:45:56 +0100

This will clean things up if the entries are integers. If the entries differ by small amounts from known algebraic numbers, that's more complicated.

sage: mat = matrix(3, 3, [2+1e-15+i*1e-15]*9)
sage: mat
[2.00000000000000 + 1.00000000000000e-15*I 2.00000000000000 + 1.00000000000000e-15*I 2.00000000000000 + 1.00000000000000e-15*I]
[2.00000000000000 + 1.00000000000000e-15*I 2.00000000000000 + 1.00000000000000e-15*I 2.00000000000000 + 1.00000000000000e-15*I]
[2.00000000000000 + 1.00000000000000e-15*I 2.00000000000000 + 1.00000000000000e-15*I 2.00000000000000 + 1.00000000000000e-15*I]
sage: mat.apply_map(lambda x: x.real().round())
[2 2 2]
[2 2 2]
[2 2 2]
sage: mat_Z = mat.apply_map(lambda x: x.real().round())
sage: mat_Z.base_ring()
Integer Ring
edit flag offensive delete link more

Comments

thanks John - that's certainly a thousand times neater than the mess I had before! The algebraic number thing is almost too good to be true, but maybe someone out there knows a way ... (obviously the list would have to be "restricted" in the sense that the abs vals of the entries would have to be separated by more than twice the error term or something, etc etc)

GaryMak gravatar imageGaryMak ( 2012-11-12 14:05:52 +0100 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2012-11-12 13:20:49 +0100

Seen: 644 times

Last updated: Nov 13 '12