Prev: need something like ReplaceAllIndexed[]
Next: Need larger window for Manipulate Slider Control (ControlsRendering)
From: Diamond, Mark on 19 Mar 2010 03:47 I am trying to construct a number of symmetric matrices with unit diagonal and random numbers in the off-diagonal entries. The matrices are of steadily increasing size. I have been constructing the matrices from random vectors with the correct number of off-diagonal entries, so that for a 3x3 matrix I have: symmetricMatrix[l_,3]:={{1,l[[1]],l[[2]]},{l[[1]],1,l[[3]]},{l[[2]],l[[3]],1}} symmetricMatrix[#,3]&/@RandomReal[{0,1},{10000,3}] or, for a 4x4 matrix symmetricMatrix[l_,6]:={{1,l[[1]],l[[2]],l[[4]]},{l[[1]],1,l[[3]],l[[5]]},{l[[2]],l[[3]],1,l[[6]]},{l[[4]],l[[5]],l[[6]],1}} symmetricMatrix[#,6]&/@RandomReal[{0,1},{10000,6}] The method works but writing the function symmetricMatrix by hand error-prone for large matrices. ... My first question is whether I have overlooked a much better (i.e., computationally faster) way of producing the matrices. Something which avoids all the calls to Part (e.g., l[[7]]) might be good. My second question relates not only to symmetric matrices but to a problem that I face frequently in other areas. Is there a way of constructing the symmetricMatrix function automatically? This is different from the question about a good way of constructing symmetric matrices. Here I am asking whether, given an appropriate matrix size, n, I can get Mathematica to create the static function in the form that I have written symmetricMatrix[3] and symmetricMatrix[6] ... so that, for example, if I enter makeStaticSymmetricMatrixFunctionForSize[3] and then enter ?makeSymmetricMatricFunction Mathematic will show me that there now exists a function like symmetricMatrix[l_,3]:={{1,l[[1]],l[[2]]},{l[[1]],1,l[[3]]},{l[[2]],l[[3]],1}} ?? I would appreciate any help or suggestions. Cheers, Mark Diamond
From: Ray Koopman on 19 Mar 2010 07:44 On Mar 19, 12:47 am, "Diamond, Mark" <d...(a)dot.dot> wrote: > I am trying to construct a number of symmetric matrices with unit > diagonal and random numbers in the off-diagonal entries. The matrices > are of steadily increasing size. I have been constructing the > matrices from random vectors with the correct number of off-diagonal > entries, so that for a 3x3 matrix I have: > > symmetricMatrix[L_,3] := (* I have changed lowercase "l" *) > {{1, L[[1]], L[[2]]}, (* to uppercase "L" throughout *) > {L[[1]], 1, L[[3]]}, (* to avoid confusing "l" and "1" *) > {L[[2]], L[[3]], 1}} > > symmetricMatrix[#,3]&/@RandomReal[{0,1},{10000,3}] > > or, for a 4x4 matrix > > symmetricMatrix[L_,6] := > {{1, L[[1]], L[[2]], L[[4]]}, > {L[[1]], 1, L[[3]], L[[5]]}, > {L[[2]], L[[3]], 1, L[[6]]}, > {L[[4]], L[[5]], L[[6]], 1}} > > symmetricMatrix[#,6]&/@RandomReal[{0,1},{10000,6}] > > The method works but writing the function symmetricMatrix by hand > error-prone for large matrices. ... > > My first question is whether I have overlooked a much better (i.e., > computationally faster) way of producing the matrices. Something > which avoids all the calls to Part (e.g., L[[7]]) might be good. > > My second question relates not only to symmetric matrices but to a > problem that I face frequently in other areas. Is there a way of > constructing the symmetricMatrix function automatically? This is > different from the question about a good way of constructing symmetric > matrices. Here I am asking whether, given an appropriate matrix size, > n, I can get Mathematica to create the static function in the form > that I have written symmetricMatrix[3] and symmetricMatrix[6] ... > so that, for example, if I enter > > makeStaticSymmetricMatrixFunctionForSize[3] > > and then enter > > ?makeSymmetricMatricFunction > > Mathematic will show me that there now exists a function like > > symmetricMatrix[L_,3] := > {{1, L[[1]], L[[2]]}, > {L[[1]], 1, L[[3]]}, > {L[[2]], L[[3]], 1}} > > ?? > > I would appreciate any help or suggestions. > > Cheers, > Mark Diamond First, the solution to a slightly different problem. Lix[i,j] = Lix[j,i] returns the linear index of row i, column j, in a symmetric matrix whose nonredundant elements are numbered as 1 2 3 4 5 6 7 8 9 10 etc. Lix[i_,j_] := #(#-1)/2 & @ Max[i,j] + Min[i,j] With[{n = 6}, Table[Lix[i,j],{i,n},{j,n}] ] {{ 1, 2, 4, 7, 11, 16}, { 2, 3, 5, 8, 12, 17}, { 4, 5, 6, 9, 13, 18}, { 7, 8, 9, 10, 14, 19}, {11, 12, 13, 14, 15, 20}, {16, 17, 18, 19, 20, 21}}] This will create a symmetric random matrix: With[{n = 4}, Table[#[[Lix[i,j]]],{i,n},{j,n}]& @ Table[ Random[Integer,9],{n(n+1)/2}] ] {{2, 7, 0, 9}, {7, 1, 0, 0}, {0, 0, 8, 5}, {9, 0, 5, 0}}] Now to your problem. The easiest solution is to insert the diagonals into the list of offidagonals. symat[L_,n_,d_] := Table[#[[Lix[i,j]]],{i,n},{j,n}]& @ Insert[L,d,Table[{i*i+i},{i,0,n-1}]/2+1] symat[Range(a)15, 6, 0] {{ 0, 1, 2, 4, 7, 11}, { 1, 0, 3, 5, 8, 12}, { 2, 3, 0, 6, 9, 13}, { 4, 5, 6, 0, 10, 14}, { 7, 8, 9, 10, 0, 15}, {11, 12, 13, 14, 15, 0}}
From: Diamond, Mark on 20 Mar 2010 03:46 Thank you Ray. Have you any thoughts about the second question? Cheers, Mark "Ray Koopman" <koopman(a)sfu.ca> wrote in message news:hnvo3m$egu$1(a)smc.vnet.net... > On Mar 19, 12:47 am, "Diamond, Mark" <d...(a)dot.dot> wrote: >> I am trying to construct a number of symmetric matrices with unit >> diagonal and random numbers in the off-diagonal entries. The matrices >> are of steadily increasing size. I have been constructing the >> matrices from random vectors with the correct number of off-diagonal >> entries, so that for a 3x3 matrix I have: >> >> symmetricMatrix[L_,3] := (* I have changed lowercase "l" *) >> {{1, L[[1]], L[[2]]}, (* to uppercase "L" throughout *) >> {L[[1]], 1, L[[3]]}, (* to avoid confusing "l" and "1" *) >> {L[[2]], L[[3]], 1}} >> >> symmetricMatrix[#,3]&/@RandomReal[{0,1},{10000,3}] >> >> or, for a 4x4 matrix >> >> symmetricMatrix[L_,6] := >> {{1, L[[1]], L[[2]], L[[4]]}, >> {L[[1]], 1, L[[3]], L[[5]]}, >> {L[[2]], L[[3]], 1, L[[6]]}, >> {L[[4]], L[[5]], L[[6]], 1}} >> >> symmetricMatrix[#,6]&/@RandomReal[{0,1},{10000,6}] >> >> The method works but writing the function symmetricMatrix by hand >> error-prone for large matrices. ... >> >> My first question is whether I have overlooked a much better (i.e., >> computationally faster) way of producing the matrices. Something >> which avoids all the calls to Part (e.g., L[[7]]) might be good. >> >> My second question relates not only to symmetric matrices but to a >> problem that I face frequently in other areas. Is there a way of >> constructing the symmetricMatrix function automatically? This is >> different from the question about a good way of constructing symmetric >> matrices. Here I am asking whether, given an appropriate matrix size, >> n, I can get Mathematica to create the static function in the form >> that I have written symmetricMatrix[3] and symmetricMatrix[6] ... >> so that, for example, if I enter >> >> makeStaticSymmetricMatrixFunctionForSize[3] >> >> and then enter >> >> ?makeSymmetricMatricFunction >> >> Mathematic will show me that there now exists a function like >> >> symmetricMatrix[L_,3] := >> {{1, L[[1]], L[[2]]}, >> {L[[1]], 1, L[[3]]}, >> {L[[2]], L[[3]], 1}} >> >> ?? >> >> I would appreciate any help or suggestions. >> >> Cheers, >> Mark Diamond > > First, the solution to a slightly different problem. > > Lix[i,j] = Lix[j,i] returns the linear index of row i, column j, > in a symmetric matrix whose nonredundant elements are numbered as > > 1 > 2 3 > 4 5 6 > 7 8 9 10 > etc. > > Lix[i_,j_] := #(#-1)/2 & @ Max[i,j] + Min[i,j] > > With[{n = 6}, Table[Lix[i,j],{i,n},{j,n}] ] > > {{ 1, 2, 4, 7, 11, 16}, > { 2, 3, 5, 8, 12, 17}, > { 4, 5, 6, 9, 13, 18}, > { 7, 8, 9, 10, 14, 19}, > {11, 12, 13, 14, 15, 20}, > {16, 17, 18, 19, 20, 21}}] > > This will create a symmetric random matrix: > > With[{n = 4}, Table[#[[Lix[i,j]]],{i,n},{j,n}]& @ > Table[ Random[Integer,9],{n(n+1)/2}] ] > > {{2, 7, 0, 9}, > {7, 1, 0, 0}, > {0, 0, 8, 5}, > {9, 0, 5, 0}}] > > Now to your problem. The easiest solution is to > insert the diagonals into the list of offidagonals. > > symat[L_,n_,d_] := Table[#[[Lix[i,j]]],{i,n},{j,n}]& @ > Insert[L,d,Table[{i*i+i},{i,0,n-1}]/2+1] > > symat[Range(a)15, 6, 0] > > {{ 0, 1, 2, 4, 7, 11}, > { 1, 0, 3, 5, 8, 12}, > { 2, 3, 0, 6, 9, 13}, > { 4, 5, 6, 0, 10, 14}, > { 7, 8, 9, 10, 0, 15}, > {11, 12, 13, 14, 15, 0}} >
From: Raffy on 22 Mar 2010 03:40 On Mar 20, 12:46 am, "Diamond, Mark" <d...(a)dot.dot> wrote: > Thank you Ray. > > Have you any thoughts about the second question? > > Cheers, > Mark > > "Ray Koopman" <koop...(a)sfu.ca> wrote in message > > news:hnvo3m$egu$1(a)smc.vnet.net... > > > > > On Mar 19, 12:47 am, "Diamond, Mark" <d...(a)dot.dot> wrote: > >> I am trying to construct a number of symmetric matrices with unit > >> diagonal and random numbers in the off-diagonal entries. The matrices > >> are of steadily increasing size. I have been constructing the > >> matrices from random vectors with the correct number of off-diagonal > >> entries, so that for a 3x3 matrix I have: > > >> symmetricMatrix[L_,3] := (* I have changed lowercase "l" *) > >> {{1, L[[1]], L[[2]]}, (* to uppercase "L" throughout = *) > >> {L[[1]], 1, L[[3]]}, (* to avoid confusing "l" and "1" *= ) > >> {L[[2]], L[[3]], 1}} > > >> symmetricMatrix[#,3]&/@RandomReal[{0,1},{10000,3}] > > >> or, for a 4x4 matrix > > >> symmetricMatrix[L_,6] := > >> {{1, L[[1]], L[[2]], L[[4]]}, > >> {L[[1]], 1, L[[3]], L[[5]]}, > >> {L[[2]], L[[3]], 1, L[[6]]}, > >> {L[[4]], L[[5]], L[[6]], 1}} > > >> symmetricMatrix[#,6]&/@RandomReal[{0,1},{10000,6}] > > >> The method works but writing the function symmetricMatrix by hand > >> error-prone for large matrices. ... > > >> My first question is whether I have overlooked a much better (i.e., > >> computationally faster) way of producing the matrices. Something > >> which avoids all the calls to Part (e.g., L[[7]]) might be good. > > >> My second question relates not only to symmetric matrices but to a > >> problem that I face frequently in other areas. Is there a way of > >> constructing the symmetricMatrix function automatically? This is > >> different from the question about a good way of constructing symmetric > >> matrices. Here I am asking whether, given an appropriate matrix size, > >> n, I can get Mathematica to create the static function in the form > >> that I have written symmetricMatrix[3] and symmetricMatrix[6] ... > >> so that, for example, if I enter > > >> makeStaticSymmetricMatrixFunctionForSize[3] > > >> and then enter > > >> ?makeSymmetricMatricFunction > > >> Mathematic will show me that there now exists a function like > > >> symmetricMatrix[L_,3] := > >> {{1, L[[1]], L[[2]]}, > >> {L[[1]], 1, L[[3]]}, > >> {L[[2]], L[[3]], 1}} > > >> ?? > > >> I would appreciate any help or suggestions. > > >> Cheers, > >> Mark Diamond > > > First, the solution to a slightly different problem. > > > Lix[i,j] = Lix[j,i] returns the linear index of row i, column j, > > in a symmetric matrix whose nonredundant elements are numbered as > > > 1 > > 2 3 > > 4 5 6 > > 7 8 9 10 > > etc. > > > Lix[i_,j_] := #(#-1)/2 & @ Max[i,j] + Min[i,j] > > > With[{n = 6}, Table[Lix[i,j],{i,n},{j,n}] ] > > > {{ 1, 2, 4, 7, 11, 16}, > > { 2, 3, 5, 8, 12, 17}, > > { 4, 5, 6, 9, 13, 18}, > > { 7, 8, 9, 10, 14, 19}, > > {11, 12, 13, 14, 15, 20}, > > {16, 17, 18, 19, 20, 21}}] > > > This will create a symmetric random matrix: > > > With[{n = 4}, Table[#[[Lix[i,j]]],{i,n},{j,n}]& @ > > Table[ Random[Integer,9],{n(n+1)/2}] ] > > > {{2, 7, 0, 9}, > > {7, 1, 0, 0}, > > {0, 0, 8, 5}, > > {9, 0, 5, 0}}] > > > Now to your problem. The easiest solution is to > > insert the diagonals into the list of offidagonals. > > > symat[L_,n_,d_] := Table[#[[Lix[i,j]]],{i,n},{j,n}]& @ > > Insert[L,d,Table[{i*i+i},{i,0,n-1}]= /2+1] > > > symat[Range(a)15, 6, 0] > > > {{ 0, 1, 2, 4, 7, 11}, > > { 1, 0, 3, 5, 8, 12}, > > { 2, 3, 0, 6, 9, 13}, > > { 4, 5, 6, 0, 10, 14}, > > { 7, 8, 9, 10, 0, 15}, > > {11, 12, 13, 14, 15, 0}} First Idea: ClearAll[symMat1]; symMat1[v_] := With[{n = (1 + Sqrt[1 + 8 Length[v]])/2}, With[{m = PadRight[ Table[Take[v, i*(i - 1)/2 + {1, i}], {i, 0, n - 1}], {n, n}, 0]}, m + Transpose[m] + IdentityMatrix[n]] /; IntegerQ[n]]; Improved Idea: ClearAll[symMat2]; symMat2[v_] := With[{n = (1 + Sqrt[1 + 8 Length[v]])/2}, SparseArray[ Reap[Fold[ Function[{i, w}, Do[With[{x = v[[i + j]]}, Sow[{1 + w, j} -> x]; Sow[{j, 1 + w} -> x]], {j, w}]; i + w], 0, Range[n - 1]]][[2, 1]], {n, n}, 1] /; IntegerQ[n]]; Function Generator: ClearAll[symMatFunc]; symMatFunc[n_Integer /; n > 0] := Module[{h}, Evaluate@ Normal(a)SparseArray[ Flatten(a)Rest@ Reap[Fold[ Function[{i, w}, Do[With[{x = h[#, i + j]}, Sow[{1 + w, j} -> x]; Sow[{j, 1 + w} -> x]], {j, w}]; i + w], 0, Range[n - 1]]], {n, n}, 1] & /. h -> Part]; symMatFunc[4] === { {1, #1[[1]], #1[[2]], #1[[4]]}, {#1[[1]], 1, #1[[3]], #1[[5]]}, {#1[[2]], #1[[3]], 1, #1[[6]]}, {#1[[4]], #1[[5]], #1[[6]], 1}} & I'm sure there are cleaner ways to do this, but I thought this method was kinda fun (using SparseArray for diagonal and Fold to generate the indices.)
From: Ray Koopman on 22 Mar 2010 03:41
On Mar 20, 12:46 am, "Diamond, Mark" <d...(a)dot.dot> wrote: > Thank you Ray. > > Have you any thoughts about the second question? > > Cheers, > Mark In[1]:= makesymat[n_] := ToExpression["symat[" <> ToString@n <> "] := Function[" <> ToString(a)Table[ Which[i > j, SequenceForm["#[[",(i-1)(i-2)/2 + j,"]]"], i < j, SequenceForm["#[[",(j-1)(j-2)/2 + i,"]]"], True, "1"], {i,n},{j,n}] <> "]" ] In[2]:= makesymat[4] In[3]:= ?symat Global`symat symat[4] := {{1, #1[[1]], #1[[2]], #1[[4]]}, {#1[[1]], 1, #1[[3]], #1[[5]]}, {#1[[2]], #1[[3]], 1, #1[[6]]}, {#1[[4]], #1[[5]], #1[[6]], 1}} & In[4]:= symat[4]@{a,b,c,d,e,f} Out[4]= {{1, a, b, d}, {a, 1, c, e}, {b, c, 1, f}, {d, e, f, 1}} |