MathGroup Archive 2001

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

Search the Archive

RE: strange behavior

  • To: mathgroup at smc.vnet.net
  • Subject: [mg27196] RE: [mg27158] strange behavior
  • From: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.de>
  • Date: Fri, 9 Feb 2001 03:10:41 -0500 (EST)
  • Sender: owner-wri-mathgroup at wolfram.com

Please look below for my answer:

-----Original Message-----
From: Otto Linsuain [mailto:linsuain+ at andrew.cmu.edu]
To: mathgroup at smc.vnet.net
Subject: [mg27196] [mg27158] strange behavior



Hi all. I have a little problem using Thread and MapThread, and although
I have found a way around it, I am still unhappy with it being there in
the first place.

I have a function (call it myF ) that takes as arguments FOUR vectors of
equal length (doesn't matter what length) -by vector I mean a List of
numbers with the simplest structure possible {x1, x2, ..... xN}- and
gives out a number. The only operations involved in getting the number
are addition, subtraction, multiplication and division. So I do
convolutions of one list with another, and things like that (although I
don't use ListConvolve).

I want to map this function over a bunch of lists in the following way:

For argument #1 I always want the same list xList={x1, x2, .....xN}

For argument #2 I have the list: yList={{a1,a2,...aN}, {b1,b2,...bN}}
and I want to apply the function first to the x's as argument #1 with
the a's as argument #2, and then to the x's as argument #1, with the b's
as argument #2. So far so good, and only need to map over the second
argument.

For argument #3 I have many lists. More exactly, I have a list
consisting of two NxN matrices:

cList={  { {Ca11,Ca12, ...Ca1N},{Ca21,Ca22, ...Ca2N},...{CaN1,Ca12,
...CaNN} }, 
    { {Cb11,Cb12, ...Cb1N},{Cb21,Cb22, ...Cb2N},...{CbN1,Cb12, ...CbNN} }  }

similarly for argument #4

lList={  { {La11,La12, ...La1N},{La21,La22, ...La2N},...{LaN1,La12,
...LaNN} }, 
    { {Lb11,Lb12, ...Lb1N},{Lb21,Lb22, ...Lb2N},...{LbN1,Lb12, ...LbNN} }  }


when I use the a's for argument #2 I want to go through and use the
first row in the Ca's for argument #3, and the first row in the La's for
argument #4, then the second row of each, etc Notice that I don't want
all the combination between the cList and the lList. When I am done with
that I go to the b's for argument #2, then I want to use the first rows
of Cb and Lb for arguments #3 and #4, then their second rows, etc.

This is what I do:

MapThread[ myF[xList,#1,#2,#3]&, {yList, cList, lList} ] this uses first
the first Parts of yList, cList and lList, and then their second Parts.

This produces { myF[ xList, {a1,a2,....aN}, matrix of Ca's, matrix of
La's], myF[xlIst, {b1,b2,..bN}, matrix of Cb's, matrix of Lb's]}

So far so good. Now I just need to Thread over the last two arguments:

Map[ Thread[#, List,-2]&, MapThread[ myF[xList,#1,#2,#3]&, {yList,
cList, lList} ] ] This threads the function myF over those arguments
just the way I wanted AS LONG AS the function myF has not been defined.
The minute I define the function myF to do what I want it to do (to
combine the four vectors in a certain way and produce a number) it
threads in a different way. Namely it threads as if using the Transpose
of the lists cList and lList. One solution is to use the Transpose in
the first place, so when they get Transposed again it would be just
fine, but this is still puzzling. Any ideas on what is going on and
suggestions on how to fix it (Transposing big matrices is a little slow)
would be appreciated. Otto Linsuain.


----------------------------------------------------

Dear Otto,

My Mathematica Version here (still) is

In[1]:= {$Version, $ReleaseNumber}
Out[1]= {"4.0 for Microsoft Windows (April 21, 1999)", 0}

First of all let me define the test data

In[2] := xList = Array[x, {3}];
In[3] := yList = Array[#, {3}] & /@ {a, b};
In[4] := cList = Array[#, {3, 3}] & /@ {Ca, Cb};
In[5] := lList = Array[#, {3, 3}] & /@ {La, Lb};

A simple solution I found for your problem including Thread (there are
possible lots of them) is:

In[23] := 
  MapThread[Thread[myF[xList, #1, #2, #3], List, -2] &, {yList, cList,
lList}]

However it shares the problems of your solution.



The answer seems to be given be the observation

In[34]:= Attributes[Thread]
Out[34]= {Protected}

No Hold being part of that, so your function might evaluate prematurely
before Threading comes into effect. (You may observe that by carefully
looking at a trace of your evaluation!)

Anyways, you certainly may circumvent that problem if you do:

In[25]:=
With[{myF = Last[#2] &}, 
    MapThread[
      Thread[Hold[myF][xList, #1, #2, #3 ], List, -2] &, {yList, cList, 
        lList}]] // ReleaseHold
Out[25]=
{{a[3], a[3], a[3]}, {b[3], b[3], b[3]}}

In[26]:=
With[{myF = Last[#4] &}, 
    MapThread[
      Thread[Hold[myF][xList, #1, #2, #3 ], List, -2] &, {yList, cList, 
        lList}]] // ReleaseHold
Out[26]=
{{La[1, 3], La[2, 3], La[3, 3]}, {Lb[1, 3], Lb[2, 3], Lb[3, 3]}}

which in both cases I consider to be the right answer. (And your solution --
of course! -- gives the same.)


Mine also works well, when only temporaryly holding myF:

In[27]:=
With[{myF = Last[#2] &}, 
  MapThread[
    Thread[Unevaluated[myF[xList, #1, #2, #3 ]], List, -2] &, {yList, cList,

      lList}]] 
Out[27]=
{{a[3], a[3], a[3]}, {b[3], b[3], b[3]}}

In[28]:=
With[{myF = Last[#4] &}, 
  MapThread[
    Thread[Unevaluated[myF[xList, #1, #2, #3 ]], List, -2] &, {yList, cList,

      lList}]] 
Out[28]=
{{La[1, 3], La[2, 3], La[3, 3]}, {Lb[1, 3], Lb[2, 3], Lb[3, 3]}}


Since your solution involves Thread twice, you have to protect it with a
double shield:

In[32]:=
With[{myF = Last[#2] &}, 
  Map[Thread[#, List, -2] &, 
    MapThread[
      Function[Unevaluated[Unevaluated[myF[xList, #1, #2, #3]]]], {yList, 
        cList, lList}]]  ]
Out[32]=
{{a[3], a[3], a[3]}, {b[3], b[3], b[3]}}

In[34]:=
With[{myF = Last[#4] &}, 
  Map[Thread[#, List, -2] &, 
    MapThread[
      Function[Unevaluated[Unevaluated[myF[xList, #1, #2, #3]]]], {yList, 
        cList, lList}]]  ]
Out[34]=
{{La[1, 3], La[2, 3], La[3, 3]}, {Lb[1, 3], Lb[2, 3], Lb[3, 3]}}

Now, why do I only need the "single shield"? The reason is simple: the first
argument of MapThread is a (here a pure) function which evaluates to itself,
so it can be map-threaded, contrary to Thread whose argument is a function
application !!!

This reminds me at my first steps with Mathematica, where I discovered that
things which don't work with Thread, do so with MapThread. I think this is
the explanation.

-- Hartmut



  • Prev by Date: RE: Plotting Intersecting Planes
  • Next by Date: Re: strange behavior
  • Previous by thread: strange behavior
  • Next by thread: Re: strange behavior