• Aucun résultat trouvé

% Length nums

4.2 Functions for manipulating expressions

Three of the most powerful and commonly used functions by experienced Mathematica programmers are Map, Apply, and Thread. They provide very sophisticated ways of manipulating expressions in Mathematica. Becoming familiar with them is essential to functional programming in Mathematica. In this section we will discuss their syntax and look at some simple examples of their use. We will also briefly look at some related func-tions (Inner andOuter), which will prove useful in manipulating the structure of your expressions. These higher-order functions will be used throughout the rest of this book.

Map

Map applies a function to each element in a list.

In[1]:= Map Head, 3, 22

7 ,

Out[1]= Integer, Rational, Symbol

This is illustrated using an undefined function f and a simple linear list.

In[2]:= Map f, a, b, c

Out[2]= f a , f b , f c

More generally, mapping a function f over the expression g[a,b,c] essentially wraps the function f around each of theelements of g.

In[3]:= Map f, g a, b, c

Out[3]= g f a , f b , f c

So this general computation is identical toMap[f,{a,b,c}], except in that exampleg is replaced withList (remember thatFullForm[{a,b,c}] is List[a,b,c]).

The real power of the Map function is that you can map any function across any expression for which that function makes sense. Using theReverse function withMap, you can reverse the order of elements in each list of a nested list.

In[4]:= Map Reverse, a, b , c, d , e, f

Out[4]= b, a , d, c , f, e

The elements in each of the inner lists in a nested list can be sorted.

In[5]:= Map Sort, 2, 6, 3, 5 , 7, 4, 1, 3

Out[5]= 2, 3, 5, 6 , 1, 3, 4, 7

Often, you will need to define your own function to perform some computation on every element of a list. This is the sort of computation thatMap is expressly designed for.

Here is a list of three elements.

In[6]:= vec 2, , ;

If we wished to square each element and add 1, we could first define a function that per-forms this computation on its arguments.

In[7]:= f x_ : x2 1

Mapping this function overvec, will then wrapf around each element and evaluatef of those elements.

In[8]:= Map f, vec

Out[8]= 5, 1 2, 1 2

Later in this chapter we will look at even simpler ways of performing such computations.

Thread and MapThread

The Thread function exchanges operations with arguments that are lists.

In[9]:= Thread g a, b, c , x, y, z

Out[9]= g a, x , g b, y , g c, z

You can accomplish something quite similar with MapThread. It differs from Thread in that it takes two arguments – the function that you are mapping and a list of two (or more) lists as arguments of the function. It creates a new list in which the corre-sponding elements of the old lists are paired (or zipped together).

In[10]:= MapThread g, a, b, c , x, y, z

Out[10]= g a, x , g b, y , g c, z

With Thread, you can fundamentally change the structure of the expressions you are working with. For example, this threads theEqual function over the two lists given as its arguments.

In[11]:= Thread Equal a, b, c , x, y, z

Out[11]= a x, b y, c z

In[12]:= Map FullForm, %

Out[12]= Equal a, x , Equal b, y , Equal c, z

Here is another example of the use ofThread. We start off with a list of variables and a list of values.

In[13]:= vars x1, x2, x3, x4, x5 ;

In[14]:= values 1.2, 2.5, 5.7, 8.21, 6.66 ;

From these two lists, we create a list of rules.

In[15]:= Thread Rule vars, values

Out[15]= x1 1.2, x2 2.5, x3 5.7, x4 8.21, x5 6.66

Notice how we started with arule of lists andThread produced alist of rules. In this way, you might think of Thread as a generalization of Transpose.

Here are a few more examples ofMapThread. This raises each element in the first list to the power given by the corresponding element in the second list.

In[16]:= MapThread Power, 2, 6, 3 , 5, 1, 2

Out[16]= 32, 6, 9

UsingTrace, you can view some of the intermediate steps thatMathematica performs in doing this calculation.

In[17]:= MapThread Power, 2, 6, 3 , 5, 1, 2 Trace

Out[17]= MapThread Power, 2, 6, 3 , 5, 1, 2 ,

