# Dynamically filling matrix with a[[n,m]] = 1/a[[m,n]]

I'm building a square matrix, with 1s on the diagonal and elements in U the inverse of elements in L, which are random integers drawn from the sequence 1, ..., 9. Given the nature of the problem I need to solve, conceptually this does the trick perfectly.

size = 5; (*size of matrix*)
range = {1, 9}; (*the range of integers, min to max*)
init = RandomInteger[range, size]; (*builds the initial vector*)
matrix = Transpose[Table[init/init[[i]], {i, size}]];
(*constructs the matrix from the initial vector the way the problem requires*)


matrix is an "ideal" matrix, because in a second step a hypothetical user should be able to perturb it by modifying the elements in L, with elements in U changing accordingly; i.e., becoming the inverse matrix[[1,2]] = 1/matrix[[2,1]], and so on.

This is the best I have done so far to implement the dynamic behavior I want.

onscreen = SparseArray[{
{i_, i_} -> 1,
(*1s on the diagonal*)
{i_, j_} /; i - j >= 1 :> InputField[Dynamic[matrix[[i, j]]]],
(*InputFields to edit L part of matrix*)
{i_, j_} /; i - j <= 1 :> Dynamic[1/matrix[[j, i]]]
(*the U part of matrix - comment below*)
}, {size, size}]


I use onscreen as the means for the user to enter the desired values. Now he/she can edit the L part of matrix, and the U part of onscreen should reflect what is expected in matrix.

However values in U of matrix don't change. How can I make it happen?

I should remark that matrix will be needed for further calculations, so I can't populate it with Dynamic.

-
Try changing Dynamic[1/matrix[[j, i]] to Dynamic[matrix[[i, j]] = 1/matrix[[j, i]]]. – swish Apr 18 '13 at 14:56
Thank you for the corrections and the answer: it works!!! However I see CPU consumption going up to 30% until I quit the kernel. Not a big deal since the whole thing is for a school project, but weird nonetheless... – Marco Apr 18 '13 at 16:54

I think you can use something like this

n = 5;

UpdateM = ToExpression["m"<>ToString[#1]<>ToString[#2]<>"="<>ToString[m[[##]]]] &;
GetM = ToExpression["m"<>ToString[#1]<>ToString[#2]] &;

Table[Piecewise[{{Dynamic[GetM[##]] &[i, j], i > j},
{Dynamic[HoldForm@Divide[1, #] &@GetM[##]] &[j, i], i < j}}, 1],
{i, n}, {j, n}] // MatrixForm


After assigninig:

m = RandomInteger[{1, 9}, {n, n}];
Do[UpdateM[i, j], {i, n}, {j, i-1}];


Now, when you set the element

m[[2, 1]] = 7;
UpdateM[2, 1];


the output was updated. Not the whole matrix was updated but only (1,2) and (2,1) elements.

Moreover, you can add input fields and get editable version

CellPrint@ExpressionCell[#, Editable -> False] &@ MatrixForm@Table[Piecewise[
{{InputField[Dynamic[GetM[##],Function[{val}, m[[##]] = val; UpdateM[##]]],
Number,Appearance -> "Frameless", ImageSize -> 10] &[i, j], i > j},
{Dynamic[HoldForm@Divide[1, #] &@GetM[##]] &[j, i], i < j}}, 1], {i, n}, {j, n}]

-

This is a nice place to use the Outer product:

a = RandomInteger[{1, 10}, 5];
mat = Outer[Times, a, 1/a];
MatrixForm[mat]


A plausible way to do the dynamic portion is to use Manipulate:

changeMat[x_, y_, val_] := Module[{},
If[x != y, mat[[x, y]] = val; mat[[y, x]] = 1/val;]];
a = RandomInteger[{1, 10}, 5];
mat = Outer[Times, a, 1/a];
Manipulate[changeMat[x, y, val];
mat // MatrixForm, {x, 1, 5, 1}, {y, 1, 5, 1}, {val, 1, 10, 1}]


-

Maybe I'm missing the point, but why can't you define matrix to be an array of functions?

size = 5;
Clear[L,matrix];
matrix = Table[Which[
i > j, L[i,j],
i < j, 1/L[j,i],
True , 1], {i,size},{j,size}]];


Then define the functions.

range = {10, 99}
init = Table[Random[Integer,range],{size}]
(* {47, 55, 65, 66, 26} *)
Do[L[i,j] = init[[i]]/init[[j]], {i,2,size},{j,1,i-1}];


Referring to matrix invokes L.

matrix
(* {{1, 47/55, 47/65, 47/66, 47/26},
{55/47, 1, 11/13, 5/6, 55/26},
{65/47, 13/11, 1, 65/66, 5/2},
{66/47, 6/5, 66/65, 1, 33/13},
{26/47, 26/55, 2/5, 13/33, 1}} *)


Changes to L show up when you refer to matrix.

L[3,1] = x; L[4,2] = y; matrix
(* {{1, 47/55, 1/x, 47/66, 47/26},
{55/47, 1, 11/13, 1/y, 55/26},
{x, 13/11, 1, 65/66, 5/2},
{66/47, y, 66/65, 1, 33/13},
{26/47, 26/55, 2/5, 13/33, 1}} *)

-