Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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.

share|improve this question
    
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

3 Answers 3

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

matrix1

After assigninig:

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

matrix

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}]
share|improve this answer

This is a nice place to use the Outer product:

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

enter image description here

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}]

enter image description here

share|improve this answer

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}} *)
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.