25, 61, 32 , 25, 32 , 61, 6 , 32, 9 , 32, 6, 9

Using theList function, the corresponding elements in the three lists are placed in a list structure (note thatTranspose would do the same thing).

In[18]:= MapThread List, 5, 3, 2 , 6, 4, 9 , 4, 1, 4

Out[18]= 5, 6, 4 , 3, 4, 1 , 2, 9, 4

The Listable attribute

Many of the built-in functions that take a single argument have the property that, when a list is the argument, the function is automatically applied to all of the elements in the list.

In other words, these functions are automatically mapped on to the elements of the list.

For example, theLog function has this attribute.

In[19]:= Log a, E, 1

Out[19]= Log a , 1, 0

This is the same result you get using theMap function.

In[20]:= Map Log, a, E, 1

Out[20]= Log a , 1, 0

Many of the built-in functions that take two or more arguments have the property that, when multiple lists are the arguments, the function is automatically applied to all of the corresponding elements in the list. In other words, these functions are automatically threaded on to the elements of the list.

In[21]:= 4, 6, 3 5, 1, 2

Out[21]= 9, 7, 5

This gives the same result as using thePlus function withMapThread.

In[22]:= MapThread Plus, 4, 6, 3 , 5, 1, 2

Out[22]= 9, 7, 5

Functions that are either automatically mapped or threaded on to the elements of list arguments are said to be Listable. Many ofMathematica’s built-in functions have this Attribute.

In[23]:= Attributes Log

Out[23]= Listable, NumericFunction, Protected

In[24]:= Attributes Plus

Out[24]= Flat, Listable, NumericFunction,

OneIdentity, Orderless, Protected

By default, functions that you define do not have any attributes associated with them. So, for example, if you define a function g, say, it will not automatically be threaded over a list.

In[25]:= g a, b , c, d

Out[25]= g a, b , c, d

If you want your function to have the ability to thread over lists, give it the Listable attribute using SetAttributes.

In[26]:= SetAttributes g, Listable

In[27]:= g a, b , c, d

Out[27]= g a , g b , g c , g d

Note that clearing a symbol only clears values associated with that symbol. It does not clear any attributes associated with the symbol.

In[28]:= Clear g

