|
[Date Index]
[Thread Index]
[Author Index]
RE: Struggling with list element assignment in functions
- To: mathgroup at smc.vnet.net
- Subject: [mg45582] RE: [mg45568] Struggling with list element assignment in functions
- From: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.com>
- Date: Fri, 16 Jan 2004 06:04:58 -0500 (EST)
- Sender: owner-wri-mathgroup at wolfram.com
For aesthetics I have to make two short notes:
>-----Original Message-----
>From: Wolf, Hartmut
To: mathgroup at smc.vnet.net
>Sent: Wednesday, January 14, 2004 1:30 PM
>To: 'mt at 3planes.com'; mathgroup at smc.vnet.net
>Subject: [mg45582] RE: [mg45568] Struggling with list element assignment in
>functions
>
>
>
>>-----Original Message-----
>>From: mt at 3planes.com [mailto:mt at 3planes.com]
To: mathgroup at smc.vnet.net
>>Sent: Wednesday, January 14, 2004 7:26 AM
>>To: mathgroup at smc.vnet.net
>>Subject: [mg45582] [mg45568] Struggling with list element assignment in
>functions
>>
>>
>>For context, I am trying to create a toroidal data structure by
>>causing edges of an array to be copies of
>>rows and columns on the first interior line of the opposite edge.
>>
>>I'm not entirely clear on what Hold does, but it seemed to solve my
>>problem when wrapping the rows of the array:
>>
>>===
>>Attributes[haloarray] = HoldFirst;
>>haloarray[array_]/;MatrixQ[array] := Module[{},
>> If [Length[array] <4 || Length[array[[1]] ]< 4,
>> (Print["haloarray: matrix too
>>small"];Return[Null])];
>> Map[halo,array];
>> array[[1]] = array[[Length[array] - 1]];
>> array[[Length[array]]] = array[[2]];
>> ]
>>
>>Attributes[halo] = {};
>>halo[x_]/;MatchQ[x,z_List] := Module[{y},
>> y = x;
>> If [Length[x] <4,(Print["halo: list too
>>short"];Return[Null])];
>> y[[1]] = x[[(Length[x] - 1)]];
>> y[[Length[x]]] = x[[2]];
>> ]
>>===
>>so, by putting in the HoldFirst, I could assign directly to the called
>>array in haloarray[] rather than having to copy it twice, to and from
>>a dummy array. Imagine my disappointment, then, in trying to extend
>>this idea to the halo[] routine. This
>>===
>>Attributes[halo] = HoldFirst;
>>halo[x_]/;MatchQ[x,z_List] := Module[{},
>> If [Length[x] <4,(Print["halo: list too
>>short"];Return[Null])];
>> x[[1]] = x[[(Length[x] - 1)]];
>> x[[Length[x]]] = x[[2]];
>> ]
>>===
>>refuses to do the assignments and yields all sorts of error messages.
>>Any ideas? It's not a showstopper for me but I'd like to know what's
>>up.
>>
>>thanks
>>Michael Tobis
>>http://geosci.uchicago.edu/~tobis
>>
>
>Michael,
>
>perhaps you fell into the error -- so common (in any field) --
>namely of "optimizing before solving the problem".
>
>I assume, you originally wanted to _extend_ your (matrix) data
>periodically by margins to the left and to the right.
>
>Take the one-dimensional case
>
>In[26]:= rr = Range[5]
>Out[26]= {1, 2, 3, 4, 5}
>(our test data)
>
>then there is a function in Mathematica, that does it:
>
>In[28]:= PadRight[rr, 7, rr, 1]
>Out[28]= {5, 1, 2, 3, 4, 5, 1}
>
>
>This function also extends to the two-dimensional case. Let's
>again define a test sample:
>
>In[30]:= (tt = Array[CirclePlus, {5, 3}]) // MatrixForm
>
>(I suppress the output here, CirclePlus is only used for
>illustration and easy reading)
>Now look at
>
>In[32]:= PadRight[tt, {7, 5}, tt, {1, 1}] // MatrixForm
>
>I guess this is your solution.
>
>As PadRight is a built-in, there usually is no need (or
>opportunity) for further optimization.
>
>
>
>
>
>Now let me explain, what went wrong with your attempt. (I drop
>all embellishments here)
>
>In[33]:= Attributes[halo] = HoldAll;
>halo[x_] :=
> (x[[1]] = x[[(Length[x] - 1)]];
> x[[Length[x]]] = x[[2]];)
>
>In[35]:= rr = PadRight[Range[5], 7, 0, 1]
>Out[35]= {0, 1, 2, 3, 4, 5, 0}
>(our test data for this case)
>
>In[36]:= halo[rr]
>In[37]:= rr
>Out[37]= {5, 1, 2, 3, 4, 5, 1}
>
>Ok, halo worked!
>
>What we did, was replace the first and last element by the
>margins of the (true) data kernel. In order to achieve that
>in-place operation, it is necessary to pass the data by a
>symbol (rr here) and hold the argument.
>
>
>Now we try to repeat the trick for the next dimension:
>
>In[38]:=
>(tt0 = PadRight[Array[a, {5, 3}], {7, 5}, 0, {1, 1}]) // MatrixForm
>Out[38]//MatrixForm=
> 0 0 0 0 0
>
> 0 a[1, 1] a[1, 2] a[1, 3] 0
>
> 0 a[2, 1] a[2, 2] a[2, 3] 0
>
> 0 a[3, 1] a[3, 2] a[3, 3] 0
>
> 0 a[4, 1] a[4, 2] a[4, 3] 0
>
> 0 a[5, 1] a[5, 2] a[5, 3] 0
>
> 0 0 0 0 0
>
>
>What you proposed effectively was this:
>
>In[39]:=
>Attributes[haloarray] = HoldFirst;
>haloarray[array_] :=
> (Map[halo, array];
> array[[1]] = array[[Length[array] - 1]];
> array[[Length[array]]] = array[[2]];)
>
>(it doesn't work) The replacement of the rows is the same as
>what we did in the 1-dim case, and indeed, if we drop the line
>Map[halo,array] it works changing the rows.
>
>So we test
>
>In[46]:= Map[halo, tt0]
>
>(doesn't work) Why? Quite simple, Map cannot map halo over a
>symbol, such it has to evaluate its argument, hence we are
>lost (Input condition for halo is now violated).
>
>Normally we now would abandon the Map idea, but for
>illustration, how we can put it further:
>
>In[49]:= Clear[tt1, tt2, tt3, tt4, tt5, tt6, tt7]
>In[50]:=
>tt = Unevaluated /@ {tt1, tt2, tt3, tt4, tt5, tt6, tt7};
>
>We define tt as a list of Symbols. We wrapped them with
>Unevaluated, to stop evaluation of tt for Map.
>
>In[51]:=
>Thread[{tt1, tt2, tt3, tt4, tt5, tt6, tt7} = tt0]
Thread is not needed for Set; also avoid writing the list explicitly:
Evaluate[Evaluate /@ tt] = tt0
>
>This assigns our test data to tt. We cannot see them
>
>In[52]:= tt
>Out[52]=
>{Unevaluated[tt1], Unevaluated[tt2], Unevaluated[tt3],
>Unevaluated[tt4],
> Unevaluated[tt5], Unevaluated[tt6], Unevaluated[tt7]}
>
>As evaluation stops, but that is exactly what we need for
>haloarray. But it's really there, believe me:
>
>In[53]:= tt2
>Out[53]= {0, a[1, 1], a[1, 2], a[1, 3], 0}
>
>
>In[54]:= haloarray[tt]
>In[55]:= tt
>Out[55]=
>{Unevaluated[tt6], Unevaluated[tt2], Unevaluated[tt3],
>Unevaluated[tt4],
> Unevaluated[tt5], Unevaluated[tt6], Unevaluated[tt2]}
>
>look close what happend, the rows are right...
>
>...and also the columns
>
>In[57]:= tt2
>Out[57]=
>{a[1, 3], a[1, 1], a[1, 2], a[1, 3], a[1, 1]}
>
>
>To arrive at the desired result we just have to put away the
>wrappers, e.g. like this
>
>In[58]:= (tt = (Evaluate /@ tt)) // MatrixForm
>Out[58]//MatrixForm=
> a[5, 3] a[5, 1] a[5, 2] a[5, 3] a[5,1]
>
> a[1, 3] a[1, 1] a[1, 2] a[1, 3] a[1,1]
>
> a[2, 3] a[2, 1] a[2, 2] a[2, 3] a[2,1]
>
> a[3, 3] a[3, 1] a[3, 2] a[3, 3] a[3,1]
>
> a[4, 3] a[4, 1] a[4, 2] a[4, 3] a[4,1]
>
> a[5, 3] a[5, 1] a[5, 2] a[5, 3] a[5,1]
>
> a[1, 3] a[1, 1] a[1, 2] a[1, 3] a[1,1]
>
>
>
>But of course the right way to put forth your idea would be:
>
>In[81]:= Clear[haloarray]
>In[82]:=
>(tt0 = PadRight[Array[a, {5, 3}], {7, 5}, 0, {1, 1}]) // MatrixForm
>
>In[83]:=
>Attributes[haloarray] = HoldAll;
>haloarray[array_] := Module[{d1, d2},
> {d1, d2} = Dimensions[array];
> array[[All, 1]] = array[[All, d2 - 1]];
> array[[All, d2]] = array[[All, 2]];
> array[[1]] = array[[d1 - 1]];
> array[[d1]] = array[[2]];]
>
>In[85]:= haloarray[tt0]
>In[86]:= tt0
>
more elegant is this:
Attributes[haloarray] = HoldAll;
haloarray[array_] := (
array[[All, 1]] = array[[All, -2]];
array[[All, -1]] = array[[All, 2]];
array[[1]] = array[[-2]];
array[[-1]] = array[[2]];)
>
>
>Nonetheless I recommend PadRight.
>
Still do
--
Hartmut
Prev by Date:
RE: Struggling with list element assignment in functions
Next by Date:
Re: Struggling with list element assignment in functions
Previous by thread:
RE: Struggling with list element assignment in functions
Next by thread:
Re: Struggling with list element assignment in functions
|