MathGroup Archive 2000

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Re: Re: Set in Scan

  • To: mathgroup at smc.vnet.net
  • Subject: [mg22055] Re: [mg22008] Re: [mg21900] Re: [mg21856] Set in Scan
  • From: "Tomas Garza" <tgarza at mail.internet.com.mx>
  • Date: Fri, 11 Feb 2000 02:38:39 -0500 (EST)
  • Sender: owner-wri-mathgroup at wolfram.com

Dear Hartmut,

Thanks a lot for your painstakingly detailed explanation. It certainly was
very helpful in understanding what goes on inside Scan. 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...

I would be very grateful for any hint.

Tomas Garza
Mexico City
 -----------------------------------------------------------

> Tomas Garza schrieb:
> >
> > It looks as if the suggested approach of Hartmut Wolf's - as
> well as Jens
> > Peer Kuska's - to this problem works fine and is extremely efficient.
> > However, suppose that instead of having a few possibly very
> long lists {v1,
> > v2, v3} one has a large number N - perhaps of the order of tens of
> > thousands - of such lists, which need not be too long. The
> procedure would
> > have to be modified
>
> In fact! This is a different problem, and it's for this one indeed, that
> the second proposal I made -- as Allan Hayes did -- comes to full
> strength. Perhaps you might go back in this thread to Allan's answer, to
> see that the elements of the compound object, the lists v<i> even need
> not be of same length, *however* all v<i> must be long enough to at
> least include the replace position, else nothing will be replaced at
> all.
>
> To do the replacement only in those sublists being long enough would
> again consitute another problem.
>
> >                 ... in order to use some symbol like allv =
> {v1, v2,..., vN}
> > in Scan, instead of writing the complete list with all
> individual v's, as
> > used by Hartmut and Jens:
> >
> > Scan[Function[sym, sym[[3]] = "-XXX-", {HoldFirst}],
> >    Unevaluated[{v1, v2, v3}]]
> >
> > However, if I write
> >
> > Scan[Function[sym, sym[[3]] = "-XXX-", {HoldFirst}],
> >    Unevaluated[allv]]
> >
> > nothing happens.
>
> It can't, because Unevaluated reaches to Scan (i.e. to it's procedural
> machinery) the unevaluated symbol allv, and if you scan a symbol nothing
> happens. Scan doesn't even look at the Head of an expression, even be it
> Hold -- as Allan noticed -- instead it feeds on the elements, yet there
> are none in this case. It's only that
>
> OwnValues[allv]
>
> {HoldPattern[allv] :>
>        {{0.308624, 0.0113816, 0.452114, 0.100156},
>         {0.368705, 0.44588, 0.878839, 0.736246},
>         {0.71764, 0.18652, 0.667573, 0.338795}}}
>
> has such elements.
>
> >              ... And the second suggestion by Hartmut is
> unusable in case
> > 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-"]].
> >
>
> Well again this is not quite the same problem, but there is a natural
> extending solution:
>
> Scan[Function[sym,
>        sym[[3]] = If[sym[[3]] < 0.5, "-XXX-", "-YYY-"], {HoldFirst}],
>      Unevaluated[{v1, v2, v3}]]
>
>
> {v1, v2, v3}
>
> {{0.308624, 0.0113816, "-XXX-", 0.100156},
>  {0.368705, 0.44588, "-YYY-", 0.736246},
>  {0.71764, 0.18652, "-YYY-", 0.338795}}
>
> > Any suggestions?
> >
>
> More along the lines of this discussion you would like to try
>
> Scan[Function[sym,
>        (#[[3]] = If[#[[3]] < 0.5, "-XXX-", "-YYY-"])&@ Unevaluated[sym],
>        {HoldFirst}],
>      Unevaluated[{v1, v2, v3}]]
>
> Or the somewhat more obfuscated
>
> Scan[Evaluate,
>   Scan[((#[[3]] = If[#[[3]] < 0.5, "-XXX-", "-YYY-"])&
> @Unevaluated[#])&,
>     Unevaluated /@ Unevaluated[{v1, v2, v3}]]]
>
> no Hold attributes in. This even works when you replace the outer Scan
> (to get the replaced elements evaluated) by Map although the inner Scan
> doesn't return anything.
> I guess this is neither a bug nor any intended use (of Map), but a
> consequence of the requirement that repeated Scans should be possible.
> This example at least is an argument that they should!
>
>
> When had I looked for a solution to the problem posed originally by
> Johannes Ludsteck that ideom Unevaluated /@ Unevaluated[{v1,v1,v3}] came
> up to my mind shortly after I had sent off my reply
>
> Scan[(#[[3]] = -the new value-)&, Unevaluated /@ Unevaluated[{v1, v2,
> v3}]]
>
> ... only to then learn from Allan Hayes
>
> Scan[(#[[3]] = -the new value-)&, Unevaluated /@ Hold[v1, v2, v3]]
>
>
> At the time of my reply I had no time for measurement and guessed the
> time complexity to be O[constant].
>
> Now I did some comparitative measurements, each with a new kernel, so
> having the same memory and history conditions:
>
>
> ---------
> In[1]:= {v1, v2, v3} = Table[Random[], {3}, {1000000}];
> In[2]:=
> Scan[Function[sym, sym[[3]] = "-XXX-", {HoldFirst}],
>     Unevaluated[{v1, v2, v3}]] // Timing
> Out[2]=
> {1.071 Second, Null}
>
> In[3]:= Take[#, 4] & /@ {v1, v2, v3}
> Out[3]=
> {{0.675382, 0.55102, "-XXX-", 0.633244}, {0.422611, 0.715315, "-XXX-",
>     0.426188}, {0.011633, 0.223577, "-XXX-", 0.240954}}
>
> ---------
> In[1]:= {v1, v2, v3} = Table[Random[], {3}, {1000000}];
> In[2]:=
> Scan[Function[sym, sym[[3]] = "-YYY-"],
>     Unevaluated /@ Unevaluated[{v1, v2, v3}]] // Timing
> Out[2]=
> {1.062 Second, Null}
>
> In[3]:= Take[#, 4] & /@ {v1, v2, v3}
> Out[3]=
> {{0.974173, 0.96568, "-YYY-", 0.747727}, {0.910969, 0.312475, "-YYY-",
>     0.34289}, {0.729062, 0.611829, "-YYY-", 0.437515}}
>
> ---------
> In[1]:= {v1, v2, v3} = Table[Random[], {3}, {1000000}];
> In[2]:=
> Scan[(#[[3]] = "-ZZZ-") &, Unevaluated /@ Hold[v1, v2, v3]] // Timing
> Out[2]=
> {1.062 Second, Null}
> In[3]:=
> Take[#, 4] & /@ {v1, v2, v3}
> Out[3]=
> {{0.921074, 0.870566, "-ZZZ-", 0.553795}, {0.198232, 0.688503, "-ZZZ-",
>     0.372325}, {0.799497, 0.21537, "-ZZZ-", 0.0673068}}
>
> plus yet another variant
>
> In[1]:= Clear[f]; Attributes[f] = {HoldFirst};
> In[2]:= f[sym_] := (sym[[3]] = "-WWW-")
> In[3]:= {v1, v2, v3} = Table[Random[], {3}, {1000000}];
> In[4]:=
> Scan[f, Hold[v1, v2, v3]] // Timing
> Out[4]=
> {1.032 Second, Null}
> In[5]:=
> Take[#, 4] & /@ {v1, v2, v3}
> Out[5]=
> {{0.422896, 0.178604, "-WWW-", 0.193691}, {0.184583, 0.524976, "-WWW-",
>     0.370107}, {0.592243, 0.952171, "-WWW-", 0.79216}}
>
> All four perform the same and are O[x], when x is the length of the
> lists!
>
> I admit, I don't understand that. The Question is: what did we measure?
> The Performance of the functions? -- obviously not. The performance of
> Scan (through a list of three elements)? -- probably not. Seems just to
> be the time of accessing the 3rd element of a list. See
>
> In[1]:= {v1, v2, v3} = Table[Random[], {3}, {1000000}];
> In[2]:=
> {v1[[3]], v2[[3]], v3[[3]]} // Timing
> Out[2]=
> {0. Second, {0.969595, 0.192005, 0.637547}}
> In[3]:=
> {v1[[3]] = "-UUU-", v2[[3]] = "-UUU-", v3[[3]] = "-UUU-"} // Timing
> Out[3]=
> {1.052 Second, {"-UUU-", "-UUU-", "-UUU-"}}
>
> So it's Set[Part[...],...] which is not O[constant]



  • Prev by Date: Re: Re: Re: Set in Scan
  • Next by Date: Sorting
  • Previous by thread: Re: Re: Re: Set in Scan
  • Next by thread: Re: Re: Re: Set in Scan