6

I am interested in monitoring the progress of a computation using Dynamic. This can be done interactively as follows:

In[3]:= Dynamic[iter]

In[4]:= Table[{iter, iter^2}, {iter, 1, 500000}];

However, if the Table is within a function such as

f[m_] := Module[{iter}, Table[{iter, iter^2}, {iter, 1, m}]]; 

how can I keep track of the value of iter, when I execute the function via

f[500000];

?

asim
  • 389
  • 2
  • 10
  • `Table` already scopes `iter`, so in this case I don't see a need to include it in the first argument of `Module`. This might not apply in more complicated functions, in which case you might consider using `Block` instead of `Module`. – Brett Champion Jan 07 '12 at 22:52
  • @Brett It is a bit more subtle I think, although I can't come up with an example of constructive use of it in this given case. `Table` scopes dynamically, but it scopes not `iter` - it scopes an already `Module`-generated symbol like `iter$123` (can be seen e.g. with `Trace`). In the case of `Block`, there are constructive uses for combinations like `Module[{sym},Block[{sym},...]]`, for example as in this answer:http://stackoverflow.com/questions/7394113/defining-a-function-with-an-optional-value-that-is-by-default-a-function-of-anot/7394668#7394668 – Leonid Shifrin Jan 07 '12 at 23:01
  • @Leonid Yes, I know that in the code above the `iter` in the `Table` is really `iter$123`, which makes it tricky to refer to it from outside the `Module`. My point is that, in this particular case, including `iter` as a `Module` variable is unnecessary, and in fact makes things harder than they need to be. – Brett Champion Jan 07 '12 at 23:08
  • @Brett I agree. But I can think of a (somewhat contrived) example where `Module` can serve to protect the inner `iter` from name collisions possible with the dynamic scoping: define `ff[] := iter^3`, and then contrast this: `Block[{iter = 2}, Module[{iter}, Table[{iter, iter^2, ff[]}, {iter, 1, 5}]]]`, with this: `Block[{iter = 2}, Table[{iter, iter^2, ff[]}, {iter, 1, 5}]]`. Not that I meet this in my day to day work, though. – Leonid Shifrin Jan 07 '12 at 23:15

3 Answers3

4

Not sure it is a good advice, but:

f[m_] := 
Module[{iter}, getIter[] := iter; 
    Table[{iter, iter^2}, {iter, 1, m}]];

And then:

Dynamic[getIter[]]

f[500000];

EDIT

This will be better but somewhat more obscure:

ClearAll[f];
SetAttributes[f, HoldRest];
f[m_, monitorSymbol_: monitor] :=
   Block[{monitorSymbol},
     Module[{iter}, 
         monitorSymbol := iter; 
         Table[{iter, iter^2}, {iter, 1, m}]]
   ];

Here, you designate a certain symbol to monitor the state of your localized variable. By using Block, you ensure that your symbol does not obtain any global value at the end (more precisely, that its global value is not changed at the end - you may as well use a symbol that has some global value, if you so desire). The default symbol is monitor, but you can change it. Here is how you use it:

Dynamic[monitor]

f[500000];

This is a somewhat better suggestion than the first simpler one, since by using Block you guarantee that no global state modifications happen after the function finishes.

Leonid Shifrin
  • 22,449
  • 4
  • 68
  • 100
  • The following also works, f[m_] := Module[{iter}, getIter = iter; Table[{iter, iter^2}, {iter, 1, m}]]. Which one is preferable? – asim Jan 07 '12 at 22:39
  • @asim Between these two, it is largely a matter of style. I prefer the one with `getIter[]`, but this is just a personal preference. But see my edit for what I think is a generally better solution. – Leonid Shifrin Jan 07 '12 at 22:44
  • Thanks! That looks sophisticated. – asim Jan 07 '12 at 22:44
  • @asim This allows you to specify the name of the monitoring symbol, as a second parameter of your function's call, plus guarantees the absence of global side-effects, as explained in the answer. – Leonid Shifrin Jan 07 '12 at 22:46
2

If you want to use ProgressIndicator, you can do something like this:

(*version 1.0*)
Manipulate[

 msg = "busy...";
 result = process[Unevaluated@progressCounter, max];
 msg = "done!";
 result,


 Dynamic@Grid[{
    {ProgressIndicator[progressCounter, {0, 100}, 
      ImageSize -> {105, 23}, ImageMargins -> 0, 
      BaselinePosition -> Bottom],
     Spacer[5],
     progressCounter, " %"},
    {msg}
    }
   ],


 {{max, 100, "maximum"}, 10, 10000, 10, Appearance -> "Labeled", 
  ContinuousAction -> False},

 {{progressCounter, 0}, None},
 {{result, 0}, None},
 SynchronousUpdating -> False,
 TrackedSymbols :> {max},

 Initialization :>
  (

   process[c_, max_] := Module[{i, tbl},
     c = 0.;
     tbl = Table[0, {max}];

     Do[
      tbl[[i]] = {i, i^2};
      Pause[0.00001];
      c = i/max*100.,
      {i, 1, max}
      ];
     c = 0.;
     tbl[[-1]]
     ]
   )
 ]

enter image description here

Nasser
  • 12,849
  • 6
  • 52
  • 104
2

To monitor an expression you could try using Monitor:

Monitor[
 t = Table[{i, i^2}, {i, 500000}];
 Last[t]
 ,
 i
]

Additionally you can use ProgressIndicator with the range on i:

Monitor[
 t = Table[{i, i^2}, {i, 500000}];
 Last[t]
 ,
 ProgressIndicator[i, {1, 500000}]
]
Arnoud Buzing
  • 15,383
  • 3
  • 20
  • 50