# How do I modify a symmetric matrix while maintaining symmetry?

I'm trying to figure out how to create a For loop for a symmetric matrix. I have a 5 $$\times$$ 5 symmetric matrix consisting of 1's and 0's and I'm trying to perform the following:

I want to create a For loop that will randomly pick an [[i, j]] point in the matrix and randomly change that corresponding value at that position to either a 0 or 1. For example, let's say position [[1, 3]] in my matrix is randomly picked. If the value there was originally 0, and then randomly the system replaces that value with 0, then the number won't change. If the system randomly picked 1 instead, then the original 0 is changed to 1. All the while, the corresponding [[j, i]] value is undergoing the same process due to the symmetry of the matrix. Lastly, the changes from each iteration need to be consistent throughout. For example, in the above example, if [[1, 3]] was changed from 0 $$\rightarrow$$ 1 then when the process is performed again, the new matrix is used not the original one.

There is no "end point" so to say in regards to the random chance. I just wish to simulate the changing matrix an infinite number of times and after each step looking to see how the matrix has changed.

• I think a For loop not a necessity. Commented Mar 10, 2020 at 2:14
• Commented Mar 10, 2020 at 2:18

First, define an $$n$$-by-$$n$$ symmetric matrix of all zeros and ones:

n = 5; a = RandomInteger[{0, 1}, {n, n}];
a = UpperTriangularize[a] + LowerTriangularize[Transpose[a]] -
DiagonalMatrix[Diagonal[a]]


Now define a function that randomly changes two of the elements while maintaining symmetry:

change[x_] := Module[{b = x},
{i, j} = RandomChoice[Range[n], 2];
b[[i, j]] = b[[j, i]] = RandomInteger[{0, 1}]; b]


To apply the function:

change[a]


If you want to see 10 of them,

NestList[change, a, 10]

• Hi, could you elaborate on why you added b = x? Also is change[x_] := Module[{b=x}…. essentially stating that when x is called -> change x, but keep the value there for subsequent iterations of the function?
– Mark
Commented Mar 10, 2020 at 15:58
• When you have a Module with input (x in this case) you cannot reset the value of x directly inside the module. So I set b=x and then changed the values within the b matrix, and this is what is returned by the function. Commented Mar 10, 2020 at 17:19

You might find this interactive version educational.

With[{n = 5},
DynamicModule[{m = ConstantArray[0, {n, n}], nextM},
nextM[] :=
Module[{i, j},
{i, j} = RandomInteger[{1, n}, 2];
m[[i, j]] = m[[j, i]] = RandomInteger[]];
Manipulate[
m // MatrixForm,
Row[{Invisible @ Button["********", {}], Button["Next", nextM[]]}],
ControlPlacement -> Bottom]]]


The matrix is initialized as all zeros, but you can change the initialization to suit yourself. Each time you press Next, the function nextM performs your randomization preserving symmetry. Envetually, it might look like this:

One fast way to implement this is to make use of SparseArray. Let us first define the dimension of the matrix:

dim=5


We can then then define the command matrix whose $$n^\text{th}$$ value represents $$n^\text{th}$$ iteration:

matrix[0] = ConstantArray[0, {dim, dim}];
matrix[n_] := matrix[n] = matrix[n - 1] +
With[{a = RandomInteger[{1, dim}], b = RandomInteger[{1, dim}]},
SparseArray[{{a, b} -> 1, {b, a} -> 1}, {dim, dim}]
];


We note three things:

• matrix[0] represents the initial condition, which I choose to be a matrix of all zeros
• matrix[n] is symmetric by construction
• We implemented the change as mere addition; we will restrict to the domain $$\{0,1\}$$ at the end. This is to achieve better performance; likewise, we used memoization to trade memory for speed.

Now, we can immediately access any desired result using Mod command:

Mod[matrix[4],2]
(* {{0, 0, 0, 0, 0}, {0, 0, 0, 1, 0}, {0, 0, 0, 0, 1}, {0, 1, 0, 0, 0}, {0, 0, 1, 0, 0}} *)


We can visualize the change using Animate and ArrayPlot commands; for example:

Animate[ArrayPlot[Mod[matrix[n], 2]], {n, 1, 100, 1}, AnimationRate -> 10]


The way we wrote down the code scales pretty nicely with bigger matrices; for example, for dim=50,

Animate[ArrayPlot[Mod[matrix[n], 2]], {n, 1, 400, 1}, AnimationRate -> 100]


yields