# matrix is found singular over CC, nonsingular over CDF

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 close merge delete

Sort by » oldest newest most voted

### 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.

more