Generating Symmetric Matrices in Numpy

47,582

Solution 1

You could just do something like:

import numpy as np

N = 100
b = np.random.random_integers(-2000,2000,size=(N,N))
b_symm = (b + b.T)/2

Where you can choose from whatever distribution you want in the np.random or equivalent scipy module.

Update: If you are trying to build graph-like structures, definitely check out the networkx package:

http://networkx.lanl.gov

which has a number of built-in routines to build graphs:

http://networkx.lanl.gov/reference/generators.html

Also if you want to add some number of randomly placed zeros, you can always generate a random set of indices and replace the values with zero.

Solution 2

I'd better do:

a = np.random.rand(N, N)
m = np.tril(a) + np.tril(a, -1).T

because in this case all elements of a matrix are from same distribution (uniform in this case).

Solution 3

There is a mathematical property in matrices that allows such structure to be created easily: A.T * A where A is a row vector and A.t is the transpose (a column vector). This always returns a square positive definite symmetric matrix which is always invertible, so you have no worries with null pivots ;)

# any matrix algebra will do it, numpy is simpler
import numpy.matlib as mt

# create a row vector of given size
size  = 3
A = mt.rand(1,size)

# create a symmetric matrix size * size
symmA = A.T * A

Solution 4

import numpy as np

n = 5
M = np.random.randint(-2000,2000,(n,n))
symm = [email protected]
# test for symmetry
print(symm == symm.T)

This worked for me

Share:
47,582
Admin
Author by

Admin

Updated on June 16, 2020

Comments

  • Admin
    Admin almost 4 years

    I am trying to generate symmetric matrices in numpy. Specifically, these matrices are to have random places entries, and in each entry the contents can be random. Along the main diagonal we are not concerned with what enties are in there, so I have randomized those as well.

    The approach I have taken is to first generate a nxn all zero matrix and simply loop over the indices of the matrices. However, given considering looping is relatively expensive in python, I'm wondering if I can acheive the same thing without using python's for loops.

    Is there some things built into numpy that allow me to acheive my goal more efficiently?

    Here is my current code:

    import numpy as np
    import random
    
    def empty(x, y):
        return x*0
    
    b = np.fromfunction(empty, (n, n), dtype = int)
    
    for i in range(0, n):
        for j in range(0, n):
            if i == j:
                b[i][j] = random.randrange(-2000, 2000)
            else:
                switch = random.random()
                random.seed()
                if switch > random.random():
                    a = random.randrange(-2000, 2000)
                    b[i][j] = a
                    b[j][i] = a
                else:
                    b[i][j] = 0
                    b[j][i] = 0
    
  • Admin
    Admin almost 12 years
    Thanks! That is an efficient solution. However, is there some way I can get it to place zeros in places randomly? This matrix is supposed to represent an kind of adjacency matrix for a graph, so having a matrix with randomly distributed zero's is preferable.
  • unutbu
    unutbu almost 12 years
    @Ryan: Do you care what kind of distribution the random entries have? If you add b + b.T, you will get a non-uniform distribution concentrated around 0.
  • Admin
    Admin almost 12 years
    I am verifying some properties of matrices. Its more an effort to provide convincing evidence of some mathematical properties, so the distribution here is not so important. Thanks though!
  • Ben Usman
    Ben Usman over 9 years
    @unutbu , true, use np.tril(a) + np.tril(a, -1).T then.
  • Arash
    Arash over 7 years
    That's a very elegant way of keeping the same distribution!
  • Bruno
    Bruno about 4 years
    ps: "always invertible" is true for matrices, not for vectors. So, it would be numerically more robust to do mt.rand(size, size). It will return a size x size matrix anyway, but more expensive computationally.
  • sushmit
    sushmit almost 3 years
    np.random.randint(-5,5,size=(N,N)) seems to have been deprecated need to use randint
  • Oalvinegro
    Oalvinegro over 2 years
    It doesn't generates a SYMMETRIC matrix