Sie sind auf Seite 1von 8

Mathematica Workshop II

NU–UI Mathematics Summer REU Program


A.J. Hildebrand

6/24/2016

About this workshop


In this workshop, you will learn how to:

• Define functions of various types, e.g., functions that take a list as input and output a scalar
value or another list.

• Use Nest and NestList to iterate functions.

• Define pure functions, using the # and & notations.

• Use Select to construct sublists, and to compute frequencies of list elements satisfying certain
conditions.

• Use the RandomReal functions to generate random numbers, and lists of random numbers.

• Use statistical functions, such as Median, Mean, StandardDeviation, and Histogram.

• Use Mathematica experimentation to come up with conjectures.

Reminders
• Working with Notebooks

– If you open an existing notebook (e.g., one you have saved before), always
evaluate the notebook first. Click on “Evaluation,” then “Evaluate Notebook”.
– Remember to press Shift-Enter after each command to evaluate this com-
mand. To evaluate (or re-evaluate) the entire notebook, click on “Evaluation”, then
“Evaluate Notebook.”
– Handling Mathematica “freezes” and crashes: If Mathematica gets “stuck” (e.g.,
because a calculation takes too long), click on “Evaluation”, then “Abort Evaluation.”
Sometimes, it takes several tries to “kill” an evaluation. Sometimes, a freeze means
that Mathematica has crashed, and then the only way out is to close the Mathematica
program. (You might see a popup window saying something like “Mathematica is unre-
sponsive. Force Quit.”) In this case, any unsaved work will be lost. This is why it is
important to save your work frequently.

1
Mathematica Workshop II A.J. Hildebrand

– TIP: Change the magnification of the notebook to 125% or 150%. This makes
it easier to distinguish different types of parentheses ([] versus () or {}). The magni-
fication can be changed through the radio button at the bottom right of the notebook
window.

• Conventions in Mathematica

– Built-in constants and functions are all capitalized. In compound function


names, both parts are capitalized. For example: I (imaginary unit), E (constant
e), Pi (constant π), Sin, ArcSin, RandomReal, RandomInteger, DivisorSum.
To avoid conflicts with built-in commands, always use lower case names for your own
definitions of functions and variables.
– Conventions for parentheses: [] (function argument, e.g., sin[x]), bgroup{}egroup
(list, e.g., {1,2,3}), () (grouping, e.g., 1/(1+x)), [[]] (list elements, e.g., a[[3]]).

• Getting help

– Quick access to documentation pages. A convenient shortcut to the documentation


for a particular command is to start typing the command until a circled “i” symbol pops
up. Alternatively, you can slowly move your mouse through the command name from
left to right until the circled “i” symbol pops up. Clicking on this symbol will pop up a
window with the documentation page for this command.
– Use built-in help pages rather than searching online for documentation. The
built-in documentation gives more reliable information and is specific to the particular
Mathematica version you have installed. In addition, the built-in documentation
pages are live notebooks that you can use for scratch work and try things
out. With online documentation, this is not possible.

2
Mathematica Workshop II A.J. Hildebrand

Defining a function
The basic form of a function definition is f[x_]:=..., where x_ (note the underscore!) is the
variable, and := denotes a delayed assignment, which is what you usually want when defining a
function. The function name, f in the above case, can be pretty much any alpha-numeric string
(though you should avoid strings beginning with a capital letter), and the right-hand side of the
definition can be pretty much any Mathematica expression. When calling up the function, use f[x]
(or f[1], f[a], etc.) without the underscore.
Here are some examples of function definitions:

• f[x_]:=x^2+2*x+3

• rpts[n_]:=RandomReal[{0,1},n] (generates n random real numbers in (0, 1); try it out a


few times!)

• squareSum[x_,y_]:=x^2+y^2.

• squareSum2[vec_]:=Total[vec^2] (takes a list vec as argument, squares the list compo-


nentwise, then adds up the components (Total))

