Some Useful Programming Tools for Mathematica

Patrick Malsom
1:00 PM    November 4th 2011
Room 300 Geo/Phys (Hauck Lab)

Abstract : This talk will focus on advanced mathematica functionallity that allows the development of portable post processing libraries used for simulation and data analysis. I will focus on programming practices for developing libraries that are easily used by relativley inexperienced users of Mathematica. I will illustrate this functionallity through concrete examples.

Overview

We will cover the following in this presentation :

Programming

Module
Compile
Wolfram Workbench

Mathematics

Pure Functions
Map
Nest
Application to Chaos (Bifurcation)

Using Mathematica

Many users of Mathematica use the language as they would a scripting (bash, python) or a compiled language (Fortran, C). While Mathematica does provide all of the functionallity necessary for these two there are many more things that Mathematica can do. I will overview a few of these.

This talk will show you how to utilize some advanced functions to be able to develop larger projects more efficiently.

Coding Paradigm

Simulations and experiments require a large amount of post processing (ie: data analysis)
The development of libraries (collection of code to perform common tasks) can use a large amount of your research time.
Code libraries can be very large and combersome.

The time it takes to run code is paramount for todays extremely large data sets.
Idealy, the only defined objects are the high level function calls that perform the final calculation. Everything else remains useable for the post processing.

Module

A module allows you to write routines that have local variables to the module. This is very useful when writing a set of functions you need to perform certain tasks and do not want to pay attention to what names you have used in your functions.

Evaluating mutiple sets of the same module will not effect the local varibles to each call.

?Module

Module[{x},Print[x];Attributes[x]]

Module of Riemann’s Zeta function

ζ[x]=(∑_(n=1)^∞)(1/(n^x))

zetaModule[x_]:=Module[{xLocal=x,sumLocal=0.0},
Do[sumLocal+=1/n^(xLocal);
,{n,1,1000000}];
sumLocal
]

zetaModule[2.]

Zeta[2.]

Compile

Biggest advantage of precompilation is the ability to perform optimizations.
Mathematica is interpreted by default: Easy to code but execution can be slow.
Compilation is very easy to perform Mathematica.

?Compile

Key differences from regular function declarations:
Function arguments are included inside of the Compile function. 
Varibles must have an explicit type.

Compilation of the Zeta Function Module

zetaCompile= Compile[{{x, _Real}},Module[{xLocal=x,sumLocal=0.0},
Do[sumLocal+=1/n^(xLocal);
,{n,1,1000000}];
sumLocal
],CompilationTarget->"C"];

compileTime=AbsoluteTiming[zetaCompile[2.]]

moduleTime=AbsoluteTiming[zetaModule[2.]]

moduleTime[[1]]/compileTime[[1]]

Wolfram Workbench

Modules do pose a significant problem when trying to debug code. The variables are local and there is no reasonable way to identify what the local varibles are inside of the module when debugging. 

Wolfram Workbench alleviates this problem. 

An example is in order!

Pure Functions

The first object I will introduce in the Math section is a Pure Function. This is different than a regular function in a programming lanuage. It is more analogous to a function from formal mathematics.

?Function

Pure functions allow the user to use a function without the need to define or name anything. It also allows the parameters of the function to remain local.

test[y_]:=Function[x,x^2*y]

test2=test[1]

test2[2]

Symbols for Pure Functions

&		Pure Function Operator	Declares  the end of a pure function
#  (#n)		Slot Number			The ((n^th)) argument of a pure function
##		All Slots			All arguments

(1+#)&[x]

(#1^2+#2)&[y,z]

f[##]&[x,y,z]

Map (/@)

?Map

Map[f,{{a,b},{c,d,e}}]

Pure functions become very useful when combined with the Map Function.

(1+g[#])&/@{a,b,c,d,e}

Nest

Nest is closeley related to the map function. Instead of applying the function to each element in an expression, the Nest function will recursivley apply the function to the expression.

Nest[f,x,5]

Pure functions may also be used inside of a nest (just as with Map)

Nest[1/(1+#)&,x,5]

A nested list gives all levels of the nesting operation in a list. This is extremely useful in the calculation of recursive algorithms.

NestList[f,x,5]

Bifurcation: What is it?

Many systes of equations have a strong dependence on the input parameters. Some input parameters yield a stable result and others do not. These equations can be very simple on face value. For example:

(Subscript[x, n])=μ (Subscript[x, n-1])(1-(Subscript[x, n-1]))

For certain values of μ this equation comverges to a single unique result as you incriment (Subscript[x, n]). for other values it converges to 2, 4, 8, ⋯ results.

Bifurcation: What is it?

bifurcation=Compile[{{μ,_Real}},Map[({μ,#}&),NestList[μ # (1-#)&,RandomReal[{0.01,0.99}],300]]];
data=Table[Table[bifurcation[j][[k]],{j,1,4,0.01}],{k,1,100}];
Do[PrependTo[data,Table[0,{i,1,301},{j,1,2}]];,{k,1,7}]
Manipulate[ListPlot[Table[data[[k]],{k,n,n+7}],PlotRange->{{1,4},{0,1}},PlotStyle->{{Black,PointSize[0.005]},{Black,PointSize[0.005]},{Black,PointSize[0.005]},{Black,PointSize[0.005]},{Black,PointSize[0.005]},{Black,PointSize[0.005]},{Black,PointSize[0.005]},{Red,PointSize[0.015]}},PlotLabel->"(Subscript[x, n + 1]) = μ (Subscript[x, n]) (1-(Subscript[x, n]))",AxesLabel->{"μ","(Subscript[x, n + 1])"}],{n,1,100,1}]

Bifurcation Using “Traditional” Programming Methods

fun[μ_,x_]:=μ x (1-x)
list2={};
Table[
list1={};
temp=.2;
Do[
temp=fun[j,temp];
,{i,1,300}];
Do[
temp=fun[j,temp];
AppendTo[list1,{j,temp}];
,{i,1,400}];
AppendTo[list2,list1];
,{j,1,4,0.01}];

ListPlot[Flatten[Union[list2],1],PlotStyle->{Black,PointSize[0.002]},PlotLabel->"(Subscript[x, n + 1]) = μ (Subscript[x, n]) (1-(Subscript[x, n]))",AxesLabel->{"μ","(Subscript[x, n + 1])"},PlotRange->{{1,4},{0,1}}]

Bifurcation Using Pure Functions and Compile

bifurcation1=Compile[{{μ,_Real}},Map[({μ,#}&),Union[Drop[NestList[μ # (1-#)&,.2,700],300]]]];

ListPlot[Flatten[Table[bifurcation1[μ],{μ,1,4,0.005}],1],PlotStyle->{Black,PointSize[0.002]},PlotLabel->"(Subscript[x, n + 1]) = μ (Subscript[x, n]) (1-(Subscript[x, n]))",AxesLabel->{"μ","(Subscript[x, n + 1])"},PlotRange->{{1,4},{0,1}}]

Thank You!

Thank you for joining me today.

I hope that using these techniques you will have a more productive experience with Mathematica!