Python matrix tools over $\mathbb{Z}_q$
This page provides the Python library matrixzq with functions to carry out matrix operations over $\mathbb{Z}_q$ ($\mathbb{Z}/q\mathbb{Z}$) in pure Python without using Numpy or Scipy.
Where q is a positive integer greater than 1. All matrix elements are expected to be nonnegative integers in the range [0, q-1]. All computations are carried out modulo q.
The modulus q does not have to be prime for most matrix arithmetical operations (add, multiply), but it must be prime to carry out operations that involve division (invert, solve).
Source code available on GitHub at https://github.com/davidi67/matrixzq
Example
import matrixzq as mzq mzq.set_modulus(11) print(f"q={mzq.get_modulus()}") # 11 # Invert a matrix M = mzq.new_matrix([[2,3,7],[4,5,10],[9,0,7]]) print("M ="); mzq.print_matrix(M) IM = mzq.invert(M) print("IM=invert(M)=");mzq.print_matrix(IM) # Multiply inverse by itself: should get identity IMM = mzq.multiply(IM, M) print(f"IM*M=\n{mzq.sprint_matrix(IMM)}") I = mzq.identity_matrix(len(M)) print("IM*M==I:", mzq.equality(I, IMM)) assert(mzq.equality(I, IMM)) # Solve the matrix equation Ax = b A = mzq.new_matrix([[1,1,1,1],[2,4,6,7],[4,5,3,5],[8,9,7,2]]) b = mzq.new_vector([6,0,4,5]) print("A=");mzq.print_matrix(A) print("b=",end='');mzq.print_vector(b) x = mzq.solve(A, b) print("Solve Ax=b => x =", mzq.sprint_vector(x)) # Check result ax = mzq.multiply(A, x) print("Check Ax =", mzq.sprint_vector(ax)) print("Ax==b:", mzq.equality(ax, b)) assert(mzq.equality(ax, b)) # Show the transpose of a matrix print("Transpose A^T=");mzq.print_matrix(mzq.transpose(A))Expected output:
q=11 M = [2, 3, 7] [4, 5, 10] [9, 0, 7] IM=invert(M)= [5, 8, 4] [1, 4, 9] [3, 7, 6] IM*M= [1, 0, 0] [0, 1, 0] [0, 0, 1] IM*M==I: True A= [1, 1, 1, 1] [2, 4, 6, 7] [4, 5, 3, 5] [8, 9, 7, 2] b=[6, 0, 4, 5] Solve Ax=b => x = [10, 2, 8, 8] Check Ax = [6, 0, 4, 5] Ax==b: True Transpose A^T= [1, 2, 4, 8] [1, 4, 5, 9] [1, 6, 3, 7] [1, 7, 5, 2]
Background
We wanted pure Python code to operate on matrices modulo an integer q to demonstrate some principles of lattice-based encryption schemes using Learning-With-Errors (LWE). We found the excellent code "BASIC Linear Algebra Tools in Pure Python without Numpy or Scipy" by Thom Ives at
https://github.com/ThomIves/BasicLinearAlgebraToolsPurePy
https://integratedmlai.com/basic-linear-algebra-tools-in-pure-python-without-numpy-or-scipy
This code is inspired and partly derived from Thom's excellent work. Thank you, Thom.
We have provided basic Python functions rather than a more-complicated class so you can easily extract and work with the underlying list of lists.
Contact us
To comment on this page or to tell us about a mistake, please send us a message.
This page first published 7 August 2023. Last updated 9 September 2025.