• gauss[x_]:=NIntegrate[(1/Sqrt[2*Pi])E^(-t^2/2),{t,x,Infinity}]
R∞ √ (computes the Gauss
2
integral x (1/ 2π)e−t /2 )

• binomProb[n_,k_,p_]:=N@Binomial[n,k]p^k(1-p)^(n-k) (computes the probabilities in


the binomial distribution). (Note the N function to force numerical computation; this could
have also been coded as N[Binomial[...]...], but the “prefix” notation N@... is more
succinct.)

Tips and pitfalls in function definitions


Errors in function definitions can be extremely hard to diagnose, so you have to be very careful
with such definitions and make sure to use the correct syntax. Here are some tips on avoiding
common errors.

• Always use lower case names for your own variables and function names. This is
to avoid conflicts with built-in variables and functions. The first letter should always be lower
case, though other letters can be upper case. For example, binomialSum would be perfectly
fine as a function name.
The same applies to variable
P names: For example, if you want to define a function, squaresum,
that calculates the sum N n=1 n 2 in Mathematica, using squaresum[N_]:=... would give an

error since N is a built-in function (numerical value). Thus, use another (lower case) letter
instead, e.g., squaresum[k_]:=....

• Never use underscores in function names. Underscores have a special meaning in Math-
ematica and should not be used in function names. For example, binomial_Sum might cause
strange errors; use binomialSum instead. (Numbers are okay; for example, binomialSum3
would work fine.)

• Don’t forget the underscore for each variable on the left side of the definition. You
won’t get an error, but the function won’t behave in the expected way. (Try it: f[x]:=x^2+1,
followed by f[1].)

3
Mathematica Workshop II A.J. Hildebrand

• Underscores should only appear on the left side of the definition. For example, if
you say g[x_]:=x_^2+1, you will get an error message.

• Use a “colon-equal” sign (:=), not an ordinary equal sign, in function definitions.

• Avoid re-using function names or use “Clear” before re-using or re-defining the
names. A common situation is when you start out with a simple function definition, e.g.,
f[x_]:=x^2+1, and then want to generalize it by introducing a second variable, e.g., f[x_
,n_]:=x^n+1. This will give an error.
To avoid this, use either a different name for the more general function (e.g., ff[x_,n_]:
=x^n+1), or “clear” the function from memory with the command Clear[f] before redefining
the function.
Note: Problems with multiple definitions of a function can persist across multiple notebooks.
Thus, if you have several notebooks open (e.g., a scratch notebook, and a practice notebook),
avoid using the same function name multiple times, even if the definitions are in different
notebooks.

4
Mathematica Workshop II A.J. Hildebrand

Practice with function definitions and iterations of functions


1. Functions of lists. Define a function norm, that takes a vector (i.e., a one-dimensional
list) as input and outputs its norm (length). For √
√ example, norm[{1,2,3}] should produce
1 + 2 + 3 , norm[{1,2,3,4}] should produce 12 + 22 + 32 + 42 , etc. Notes:
2 2 2

• The above approach using lists as function argument is useful in many contexts: Its
main advantage is that it works for vectors of arbitrary dimensions. Without lists,
one would need to define a separate function for each dimension, e.g., norm2[x_,y_],
norm3[x_,y_,z_], etc.
• Make sure to provide the arguments to this function as a list, encloed in a pair of braces,
{}, i.e., norm[{1,2,3}], not norm[1,2,3].

2. Iterating functions: Functions can be iterated using the Nest and NestList commands.
For example, Nest[Cos,0,3] produces the 3rd iterate of cos with initial value 0, while
NestList[Cos,0,3] generates the list of the all k-th iterates up to k = 3. Use this approach
to determine experimentally the limit when iterating the cosine function, with 0 as initial
value, i.e., the value of cos(cos(cos(...0))). (Hint: Use the N function to force Mathematica to
carry out the computations numerically.)

