Introduction to Mathematical Software

21-126, Spring 2000
Dr David Handron

Lesson 2

Mathematica's List[]s

Introduction

Lists in Mathematica are similar to arrays in other programming languages. While a list doesn't do anything, the variety of Mathematica commands that will operate on lists makes them one of the most important concepts in Mathematica.

Construction of List[]'s

Lists containing consecutive integers are made with Range[]

Range[5]

Range[7,20]

A third argument to Range[] specifies the step size.

Range[-5,15,2]

The Table[] command can be used to make more complicated lists

Table[Sin[i Pi/6], {i,0,6}]

Note the use of the short list {i,0,6} as the second argument to Table[]. Many Mathematica commands use short lists. A fourth element in the list gives the step size.

Clear[f] 
Table[3 f[i]^2, {i,0,8,2}]

New lists can be made from old by Join[]ing them together.

ll = Range[-3,9,3] 
mm = Table[i^3,{i,2,4}]

Join[ll,mm] 
Join[ll,mm,{a,b,c}]

Manipulating List[]'s

Mathematica has many commands for modifying lists.

ll = Range[10]

Reverse[ll]

First[] and Last[] get the first and last elements of a list, and Rest[] drops the first element from a list.

First[ll] 
Last[ll]

Rest[ll]

The commands Prepend[] and Append[] add list elements to the beginning or end of a list.

Prepend[ll, abc] 
Append[ll, abc]

Drop[] is used to remove certain elements from a list, and Take[] takes elements from a list to form a new list. These two commands have similar syntax. 
 
To Drop[] or Take[] the first four elements of a list use:

Drop[ll,4] 
Take[ll,4]

To Drop[] or Take[] the last four elements of a list use a minus sign.

Drop[ll,-4] 
Take[ll,-4]

Finally, to address the middle portion of a list use a range for the second argument

Drop[ll, {3,7}] 
Take[ll, {3,7}]

List[]'s as Sets.

Recall that a (mathematical) set does not include repetitions and is not ordered. For example, the set {a,b,b,c} is the same as the set {c,a,b}. While Mathematica's lists are enclosed in curly brackets, they do not behave like (mathematical) sets: repetitions and order are considered.

ll = {a,b,b,c} 
mm = {c,a,b}

Mathematica does have commands to manipulate lists like (mathematical) sets. The command to remove repetitions and to put a list in a standard order is Union[]

Union[ll] 
Union[mm]

The intersection of two sets (that is, lists representing sets) is computed with Intersection[]

ll 
mm 
Intersection[ll,mm]

The Complement[] command is like "subtracting" two sets. That is, it removes elements from one list contained in anther.

Complement[{a,b,c},{b,d,e}]

Selecting Elements from List[]s

Frequently we will want to form a sub-list by extracting distinguished elements for a given list. For example,we may want to find all the prime numbers in a list. The function Select[] is used for this purpose.

ll = Range[100]; 
Select[ll, PrimeQ]

Select[] will select elements from the list for which the function in the second argument returns a value of true. Mathematica provides many such functions, and later we will learn how to write such functions ourselves. Recall that functions ending in Q (for query) all return true or false:

?*Q

Functions and List[]s

Frequently we will want to map a function onto a list, for example, given a list of numbers we may want to form a new list by consisting of the cosines of the numbers in the original list. This may be done using the Map[] command.

ll = Table[i Pi/3, {i,0,6}]

Map[Cos,ll]

Since the type of operation is so common, may of Mathematica's functions will automatically map onto lists.

Cos[ll]

Functions that do this are called "Listable", and they have this as an attribute. Recall that the attributes of any function can be found using ??

??Cos

The Attributes[] function will return the list of attributes assigned to a function.

Attributes[Cos]

Most algebraic functions are listible. For example, the following squares each element of the list mm and then adds one to each element.

mm^2 + 1

Attributes[Power]
Attributes[Plus]

Incidently, Mathematica often returns lists of lists, like nn, and you may want to "flatten" them to form a single list containing the data. The Flatten[] command will do this.

nn = {{a,b,c},{1,2,3}}
Flatten[nn]

An Introduction to Expressions

(Almost) Everything is an Expression

General Expressions

To understand the operation of Mathematica it is useful to know how it represents all of the different things (such as plots, equations, lists etc.) internally. Unlike most languages that have a variety of data types (arrays, structs etc) Mathematica represents everything as an expression of the form

f[exp1, exp2, .... , expN]

Where exp1, exp2 etc. may be other expressions. 
 
As an example, consider the simple expression x+y. The Mathematica kernel represents this as Plus[x,y].

x+y 
FullForm[%]

