Ask Your Question
1

matrix is found singular over CC, nonsingular over CDF

asked 2021-03-25 02:03:28 +0200

beanplantz gravatar image

updated 2021-03-25 03:49:05 +0200

slelievre gravatar image

I am trying to take the inverse of complex valued matrix where every entry is either +/-1,+/-i,or 0. The matrices are quite large and I am getting substantial rounding errors when I construct the matrix using "matrix(CDF,array)" and then take the inverse, but I still get an output.

When I construct the matrix using the same array but using "matrix(CC,array)" and then take the inverse I get this error: ZeroDivisionError: input matrix must be nonsingular

I am confused because the array when I use "matrix(CC,array)" is exactly the same as the array when I use CDF, however "matrix(CDF,array)" is nonsingular and the function inverse works. Why is this happening and is there another way I can avoid large rounding errors when taking the inverse?

I hope this is enough detail. I'm not really sure how to provide an example of this error occurring since the smallest example of the array I am working with is still quite large (52x52) and I haven't been able to get this error to occur with smaller simpler arrays.

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
0

answered 2021-03-25 02:32:16 +0200

slelievre gravatar image

updated 2021-03-26 11:18:17 +0200

Dealing with rounding errors

Why is this happening and is there another way I can avoid large rounding errors when taking the inverse?

This is happening because CC and CDF use floating-point numbers, and computations are thus inexact and subject to rounding errors.

Instead of working with CC or CDF, one could

  • use matrices over GaussianIntegers() or ZZ[i] or QQ[i] or QQbar for exact computations

  • use matrices over CBF ("complex ball field") for floating-point computations with rigorous error bounds


Providing a large example

I'm not really sure how to provide an example of this error occurring since the smallest example of the array I am working with is (52x52).

Communicating a 52 x 52 matrix with entries in {0, 1, -1, i, -i} is doable.

You can encode the matrix and provide decoding instructions rather than the matrix itself.

One possible encoding, since the entries can only take 5 values, take them as 5-ary digits; then each row can be thought of as the 5-ary expansion of a number. If we agree on the digits and communicate the numbers, we're good.

Here is a random matrix a with entries in {0, 1, -1, i, -i}:

sage: G = GaussianIntegers()
sage: U = [0, 1, -1, i, -i]

sage: a = matrix(G, 52, lambda i, j: U[randint(0, 4)])

Encoded matrix:

sage: b = [Integer(tuple(U.index(e) for e in row), 5) for row in a]

sage: print(b)
[1986835196674783292709127771671427698, 372532889760445898415871372893604877,
 29903254311383361818758881193795318, 1358695302115484662298806740046547384,
 1537321601024823802437657316988965568, 807200500103255107975400681439180354,
 567350510853383980331713019521919561, 1502850803304703506587108729499355006,
 846884730762028905888265726139310683, 137381915837271267181515478275643286,
 522105367460276163750943030646864364, 1062521690576328608603843582516522599,
 899547582492594668160772320652245190, 767732247768012897653127687752209191,
 629354811960707798077793065391805161, 922202162939977177914455168534168765,
 1729869497057901779087386639626774141, 1868018985439944039499425518652161649,
 1296299082686624643142119402841062894, 1064799841987832209268578137251968874,
 2155066789175869415783929309121456698, 267366791364966820259349410583047599,
 1632002494019334195780113340724191796, 2192661273536615612340019587291366905,
 1762917404578120599684457836032844498, 228986171419406644876547615831863389,
 2101920423365829833128536344495944345, 660985714605962040665526677335410210,
 873334831095240711598788236281716427, 1744121894438415469560277438117935725,
 2210059965689974187926035573546483126, 1594508474721458635473949546648185838,
 518211385383214049244941993118895991, 231206763245123017363282654207827645,
 1748059359372987512622900717899928645, 259988738192311572545249238464600548,
 2007721547194093983826996655201647232, 1240843285105582949996674635390136465,
 1736982326629685244276013105887136315, 435682393610221223713098672542297123,
 66566788503415822985489945441756435, 1141561970732274264554486688206105649,
 2044822779971527183978088623745613537, 17299608296692077102235770236630252,
 780853597789891512314851615527578148, 427428566224687826328803693567479441,
 1922351158930802787176924223394683886, 2104373328835002410314401979576425296,
 1317300586469460326137557530572476230, 1736284365530465805899187629996562866,
 2132757211837100962505268985637520292, 147031314086172436786678135727403627]

To decode:

sage: aa = matrix(G, 52, [[U[d] for d in r.digits(5, padto=52)] for r in b])
sage: aa == a
True

Here is a function that takes a matrix as an argument, and returns "short enough code" to recreate that matrix.

def matrix_code(a):
    r"""
    Return code for a matrix with entries in {0, 1, -1, i, -i}.

    EXAMPLE::

        sage: G = GaussianIntegers()
        sage: U = [0, 1, -1, i, -i]
        sage: a = matrix(G, 52, lambda i, j: U[randint(0, 4)])
        sage: matrix_code(a)
        ...
    """
    G = GaussianIntegers()
    U = [0, 1, -1, i, -i]
    m = a.nrows()
    n = a.ncols()
    b = [Integer(tuple(U.index(e) for e in row), 5) for row in a]
    print(f"""
    G = GaussianIntegers()
    U = [0, 1, -1, i, -i]
    b = {b}
    a = matrix(G, {m}, {n}, [[U[d] for d in r.digits(5, padto={n})] for r in b])
    """)

Run it on your matrix. Edit your question, pasting the output. Then we can all play with the same matrix.

edit flag offensive delete link more

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: 2021-03-25 02:03:28 +0200

Seen: 41 times

Last updated: Mar 26