Towards Programming in Mathematica

Comp110 Course Module 2

Having seen some of the basics of Mathematica, our goal in this module is to start to learn how to program in Mathematica.  Perhaps the best way to think of Mathematica is as an extremely powerful calculator.  You, the user, type in an expression and Mathematica then evaluates that expression and returns an answer.  For simple problems, these expressions will only involve functions that are built into Mathematica.  For more complex problems, one typically defines new functions in terms of existing functions that are then used in more complex expressions.   In the following module, we explore this process in more detail.

Arithmetic Expressions

To begin, let's briefly review some basic material from Module 1.  Arithmetic expressions in Mathematica are built using numbers such as  2, -1, 0.003 and operations such as addition +, subtraction -, multiplication * and division /. These expression can be entered in standard mathematical form such as

1+2+3
(5.0/7.5)
(Sqrt[2.2-0.9])

One point of interest that will be become more relevant later in the class is that all Mathematica expression are represented in the form foo[a,b, …, c] where foo is a function and a,b,c are themselves expressions.  For example, the previous three expressions written in "standard" form are

Plus[1,2,3]
Divide[5.0,7.5]
Sqrt[Subtract[2.2,0.9]]

In fact, all expressions in Mathematica are represented internally in the Standard form foo[a,b,…,c].  However, for ease of use, Mathematica also supports writing expressions in Traditional form

Problem:

In general, Mathematica has almost every mathematical function that you can imagine already available.  Your goal in this class is not to learn how to program, but rather how to solve problems.  Instead of focusing on writing Mathematica code for standard functions from scratch, your goal should be to become a wizard with the Documentation Center.   Never attempt to write your own definition of a simple function without first checking the Documentation Center for whether Mathematica has the function built-in.

Variables and assignment

The last two expressions included symbols such as π, e and i.  In Mathematica (and other programming languages), the symbols e, i and π are placeholders that stand for well-known constants.  For example,  π is the ratio of a circle's circumference to its diameter, e stands for the base of the natural logarithm, and i stands for (Sqrt[-1]).  Another important placeholder is ∞, which stands for the positive end of the number scale.

Mathematica users can also define their own placeholders for important values.  These placeholders are known as variables and by convention always start with a lowercase letter to distinguish them from Mathematica's built-in constants.  Variables are given their values via the assignment operator =.  For example, one can define two variables r and myπ

r =10
myπ = 4π

Now the surface area of a sphere with radius r is 4π (r^2).

area = myπ (r^2)

One common practice of novice programmers is to redefine the value of a variable by performing multiple assignments to the variable.   For example, we could redefine the value of r and area using =.

r=20

area=myπ (r^2)

While this practice can be useful for complex problems, it is best avoided by novice programmers, since redefining a variable forces the programmer to remember the current value of the variable.  For now, we will write functional programs in Mathematica in which a variable is assigned a value only once.  Following this convention ensures that the value associated with a variable stays unchanged during a Mathematica computation.

One of the most powerful capabilities of Mathematica is that Mathematica can simplify expressions containing undefined variables. This method of computing is known as symbolic computation.  For example you can ask Mathematica to evaluate 3a+5a.  Although the value of the variable a is unknown, Mathematica is still able to answer that 3a+5a is 8a.

3a+5a

This feature distinguishes Mathematica from many other languages such as Basic, C, Pascal, .... which require all variables to have known values.

Problem:

Conditional expressions

Boolean expressions

Not all mathematical functions can be written as arithmetic expressions based on the operators +, - and so on.  Sometimes it is necessary to test for different cases inside an expression.   In particular, we can direct the evaluation of an expression depending on whether a Boolean value is either True or False.  (True and False are Mathematica built-in constants.)  We can build up expressions that return Boolean values using the relational operators ==, ≤, <, >, ≥ and ≠.  For example the expression a==b will evaluate to True if both variables a and b have defined values that are the same. This expression evaluates to False if a and b have values that differ.  Finally, if the variables a and b are undefined, then Mathematica will return the expression a==b denoting that this expression cannot be simplified further.

Problem:

If expressions

We just saw how we can test certain equality and inequality conditions.  Later we will learn more about built-in functions whose names end in the capital letter Q that can be used to test more complex conditions.  Inside Mathematica expressions we can direct the evaluation depending on a condition using the If-expression. This expression has the form If[b,ex1,ex2].  An If expression is evaluated as follows:  First, Mathematica evaluates the expression b.  If the value of b is True, the value of the whole If-expression is the value of ex1.  If the value of b is False,  the value of the If-expression is the value of ex2.  Otherwise, the value of the If-expression is the expression itself.   An example of when the third case occurs is when b contains undefined variables.  For example,