When we enter x+y the front end converts it to Plus[x,y] and feeds it to the kernel. Since nothing is known about x or y this could not be simplified, so the kernel returned Plus[x,y], and the front end then wrote it out in the "pretty" form x + y. The function FullForm[] prints out the internal representation of its argument. 
 
The front end allows us to use many shortcuts such as typing x+y instead of Plus[x,y]; however, you may always enter the long form.

Plus[x,y] 
Plus[2,3]

As indicated above, expressions may contain expressions:

Plus[z,2,3,z,x,-1,y] 
FullForm[%]

Here the result has four arguments, one of them being Times[2,z] which represents 2z. Notice that Plus[] did some work this time, it added the numbers 2, 3, and -1 appearing as arguments and it took the two z's and represented them as 2z (a product) instead of z+z, and it was the final result (not the input) that we actually got the FullForm[] of. This brings up the very important topic of evaluation which we will discuss in more detail later.

Atoms

We said that almost everything is represented by an expression; let's look at an exception:

1+1 
FullForm[%]

Clearly the FullForm[] of an integer isn't of the form f[expr1,expr2,...]. Mathematica expressions are built from "atoms" which are the fundamental building blocks which are indivisible, and integers are one class of atoms.

AtomQ[2]

Dissecting Expressions

Head[]s

Frequently you will need to "get at" the bits and pieces of an expression. Recall from above that a generic expression is of the form

f[exp1, exp2, .... , expN]

The function Head[] will extract the head of the expression, i.e. the f in the above.

Head[ f[expr1,expr2] ]

FullForm[x+y] 
Head[x+y]

Head[2 z]

We mentioned above that integers like 2 are atoms, so are not represented as expressions. So a natural question is: What is the Head[] of an integer ?

Head[3]

For all practical purposes you can consider integers as expressions of the form Integer[3], but be warned that the following is garbage:

3 + Integer[2]

Similarly, numbers containing decimal points like 3.14159 can be thought of as expressions of the form Real[3.14159], but this is not how they are represented in Mathematica.

Head[3.14159]

Part[]s

To extract the other pieces of the expression we can use the Part[] function

Part[ f[expr1,expr2], 1] 
Part[ f[expr1,expr2], 2]

The front end supports a rather ugly abbreviation for Part[]:

f[expr1,expr2] [[1]] 
f[expr1,expr2] [[2]]

You may read the help file for Part[] to see how to get many parts of an expression all at once.

Modifying Expressions

Beheading Expressions

The Apply[] function allows you to change the head of an expression. As an example, we will change the expression f[expr1,expr2] to g[expr1,expr2]

Apply[g, f[expr1,expr2]]

More typical illustrations would be

Apply[Plus, f[expr1,expr2]] 
Apply[Times,f[expr1,expr2]]

Apply[] is often used with List[] expressions. List[]'s are the closest thing Mathematica has to arrays, and the front end prints List[expr1,expr2,...] as {expr1,expr2,...}.

ll = {1,7,-5,x} 
FullForm[ll]

As a typical example of Apply[], let us find the average value of the arguments of the list.

Apply[Plus,ll] / Length[ll]

The result of Apply[Plus,ll] is Plus[1,7,-5,x] which gets simplified to 3+x and we then divided by the length of ll which was 4.

Map[]ing the Sub-Expressions

While Apply[] changes the Head[] of an expression, the Map[] command is used to modify the sub-expressions of an expression by applying a function to each of them. A generic (but atypical) case would is:

Map[g, f[expr1,expr2]]

Notice  that each sub-expression got modified. The Map[] command is most commonly used to transform lists of data as in this next example.

ll = {1,2,3,4,5,6,7,8,9,10} 
Map[PrimeQ, ll]

This list now has True values where there were primes and False in the sites formally occupied by composite numbers.

Application to Least Squares Approximations

If we have N data points (xi, yi) and want to fit a line of the form y = a x + b through them, the best least squares approximation gives

a =  ((∑_□) xi yi - (1/N)  ∑xi  (∑_□) yi) /  (∑xi^2- (1/N) (∑xi)^2)

b =  ((∑_□) yi- a (∑_□) xi) / N

xx  =  Range[1, 5]yy  =  Table[0.5 Log[i],  {i, 1, 5}]

\(a\  = \ 
      \((Apply[Plus, xx\ yy]\  - \ Apply[Plus, xx]\ Apply[Plus, yy]\ /\ 5)
          \)\ /
\ \ \ 
        \((Apply[Plus, xx\ xx]\  - \ Apply[Plus, xx]\ Apply[Plus, xx]\ /\ 5)
          \)\)

b  =  (Apply[Plus, yy]  -  a Apply[Plus, xx]) / 5

Plot[{a*x  +  b,  0.5*Log[x]},  {x, 1, 5}]