3. Iterating the “sum of digit squares” function. Define a function that takes a positive
integer, forms the list of its decimal digits (IntegerDigits), and computes the sum of the
squares of these digits (Total[...^2]. See what happens when you iterate this function.

4. “Pure” function: To iterate the function x → x2 , we could give it a name, say square[x_]:
=x^2, and then use Nest[square,2,5] as before.
A shorter, and more elegant approach is to put the definition of this function inside the
Nest or NestList commands: NestList[#^2&,2,5]. Here #^2& denotes a pure function,
that takes a number, denoted by #, and squares it; the ampersand, &, is a required part of
the pure function syntax and denotes the end of the function definition. Don’t forget the
ampersand here!
Try this approach with some examples, e.g., the iterations of x → 2x , or x → cx(1 − x).

5. A function that “grows” lists. Here is an example of a function that takes a list of 0’s and
1’s as input and outputs a list that is double the length of the original list: Given a list of 0’s
and 1’s, say {1,0,1}, define a function that (1) computes its “complement” (i.e., {0,1,0},
or 1 minus the list), and (2) concatenates (Join) the two lists, and outputs the concatenated
list, e.g., {1,0,1,0,1,0}.
See what happens if you iterate this function, starting with the list {0}.1
Rewrite the iteration as a single NestList command, using the “pure” function notation to
denote the above list function.

1
The resulting sequence is a very famous one, called the Thue-Morse sequence. Can you guess a formula for the
n-th term of this sequence?

5
Mathematica Workshop II A.J. Hildebrand

Working with random numbers


Mathematica has very powerful random number functions, in particular, the functions RandomReal
and RandomInteger. This and the following exercises illustrate the use of the these functions.
Look up the documentation on RandomReal , and keep a window with the documentation page
open while you are working on this problem.

1. Simulating sums of random numbers: Watching the bell curve taking shape. One
of the fundamental results in probability is the Central Limit Theorem which says (roughly)
that, whenever a large number of independent random quantities are added up, the resulting
quantity tends to have normal (i.e., “bell curve”) distribution. A nice way to see the normal
curve taking shape is by performing a large number of simulations of sums of n random
numbers in [0, 1], and observing the shape of the resulting distribution as n gets larger and
larger. The following sequence of exercises illustrates this:

(a) Define a function rsum[n_] that generates n random numbers in [0, 1] (RandomReal[1,
n]) and outputs their sum (Total). Test this out for small values of n.
(b) The result of a single run of rsum[n_] is a sum of n random numbers. To see how these
random sums are distributed, define a function, sim[k_,n_], that carries out k runs of
rsum[n] and produces a list of the resulting k random sums. Test this out to make sure
it works as expected.
(c) Apply Mean, Median, and StandardDeviation to the list produced by sim[k,n]. Test
this out with small values of n (say, n ≤ 5) and moderate or large values of k (say,
k = 10, k = 100, k = 10000). Do the results make sense? (The mean and median of
a sum of n random numbers in [0, 1] should be very close to 0.5n, while the standard
deviation should get smaller as the number of simulations, k, increases.)
(d) Apply Histogram to the list produced by sim[k,n] to see the shape of the distribution.
You’ll need to take k fairly large, e.g., k = 104 or k = 105 , to get good results.
(e) Finally, using Table, generate a list of these histograms for n = 1, 2, . . . , 6, say. Observe
how the shape of the histograms approximates a normal (bell-shaped) curve as n gets
larger.

2. Computation of π via random simulations As a fun application of random simulations


here is a way to numerically compute π: Generate a random point (x, y) in the square
[0, 1] × [0, 1]. The probability that this point satisfies x2 + y 2 < 1 is equal to the area of
the part of the unit disk inside that square, i.e., π/4. Performing a large number of such
simulations yields an approximation to this probability, and hence an approximation to π/4.
(This method is known as the Monte Carlo method; it provides a way to numerically compute
areas and volumes of very general regions.)
In Mathematica, this is particularly easy to implement, using arithmetic operations on lists:

(a) First generate a list of n sums of two squares of random numbers, x2 + y 2 . Here is a
one-liner that does this: rlist[n_]:=RandomReal[1,n]^2+RandomReal[1,n]^2
(To see why this works, recall that squaring a list gives the list of squares of the elements,
so the right-side is a sum of two lists, each containing n squares of random numbers. The
sum of lists is computed componentwise, producing a list in which each element is a sum
of two squares of random numbers. Note that each invocation of RandomReal generates a

6
Mathematica Workshop II A.J. Hildebrand

new set of random numbers, so the two lists in RandomReal[1,n]^2+RandomReal[1,n]^2


are in fact different.)
(b) Next, we want to extract the terms in this list of sums of random squares that are
< 1: The key is to apply the Select function to extract the list values that satisfy
our condition, as follows: Select[list,#<1&], where list is our list (in this case,
the result of rlist), and the second argument, #<1&, is the criterion for our selection,
coded in much the same way as a pure function. Don’t forget the ampersand
(&) at the end of the condition. Test this out first with an explicit list, e.g.,
Select[{.2,.5,1.2,3},#<1&], then apply it to the list produced in the previous step:
goodlist[n_]:=Select[rlist[n],#<1&]
Test this out with a few explicit values of n.
(c) Next, calculate the numerical proportion of those terms that are < 1 and multiply by 4
to get an approximation for π: approxPi[n_]:=4*N[Length[goodlist[n]]/n].
Again, test this out to make sure it works.
(d) Finally, tabulate the approximations for an appropriate sequence of n-values, e.g., 10k ,
for k = 1, 2, . . . , 6. If your code is correct, these should approach the actual value of π.

Two Case Studies


1. The probability that the sum of n random numbers in [0, 1] is < 1.
Here we try to solve experimentally the following question:

Suppose n numbers are chosen at random from the interval [0, 1]. What is the
probability, P (n), that their sum is < 1?

This question can be answered theoretically using multiple integrals, but it is more fun to
determine the answer experimentally, using Mathematica’s random number functions.

(a) To start with, use the above function sim[k_,n_] to generate a list of k sums of n
random numbers. Check that the function still produces the expected results.
(b) Next, use the Select, Length, and N functions as above to extract the list values that
are < 1, and compute their numerical proportion. Call this proportion prob[k,n].
Test the prob function with explicit values of n and k to make sure it works. (Take a
small n, e.g., n = 4, and a large k, e.g., k = 105 ).
Try this out first on an explicitly specified list, then apply it to sim function, and test
the results with small k and n values.
(c) Finally, tabulate the results for the first few n-values, and try to guess the formula for
prob[n]. Take k larger as needed to get sufficiently accurate results.

2. The smallest gap between random points in [0, 1]. Here we try to answer experimentally
the following question.

If you pick 10 random points in [0, 1], what is, on average, the smallest gap between
these points? What if you have 100 random points instead of 10, or in general n
points?

7
Mathematica Workshop II A.J. Hildebrand

Before attempting to solve this problem experimentally, try to guess the answer. For an
experimental approach, proceed as follows:

(a) Generate a list of 10 random real numbers in [0, 1] (RandomReal[1,10], sort these (Sort),
compute the differences between consecutive sorted numbers (Differences), and calcu-
late the smallest of these differences (Min). The end result is the smallest gap between
10 random points on the interval [0, 1].
(b) Once you have tested the above sequence of commands, define a single function mingap[n_
] that generates n random points in [0, 1] and outputs the smallest gap between these
points.
(c) To get (approximately) the average value of the smallest gap, repeat the mingap func-
tion a large number of times and compute its average value, e.g., using something like
Table[mingap[10],{k,1,100}]//Mean. Try this out for concrete values of n first, then
define a function, say avgmingap[n_], that computes the average smallest gap for a
general number n of random points.
(d) We are interested in the behavior of “average smallest gap” function as n → ∞. To that
end, generate a table of values avgmingap[n] for an appropriate set of n-values (e.g.,
powers of 2), try to come up with an initial guess, then use appropriate normalizations
to test your guess ...

Das könnte Ihnen auch gefallen