If[z==z,1,2]
If[z≠z,1,2]
If[z,1,2]

Problem

Defining New Mathematica Functions

We already saw how we can use functions to compute complicated values inside Mathematica. For example, using Product to compute the product of a sequence of numbers was much easier than typing in the entire sequence by hand.  We can also define our own functions in Mathematica and then use these new functions to compute more complicated expressions.  To reemphasize: in working with functions, there are two distinct steps: function definition and function evaluation.

In the previous problem, we created an expression that computed the absolute value of a variable y.  We could define a new function myAbs that takes a single parameter y and computes the absolute value of y.  (Of course, in practice, we would just use the built-in Mathematica function Abs.)  By convention, user-defined functions in Mathematica always have names that begin with lower case letters.  This convention distinguishes user-defined functions from built-in functions.

myAbs[y_]:=If[y<0,-y,y]

The underscore _ after the variable y tells Mathematica that y_ is a pattern (i.e. y is an parameter for the function).  In Mathematica, patterns are used to give names to parts of an expression that have a particular structure.  Anytime that Mathematica subsequently encounters an expression of the form myAbs[…], Mathematica will evaluate the … expression and assign its value temporarily to the variable y.  Then, myAbs will evaluate the right-hand side of its definition (If[y < 0, -y, y]) using this temporary value for y and return this value as its answer.

We can now evaluate myAbs using various expressions as input,

myAbs[1+1]
myAbs[0*1]
myAbs[-1-1]

To repeat,  the definition of myAbs causes evaluation of subsequent instances of the expression myAbs[…] (such as the three above) in the following manner:  First, the argument … to myAbs is evaluated.  Next, the value of this expression is assigned to the temporary variable y.  Finally, the value of the expression If[y<0,-y,y] is returned as the value of myAbs[…].

