Services & Resources / Wolfram Forums
-----
 /
MathGroup Archive
2004
*January
*February
*March
*April
*May
*June
*July
*August
*September
*October
*November
*December
*Archive Index
*Ask about this page
*Print this page
*Give us feedback
*Sign up for the Wolfram Insider

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: [mg45581] 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:57 -0500 (EST)
  • Sender: owner-wri-mathgroup at wolfram.com

>-----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: [mg45581] [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
evaluattion of tt for Map.

In[51]:=
Thread[{tt1, tt2, tt3, tt4, tt5, tt6, tt7} = 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



Nonetheless I recommend PadRight.

--
Hartmut Wolf


  • Prev by Date: Creating Evaluation Palettes
  • 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