Re: Re: Re: Set in Scan
- To: mathgroup at smc.vnet.net
- Subject: [mg22075] Re: [mg22008] Re: [mg21900] Re: [mg21856] Set in Scan
- From: Hartmut Wolf <hwolf at debis.com>
- Date: Sat, 12 Feb 2000 04:04:33 -0500 (EST)
- Organization: debis Systemhaus
- References: <000001bf73ea$4985a4e0$937227c8@default>
- Sender: owner-wri-mathgroup at wolfram.com
Tomas Garza schrieb: > > Dear Hartmut, > > ..... However, I'm still > at a loss concerning the problem of a very long list of fixed-size (not > necessarily too long, maybe less than 20) lists where the assignment may be > something which depends on the value of the element to be replaced, e.g., > Function[sym,If[sym[[3]] < 0.5, "-XXX-","-YYY-"]], so that it is not > possible to use > > allv[[All,3]] = k > > since here k would have to be the same for each element of allv. But I can't > use > > Scan[Function[sym, > (#[[3]] = If[#[[3]] < 0.5, "-XXX-", "-YYY-"])&@ Unevaluated[sym], > {HoldFirst}], > Unevaluated[{v1, v2, v3}]] > > or > > Scan[(#[[3]] = new) &, Unevaluated /@ Hold[v1, v2, v3]] > > as Allan Hayes suggests, since I would have to write explicitly the full > list {v1, v2,..., vN}, which is out of the question for very large N > (between 10,000 and 20,000). So far I have been using a ReplaceAll approach > which is unbelievably slow. I'm sure the Scan approach is much faster, > but... > Dear Tomas, ... some proposals how to deal with your problem. The best answer depends a little on how you get at your (many, relatively short) lists. Johannes Ludstecks problem originated from his wish to give his (not so many, yet long) lists *individual* names, but process them effectively together "in single strokes". For the methods proposed so far it was neccessary to write down explicit list, like {v1, v2, v3}, which had to be carefully dealt with as not to get the symbols unevaluated to the lhs of Set[Part[...],...] I now show how to extend these methods, in case your are not able (or simply down like) to write down the explicit List of the symbols. What we need is a bag, from which we can get at the unevaluated symbols at will, but have the bag itself evaluated. So what we need to do in first place, is to put the unevaluated symbols in that bag. That's the tricky point, but it can be done easily, if you first define your symbols, put them into the bag, and *then* give them values. Here is a model for that: allv = Table[Unique[v], {3}] {v$5, v$6, v$7} ...these are our symbols, as many as you like. You need not get at them through Unique, e.g. you could read in a table of names and make them to symbols. allvheld = Hold /@ allv {Hold[v$5], Hold[v$6], Hold[v$7]} ...this is the magic bag. All is save there, e.g. you may take it away for a walk. Do[ Evaluate[allv[[i]]] = Table[Random[], {4}], {i, 3}] ...here the symbols get there values, that's your program. We look at the values: allv {{0.166919, 0.200547, 0.974411, 0.131898}, {0.617234, 0.177582, 0.771096, 0.519545}, {0.639894, 0.347534, 0.957892, 0.124675}} ?allv "Global`allv" allv = {v$5, v$6, v$7} ...we see allv hasn't changed, yet we can't get at its components (the symbols) because of the recursive evaluation in _Mathematica_. ...for executing our compound assignment, we use our magic bag: Scan[(#[[3]] = gg[#[[3]]]) &, Apply[Unevaluated, allvheld, {1}] ] allv {{0.166919, 0.200547, gg[0.974411], 0.131898}, {0.617234, 0.177582, gg[0.771096], 0.519545}, {0.639894, 0.347534, gg[0.957892], 0.124675}} ...we applied a trick, to remove the Hold-s: Apply[Unevaluated, allvheld, {1}] {Unevaluated[v$5], Unevaluated[v$6], Unevaluated[v$7]} Of course you can also reach you goal with the held symbols -- I did it -- but it's more difficult and there is no point in doing that after we know this trick. Wrapping head Hold around the symbols in our bag is save, yet not strickly neccessary. You could also wrap with Unevaluated. Also you need not to know in advance the number of your symbols you would need, just generate enough (remark: of course, with some attention we may add further symbols later). Here a few snapshots: ... allvkept = Unevaluated /@ allv {Unevaluated[v$8], ..., Unevaluated[v$12]} Do[ Evaluate[allv[[i]]] = Table[Random[], {4}], {i, 3}] allv {{0.389824, ...}, ..., {..., 0.590491}, v$11, v$12} ...the last two symbols do not have values. Now the final Set: Off[Part::partd, Set::noval] Scan[(#[[3]] = hh[#[[3]]]) &, allvkept ] (* trompe l'oeil *) allv {{0.389824, 0.712106, hh[0.337913], 0.118311}, {0.442732, 0.883199, hh[0.0471863], 0.284335}, {0.821009, 0.347524, hh[0.062472], 0.590491}, v$11, v$12} On[Part::partd, Set::noval] However all this is not needed, when you don't reach for individual names for your lists, if you can hold all data together in a big list, i.e. your short lists are just elements of it. (You may have got at this through Map-ping, Table-ing, Array-ing, Append-ing, but not Do-ing.) allv = allv0 = Table[Random[], {3}, {4}] {{0.289622, 0.158518, 0.627899, 0.486945}, {0.727602, 0.394153, 0.58083, 0.564662}, {0.42659, 0.182415, 0.606131, 0.28117}} You had been frustrated with Set[allv[[All,...]],...]. Well, let's go back to the days of Version 3. There we had used instead allv[[Range[3], 3]] = k; allv {{0.289622, 0.158518, k, 0.486945}, {0.727602, 0.394153, k, 0.564662}, {0.42659, 0.182415, k, 0.28117}} ------ allv = allv0 Scan[(allv[[#, 3]] = kk) & , Range[3]] allv {{0.289622, 0.158518, kk, 0.486945}, {0.727602, 0.394153, kk, 0.564662}, {0.42659, 0.182415, kk, 0.28117}} ------ allv = allv0 Scan[(allv[[#, 3]] = gg[allv[[#, 3]]]) &, Range[3]] allv {{0.289622, 0.158518, gg[0.627899], 0.486945}, {0.727602, 0.394153, gg[0.58083], 0.564662}, {0.42659, 0.182415, gg[0.606131], 0.28117}} ------ allv = allv0 Do[allv[[i, 3]] = gg[allv[[i, 3]]], {i, 3}] allv {{0.289622, 0.158518, gg[0.627899], 0.486945}, {0.727602, 0.394153, gg[0.58083], 0.564662}, {0.42659, 0.182415, gg[0.606131], 0.28117}} Now for version 4: ------ allv = allv0 allv[[All, 3]] = k; allv {{0.289622, 0.158518, k, 0.486945}, {0.727602, 0.394153, k, 0.564662}, {0.42659, 0.182415, k, 0.28117}} ...this probably is not well known: allv[[All, 3]] = {1, 2, 3}; allv {{0.289622, 0.158518, 1, 0.486945}, {0.727602, 0.394153, 2, 0.564662}, {0.42659, 0.182415, 3, 0.28117}} allv[[All, 3]] = allv[[All, 3]]^2; allv {{0.289622, 0.158518, 1, 0.486945}, {0.727602, 0.394153, 4, 0.564662}, {0.42659, 0.182415, 9, 0.28117}} Now finally i did some Timing measurements. I measured t[[4, 1]] = (Scan[(allv[[#, 3]] = allv[[#, 3]]^2 + a) &, Range[8000]] // Timing)[[1, 1]] t[[4, 2]] = (Do[allv[[i, 3]] = allv[[i, 3]]^2 + b, {i, 8000}] // Timing)[[1, 1]] t[[4, 3]] = (allv[[All, 3]] = allv[[All, 3]]^2 + c; // Timing)[[1, 1]] ...and got for t {{2.123, 2.093, 0.06}, {8.012, 7.951, 0.12}, {32.536, 31.946, 0.26}, {132.26, 131.129, 0.501}, {0, 0, 0}} t[[1,...]] is for n=1000, 2 for 2000, 3 for 4000, 4 for 8000 (as seen above). What is remarkable is the phantastic Performance of Set[allv[All,...]],...] Do even is a little bit better than Scan, yet both are somewhat disappointing. I guess this is all due to single access times (added up). The observed complexity is t[[# + 1, All]]/t[[#, All]] & /@ {1, 2, 3} {{3.7739, 3.79885, 2.}, {4.06091, 4.01786, 2.16667}, {4.06504, 4.10471, 1.92692}} So Set[..[[All,..]],...] is seemingly linear O[n] (within the measured range), and Set[..[[n,..]],...] is seemingly quadratic O[n^2] What I learnt from this thread is: strive to use All in any case. (For Johannes Ludsteck, however it should not make enough a difference to abandon the advantage of descriptive access, i.e. through names of symbols.) Kind regards, Hartmut