Creating functions in Mathematica is your first real step towards programming.  To reduce the number of errors that you will make in defining new functions, here are the Three Laws of Function Definition for Mathematica (in homage to Asimov's Three Laws of Robotics.

1. Always use square brackets in the function definition and function evaluation.

For example, use f[x_]:=x+3 instead of using f(x_)=x+3.

2. Always use := instead of = in your function definition.

For example, use f[x_]:=x+3 instead of using f[x_]=x+3.  Using SetDelayed (:=) causes your function not to be evaluated until you call it.  This behavior mimics how most other programming languages work. (Later you will make use of = once you have a rock solid understanding of the difference between how := and = behave.

3. Always remember to use an underscore after the parameters to your function.

For example, use f[x_]:=x+3 instead of using f[x]=x+3.  This is a common mistake even for experienced Mathematica users.  A tip-off that this is the problem is if Mathematica acts like it doesn't recognize your definition. For example,

f[x]:=x+3

f[3]

Note that Mathematica actually does have a definition for f[x] stored.  However, without the underscore after the variable x, the definition matches only the exact expression f[x] and nothing else.  For example.

f[x]

Finally, it is also possible to define functions of several variables.  For example, the function bothPos[x,y] returns the Boolean value True if and only if both x and y are positive.  Note that these definitions also follow the three laws given above.

bothPos[x_,y_]:=And[x>0,y>0]

bothPos[1,1]
bothPos[-1,1]

Problem

ascending[1,2,3]
ascending[3,2,1]

Problem

Problem

Problem

Lists

So far we have seen only atomic values in Mathematica (i.e. data consisting of only a single piece of information), such as integers, real numbers, and booleans. However, the most important aggregate data type in Mathematica is the list.  A list consists of a sequence of items enclosed by curly braces and separated by commas.  For example, the list consisting of the numbers 1, 2, 3, and 4 has the form

{1,2,3,4}

Note that internally, Mathematica represents this list in the form List[1,2,3,4].

Creating lists

There are several ways to create lists in Mathematica.  The easiest way is simply to enumerate the entries in the list as done above.

Built-in functions

The Mathematica function Range is also a very useful function for creating simple lists of numbers.  Be aware that Range has many variants to handle more complex demands.

Range[4]

Unfortunately, life is not always so simple.  In many cases, we wish to build a function that processes lists in some manner. In Mathematica, there are two standard ways to create lists: recursively or iteratively.

Problem

Recursion

Recursive constructions for lists use the functions Append (or Prepend) to add members to the end (or beginning) of the list.  To illustrate this process, here is a simple recursive definition of a list

A list is either the empty list {} or Append[l,x] where l is also a list.

Here is a function that create a list of integers from 1 to n.

makeList[n_]:=If[n==0,{},Append[makeList[n-1],n]]

makeList[4]

Note that this definition of makeList has a structure very similar to the recursive definition of factorial in the previous section.  The definition checks whether n==0 (the base case) and returns our definition of what a list of length zero looks like ({}) when n==0.  Otherwise, makeList calls itself recursively using the smaller value n-1.  By repeatedly decreasing n, makeList eventually hits the case n==0 and stops.

Problem

Iteration

Another method for creating lists is to construct the list iteratively using the Table function.  Here is an alternative definition of makeList using Table.

makeList[n_]:=Table[i,{i,1,n}]

makeList[4]

The function Table is the most important Mathematica function that you will learn in this class.  One of your first goals in the class is to become a skilled user of Table.   To this end, let's examine Table in more detail.  In our example, Table takes two parameters:  the expression i and an iterator {i,1,4}.  In Mathematica, an iterator expresses a range of values that a variable should take on during some type of computation.  In this case, the variable i should take on the values from 1 to 4, increasing by the (default) stride of 1.   The Table command then creates a list with the expression i taking each of these values.

Problem

Taking lists apart

Often you will need to extract various pieces of a list.  Mathematica supports multiple functions to perform this task.  In the recursive style, Mathematica supports the functions First and Last that return the first and last elements of a list.  The functions Rest and Most return the list with either its first or its last element removed.  For example,

First[{1,2,3,4}]
Last[{1,2,3,4}]
Rest[{1,2,3,4}]
Most[{1,2,3,4}]

These functions will be particularly useful when you are manipulating lists recursively.

For iterative applications, Mathematica supports the function Part[l,i] that returns the ith element of the list l.  This function is used so often that Mathematica supports the shorthand form l[[i]] or l[[i]].  (The special bracket [[ are formed by typing Escape [[ Escape.)  Remember this operation, you will use it often.

l={1,2,3,4}
Part[l,3]
l[[3]]
l[[3]]

A common error when using Part is to try and access a portion of the list that does not exists.   For example, list indices start at 1.  Trying to take the 0th element in the list yields nonsense (the value List).  Asking for an element after the end of the list yields an error.

l[[0]]
l[[5]]

This overview just skims the surface of Mathematica's capabilities concerning lists.  Spend a couple of minutes browsing the section List Manipulation in the Documentation Center to get a better idea of Mathematica's list capabilities.

Problem

sqrList[l_]:=Table[…,{i,1,10}]

Basic Graphics

The eye is probably the most potent sensory organ for human beings and as we all know a single picture is worth a thousand words.  For these and other reasons, we want to be able to produce visual representations of scientific, mathematical, or technical problems.  The following two functions in Mathematica are the workhorses for making plots.

ListPlot

In Mathematica the function ListPlot can be used to create plots of lists. ListPlot[l] creates a plot of values l[[1]], l[[2]], ..., l[[n]]at the parameter values 1, 2, ..., n.

ListPlot[{1,4,9,16,25,36}]

You can use the following form to join the points by lines:

ListPlot[{1,4,9,16,25,36},Joined->True]

The extra parameter Joined->True is an option to the function ListPlot. Most of the plotting functions in Mathematica have numerous options that allow the user to control the appearance of a plot.  The Documentation Center contains lots of information on appropriate options.

Problem:

Plot

The function ListPlot can be used to create plots of discrete sequences, i.e. a list of numbers.  Often we want to create visual representations of continuous functions such as the function (x^2).  Mathematica can create plots of such continuous functions using the function Plot[expr,{x,min,max}].  Here, expr is a Mathematica expression containing the variable x and {x,min,max} is an iterator that specifies that x should vary from min to max.  This function will create a plot of the values of expr with x varying between the range min and max.  For example:

Plot[(x^2),{x,1,6}]

Problem:

Strings

To conclude this module, we will attack a slightly more complicated programming exercise that is relevant to a real world problem.  A string is a sequence of characters enclosed by double quotes.

"Hello world"

The most common use for strings is as input to the Print  function

Print[10, " factorial is ", 10!]

You will not use Print statements except occasionally to help in debugging your Mathematica functions.  Instead, we shall rely on Mathematica to simply return the answer we desire.  Here, we introduce strings to frame an interesting, real world problem: cryptography.

Problem:  Cryptography

decrypt[encrypt[s]]==s

encrypt["this is my secret message"]

decrypt[%]