MathGroup Archive 2004

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

Search the Archive

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