2

I have some code inside a Manipulate, whose goal is to allow the user to edit the upper half of the matrix while keeping it symmetric at all time. The minimal code is the following:

Manipulate[
 Refresh[
    i = i + 1;
    Do[Cmat[[i, j]] = Cmat[[j, i]], {i, 2, 6}, {j, 1, i - 1}];
  , TrackedSymbols -> {Cmat}];
 {i, Grid[Array[InputField[Dynamic[Cmat[[#1, #2]]], FieldSize -> 5, Enabled -> #1 <= #2] &, {6, 6}]]}
 ,
 Initialization :> (
   i = 0;
   Cmat = ConstantArray[0, {6, 6}];
   )]

I added the i variable as a counter, and I expected it to be only incremented when I actually change the value of one of the Cmat elements. What actually happens is that i increases near the speed of the runloop, and that code actually hogs the CPU (one core of it, anyway). I suppose what happens is that the modification of the tracked value inside Refresh actually triggers Refresh itself, hence the loop.

How can I prevent this? I thought restricting TrackedSymbols to the upper half of Cmat would do the trick, but it changes nothing. Is there a way, inside of Refresh, to change Cmat without it being tracked? The opposition functionality exists, in the form of Update.

F'x
  • 10,817
  • 3
  • 52
  • 92

2 Answers2

4

Why Refresh? The second argument of Dynamic is your friend:

DynamicModule[
  {Cmat = ConstantArray[0, {6, 6}]}, 
 Deploy@Panel@Grid[Array[Function[{m, n}, 
      InputField[Dynamic[Cmat[[m,n]], 
        (Cmat[[m,n]] = #1; 
          Cmat[[n,m]] = #1) & ], 
       Number, FieldSize -> 5, 
       Enabled -> m <= n, 
       ContinuousAction -> True]], 
     {6, 6}]]]
Rolf Mertig
  • 17,172
  • 1
  • 45
  • 76
  • Yes, I can do it like that, I forgot about it… I like the Refresh construct, though, and I'd like even better to understand how to make it work. Any idea? – F'x Nov 12 '12 at 15:06
2

Why do you say Update has the opposite functionality? Perhaps what you want is something like this, changing your code minimally

Manipulate[Refresh[i = i + 1;
  Do[Cmat[[i, j]] = Cmat[[j, i]], {i, 2, 6}, {j, 1, i - 1}];, 
  None]; Cmat;
 {i, Grid[
   Array[InputField[Dynamic[Cmat[[#1, #2]]], FieldSize -> 5, 
      Enabled -> #1 <= #2] &, {6, 6}]]}, Initialization :> (i = 0;
   Cmat = ConstantArray[0, {6, 6}];)]
Rojo
  • 42,601
  • 7
  • 96
  • 188
  • Nope, doesn't work. If you switch focus out and back in the matrix, your counter starts to increment like crazy! – F'x Nov 12 '12 at 19:43
  • @F'x I'm trying to reproduce that but so far I couldn't! – Rojo Nov 12 '12 at 20:23
  • This works fine as long as I don't hit the [enter] key after entering a value (as one is tempted to do when entering digits from the numeric keypad). At least on my system, I get two copies of the panel and a runaway counter if I hit [enter] as opposed to [return]. – m_goldberg Nov 12 '12 at 20:46
  • @m_goldberg, I think that issue has it's own question already. You don't get that problem when hitting enter with the original solution? – Rojo Nov 12 '12 at 22:41
  • @Rojo: I didn't mean to imply that the problem was peculiar to your answer. It is more general -- it seems occur with most if not all dynamic output cells. Can you give me a link to where this has been discussed before? I'd be interested in reading that discussion. – m_goldberg Nov 13 '12 at 01:25
  • @m_goldberg probably this is what I had in mind – Rojo Nov 13 '12 at 01:39
  • @Rojo. I read the discussion you pointed me to. What Mr.Wizard experienced is similar and maybe the same as what I mentioned. – m_goldberg Nov 13 '12 at 02:16