How can I create a random symmetric matrix in this way?

The most straight forward way for me to think about is like this:

H[N_] := RandomReal[{0,10},{N,N}]
symmetryH[N_]:=(H[N]+H[N]\[Transpose])/2
symmetryH[4]//MatrixForm


However, the above code does not work because the second call of H[N] will generate a different matrix from the first call. How can I get around this side effect?

-

First, you just have to create exactly one H[N] and use this 2 times. This can be achieved by

H[n_] := RandomReal[{0, 10}, {n, n}]
symmetryH[n_] := With[{hn = H[n]},
(hn + Transpose[hn])/2
]


Second, please do not use N as variable or pattern. It might shoot you in the foot because it is a function in Mathematica.

Finally, you should realize, that your approach contains a very serious flaw. What makes you believe, that you can calculate the mean of your matrix and its transpose while still maintain the same distribution for your randomness? Let us make a very quick example, where we create 1000 of your random matrices:

data = Table[symmetryH[4], {1000}];


Now, let us look on all upper left elements and plot their histogram

Histogram[data[[All, 1, 1]]]


Exactly what you wanted. Evenly distributed. Let's take a look on the upper right corner

Histogram[data[[All, 1, -1]]]


Uhh, not so nice. This happens because all upper right elements are really the mean of two different numbers, while the upper left elements are the mean of the same number.

-
You are very quick! :) – Oleksandr R. Jan 24 at 6:54
Sorry. Saw it and thought I need to clear this up as quick as possible so that no one believes it is a good way. – halirutan Jan 24 at 6:55
Thank you for pointing this out. – buzhidao Jan 24 at 7:04

This one prevents the distribution problems halirutan is talking about:

h[n_] :=
Module[{m},
m = RandomReal[{0, 10}, {n, n}];
m SparseArray[{i_, j_} /; i >= j -> 1, {n, n}] +
Transpose[m SparseArray[{i_, j_} /; i > j -> 1, {n, n}]] // Normal
]

h[5] // TableForm


Distribution is uniform now:

Histogram@Flatten@h[1000]


-
Sjoerd, rather than using SparseArray to obtain a lower vs. upper triangular matrix, I found that using LowerTriangularize and UpperTriangularize seems faster (and also more readable, at least to me). For instance, substituting UpperTriangularize[m] + LowerTriangularize[Transpose@m, -1] for your expression seems to give a roughly 100x speedup, at least on my system (v. 10.3). – MarcoB Jan 25 at 5:17
@marcob you're fully right and I should have remembered this. – Sjoerd C. de Vries Jan 25 at 21:11

One can use the Module to declare a local variable:

H[N_] := RandomReal[{0,10},{N,N}]
symH[N_]:=Module[{h=H[N]},(h+h\[Transpose])/2];
symH[4]//MatrixForm


This should work.

-
No one upvote this poor answer... It is very convenient if one don't cares about the distribution.... – buzhidao Jan 25 at 6:00