In[29]:= ? g Global`g

Attributes g Listable

To clear attributes, you need to useRemove.

In[30]:= Remove g

Now there is no remaining information associated withg.

In[31]:= ? g

Information::notfound : Symbol g not found. More…

Apply

Whereas Map is used to perform the same operation on each element of an expression, Apply is used to change the structure of an expression.

In[32]:= Apply h, g a, b, c

Out[32]= h a, b, c

The functionh was applied to the expressiong[a,b,c] andApply replaced the head of g[a,b,c] withh.

If the second argument is a list, applying h to that expression simply replaces its head (List) withh.

In[33]:= Apply h, a, b, c

Out[33]= h a, b, c

The following computation shows the same thing, except we are using the internal represen tation of the list{a,b,c} here to better see how the structure is changed.

In[34]:= Apply h, List a, b, c

Out[34]= h a, b, c

We see that the elements of List are now the arguments of h. Essentially, you should think of Apply[h,expr] as replacing the head of expr withh.

In[35]:= Apply Plus, 1, 2, 3, 4

Out[35]= 10

Here,List[1,2,3,4] has been changed to Plus[1,2,3,4] or, in other words, the head List has been replaced by Plus.

Plus[a,b,c,d] is the internal representation of the sum of these four symbols that you would normally writea+b+c+d.

In[36]:= Plus a, b, c, d

Out[36]= a b c d

This list conversion can be applied to an entire list.

In[37]:= Apply h, 1, 2, 3 , 5, 6, 7

Out[37]= h 1, 2, 3 , 5, 6, 7

This is just vector addition.

In[38]:= Apply Plus, 1, 2, 3 , 5, 6, 7

Out[38]= 6, 8, 10

One important distinction between Map and Apply that you should be aware of concerns the level of the expression at which each operate. By default, Map operates at level 1. That is, inMap[h,expr], h will be applied to each element at the top level ofexpr.

So, for example, ifexpr consists of a nested list,h will be applied to each of the sublists, but not deeper, by default.

In[39]:= Map h, a, b , c, d

Out[39]= h a, b , h c, d

If you wish to apply h at a deeper level, then you have to specify that explicitly using a third argument toMap.

In[40]:= Map h, a, b , c, d , 2

Out[40]= h a , h b , h c , h d

Apply, on the other hand, operates at level 0. That is, inApply[h,expr], Apply looks at the part 0 of expr (that is, its Head) and replaces it withh.

In[41]:= Apply f, a, b , c, d

Out[41]= f a, b , c, d

Again, if you wish to applyh at a different level, then you have to specify that explic-itly using a third argument to Apply.

In[42]:= Apply h, a, b , c, d , 1

Out[42]= h a, b , h c, d

For example, to applyPlus to each of the inner lists, you need to specify thatApply will operate at level 1.

In[43]:= Apply Plus, 1, 2, 3 , 5, 6, 7 , 1

Out[43]= 6, 18

If you are a little unsure of what has just happened, consider the following example and, instead of h, think of Plus.

In[44]:= Apply h, 1, 2, 3 , 5, 6, 7 , 1

Out[44]= h 1, 2, 3 , h 5, 6, 7

Inner and Outer

The Outer function applies a function to all of the combinations of the elements in several lists. This is a generalization of the mathematicalouter product.

In[45]:= Outer f, a, b , 2, 3, 4

Out[45]= f a, 2 , f a, 3 , f a, 4 , f b, 2 , f b, 3 , f b, 4

Using theList function as an argument, you can create lists of ordered pairs that com-bine the elements of several lists.

In[46]:= Outer List, a, b , 2, 3, 4

Out[46]= a, 2 , a, 3 , a, 4 , b, 2 , b, 3 , b, 4

Using Inner, you can thread a function on to several lists and then use the result as the argument to another function.

In[47]:= Inner f, a, b, c , d, e, f , g

Out[47]= g f a, d , f b, e , f c, f

This function lets you carry out some interesting operations.

In[48]:= Inner Times, x1, y1, z1 , x2, y2, z2 , Plus

Out[48]= x1x2 y1y2 z1z2

In[49]:= Inner List, a, b, c , d, e, f , Plus

Out[49]= a b c, d e f

Looking at these two examples, you can see that Inner is really a generalization of the mathematical dot product.

In[50]:= Dot x1, y1, z1 , x2, y2, z2

Out[50]= x1x2 y1y2 z1z2

Exercises

1. Write a function addPair[{x,y}] that adds the elements in a pair. Then use your addPair function to sum each pair from the following.

data 1, 2 , 2, 3 , 3, 4 , 4, 5 , 5, 6 ; Your output should look like{3,5,7,9,11}.

2. UseApply to add the elements in each pair from a list of pairs of numbers such as in the previous exercise.

3. A matrix can be rotated by performing a number of successive operations. Rotate the matrix {{1,2,3},{4,5,6}} clockwise by 90 degrees, obtaining

{{4,1},{5,2},{6,3}}, in two steps. UseTableForm to display the results.

4. While matrices can easily be added using Plus, matrix multiplication is more complicated. TheDot function, written as a single period, can be used.

In[1]:= 1, 2 , 3, 4 . x, y

Out[1]= x 2 y, 3 x 4 y

Perform matrix multiplication on{{1,2},{3,4}} and{x,y} without using Dot.

(This can be done in two or three steps.)

5. FactorInteger[n] returns a nested list of prime factors and their exponents for the numbern.

In[2]:= FactorInteger 3628800

Out[2]= 2, 8 , 3, 4 , 5, 2 , 7, 1

UseApply to reconstruct the number from this nested list.

6. Repeat the above exercise but instead use Inner to construct the original numbern from the factorization given by FactorInteger[n].

7. Using Inner, write a function div[vecs,vars] that computes the divergence of an n-dimensional vector fieldvecs e1,e2, …,en dependent uponn variables

vars v1,v2, …,vn. The divergence is given by the sum of the pairwise partial