A First Tour Through Mathematica

Basic Mathematica Commands

In this section, we explain basic Mathematica commands and principles demonstrated in small and hopefully easy examples.

Mathematica does exact calculations without round-off errors.

4700+11

Plus[4700,11]

1/3+5/7

(1/3)+(5/7)

Moreover, it can deal with "symbols" such as (Sqrt[ ]).

Sqrt[4711]

sqrt[4711]

(Sqrt[4711])

Well, this didn't compute much. See the following example:

(Sqrt[(9/13)])

If desired we can compute the numerical value of an expression.

N[%]

The last command shows two features:

the function call and

the access to previously computed output.

f[x,y] is the standard form of calling a function f with parameters x and y. There are alternative ways of expressing the same:

f@x

x//f

x~f~y

The percent sign % refers to the last output. Every output is numbered, and the number can be used to refer to arbitrary output of the current session.

%

%7

Caution: Be careful with % in the notebook frontend. The % refers to the last output from the kernel's point of view. This need not necessarily be the output immediately above, it can be anywhere in the notebook, it can even be in a different notebook. Use this feature with care, it is convenient for quick interactive prototyping. For computations that are intended to be stored and reproducible in furture sessions, we recommend to assign result that are needed later to auxiliary variables. Note: What is output %7 in this session need not necessarily have number 7 in any future session!

For numeric evaluation, we can optionally give the number of decimal digits.

(Sqrt[(23/45)])

N[(Sqrt[4711]),30]

However, Mathematica does not display more digits than it has available

N[6.5,20]

For display, we recommend NumberForm.

NumberForm[6.5,20]

The number of digits available can be specified when inputting approximate numbers.

6.5`4

NumberForm[6.5`4,3]

Be careful with =: Equalities are written with ==, whereas the single = is for assignment (like in many programming languages).

eqn=a*(x^2)+b*x+c==0

sol=Solve[eqn,x]

Solve returns the two solutions of the equation in form of lists of transformation rules, which can be applied to other expressions in various ways.

Replace[x,sol]

Replace[2 a x,sol]

2 a x/.sol

Various Further Commands

We try to give an overview over other commands for manipulating mathematical expressions. We show all commands as stand-alone function calls, but always remember that all these functions will be available as subroutines in our own programs!
We only show some functions, use the HelpBrowser to find out more.

Manipulating Terms

Expand[(((a+b))^2)]

Factor[(x^2)-1]

Expand[(((a+b))^30)((a^3)-1)]

Factor[-(a^30)+(a^33)-30 (a^29) b+30 (a^32) b-435 (a^28) (b^2)+435 (a^31) (b^2)-4060 (a^27) (b^3)+4060 (a^30) (b^3)-27405 (a^26) (b^4)+27405 (a^29) (b^4)-142506 (a^25) (b^5)+142506 (a^28) (b^5)-593775 (a^24) (b^6)+593775 (a^27) (b^6)-2035800 (a^23) (b^7)+2035800 (a^26) (b^7)-5852925 (a^22) (b^8)+5852925 (a^25) (b^8)-14307150 (a^21) (b^9)+14307150 (a^24) (b^9)-30045015 (a^20) (b^10)+30045015 (a^23) (b^10)-54627300 (a^19) (b^11)+54627300 (a^22) (b^11)-86493225 (a^18) (b^12)+86493225 (a^21) (b^12)-119759850 (a^17) (b^13)+119759850 (a^20) (b^13)-145422675 (a^16) (b^14)+145422675 (a^19) (b^14)-155117520 (a^15) (b^15)+155117520 (a^18) (b^15)-145422675 (a^14) (b^16)+145422675 (a^17) (b^16)-119759850 (a^13) (b^17)+119759850 (a^16) (b^17)-86493225 (a^12) (b^18)+86493225 (a^15) (b^18)-54627300 (a^11) (b^19)+54627300 (a^14) (b^19)-30045015 (a^10) (b^20)+30045015 (a^13) (b^20)-14307150 (a^9) (b^21)+14307150 (a^12) (b^21)-5852925 (a^8) (b^22)+5852925 (a^11) (b^22)-2035800 (a^7) (b^23)+2035800 (a^10) (b^23)-593775 (a^6) (b^24)+593775 (a^9) (b^24)-142506 (a^5) (b^25)+142506 (a^8) (b^25)-27405 (a^4) (b^26)+27405 (a^7) (b^26)-4060 (a^3) (b^27)+4060 (a^6) (b^27)-435 (a^2) (b^28)+435 (a^5) (b^28)-30 a (b^29)+30 (a^4) (b^29)-(b^30)+(a^3) (b^30)]

Simplify[(((x^2)-1)/(x+1))]

Integration

∫((x^(3/2)) Cos[2 (Sqrt[x])]+2 x Sin[2 (Sqrt[x])])\[DifferentialD]x

(∫_0^((π^2)/16))((x^(3/2)) Cos[2 (Sqrt[x])]+2 x Sin[2 (Sqrt[x])])\[DifferentialD]x

Differentiation

D[(x^5),x]

(∂_x) ((x^2)Sin[2(Sqrt[x])])

deq=x''[t]==-x[t]

DSolve[deq,x[t],t]

dsol=DSolve[{deq,x[0]==0,x[(π/2)]==1},x[t],t]

tsol=Table[DSolve[{y''[x]+((3/4y'[x])/(x+3))==1,y'[0]==a,y[0]==0},y,x],{a,-2,2,1/2}]

Limits

Limit[((Sin[x])/x),x->0]

Limit[(1/(Sqrt[x])),x->∞]

Limit[(1/(Sqrt[x])),x->0]

Matrices

H=Table[(1/(i+j-1)),{i,5},{j,5}];
MatrixForm[H]

Det[H]

G=Inverse[H];
MatrixForm[G]

MatrixForm[H.G]

Gn=Inverse[N[H,3]];
MatrixForm[Gn]

MatrixForm[H.Gn]

LinearSolve[(({{1, -1, 2}, {-3, (2/3), 1}, {0, 1, 1}})),{0,1,2}]

A={{1,-3,3},{3,-5,3},{6,-6,4}};
MatrixForm[A]

Eigensystem[A]

Sums, Products, Series

(∑_(i=1)^n)(i^2)

(∏_(i=1)^n)(i^2)

Series[Log[x],{x,1,6}]

Graphics

Plot[LegendreP[3,x],{x,-1,1}]

Plot[Evaluate[y[t]/.tsol],{t,-1,2},PlotRange->{-1,2},PlotStyle->Table[Hue[a],{a,0,1,0.1}]]

Plot3D[(x^2)+Sin[(y^2)],{x,-3,3},{y,-π,π},PlotPoints->100]

Programming

If we want to execute more than one command in one stroke, we simply separate the individual commands by semicolons ";".

a=1;b=2;a+b;

a

b

Note, the semicolon separates commands, therefore we don't need a semicolon after the last command in the sequence. This differs from many programming languages where the syntax requires every statement to be terminated by a semicolon.
The general rule is: everywhere, where we are allowed to write one expression, we can also write a sequence of expressions of the form

expr1;expr2;expr3

The return value of a sequence is the return value of the last command in the sequence.

expr1;expr2;expr3

Putting a semicolon after the last expression in a sequence makes Mathematica think there is an additional command in the sequence, which is eventually the "empty command" represented as Null in Mathematica. By convention, Mathematica does not display Null.

Null

This has turned into the standard way to suppress output from an expression.

FullForm[Hold[a=45;]]

a

At the same time, this is one of the most common errors in Mathematica programming: as we will see later, the return value of a function if often simply the result of the sequence of commands in the body of the function. Terminating the last command with a semicolon suppresses result, and thereby suppresses the return value of the function. However, it is no syntax error to do so …
Conditional branching and looping constructs are available as special expressions.

a

If[a==45,a=2 a,b]

a

If[a==45,a=2 a,b]

For[i=1,i≤4,i++]

i

Which[i<1,i+1,i==5,N[(i/2)],True,i]

If we want to repeat the evaluation of a certain expression or sequence of expressions, we simply give it a name. If we want to substitute actual values at certain positions when "calling the expression" again, we introduce formal parameters. A program has been born …

P[i_]:=(a=i;b=i+2;a+b)

P[0]

x=P[5]

x

y=P[7]

y

a

b

?y

?P

Clear[a,b,x,y,P]

?P

Patterns

As shown above, we can pass values to a function. ATTENTION: In the function definition we write parameters in square brackets "[" and "]", in the function call we pass values enclosed in square brackets.
Mathematica supports overloading, i.e. we can use one function name and give several definitions depending on the number of parameters and/or the type of the parameters.

Successor[n_Integer]:=n+1

Successor[r_Rational]:=((Numerator[r]+1)/(Denominator[r]))

Successor[1]

?Successor

Successor[{a_Integer,b_Rational}]:=a+b

?Successor

Clear[Successor]

Successor[n_]:=n/2

Successor["es"]

Successor[(1/7)]

Successor[n_Integer]=.

?Successor

The following does not work …

Successor[(Rational)3]

But not only "types" can be used in the parameter specification. There is a multitude of so-called patterns that can be used and pattern matching is then the method to call the appropriate function when a function call with concrete values needs to be executed. In the sequel, we show some of the possibilities how to specify patterns in function definitions.

NonNegative[2]

mySqrt[r_?NonNegative]:=(Sqrt[r]);
mySqrt[r_?Negative]:=False

mySqrt[4]

mySqrt[-3]

f[x_?x>0]:=2x

f[4]

?f

(x>0)[4]

Function[x,x>0][4]

Clear[f]

f[x_?(Function[x,x>0])]:=2x

f[4]

?f

Clear[minimum]

minimum[x_,y_]/;x<y:=x

minimum[x_,y_]:=y

?minimum

minimum[1,3]

minimum[3,1]

In many applications it turns out to be useful to refer to the syntactical structure of the parameters.

myLength[l_List]/;l=={}:=0

myLength[l_List]:=1+myLength[Rest[l]]

myLength[{3,4,6}]

Clear[myLength];
myLength[{}]:=0;
myLength[{f_,r___}]:=1+myLength[r]

myLength[{}]

myLength[{a}]

myLength[{a,b,c,d}]

We need to put r in the recursive call again into a list!

Clear[myLength];
myLength[{}]:=0;
myLength[{f_,r___}]:=1+myLength[{r}]

myLength[{a,b,c,d}]

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

Pattern matching (except the patterns "?" und "/;") refers to the syntactical structure, not to the meaning of the parameters.

f[x_,2x_]:=3

f[2,4]

f[WW,2WW]

f[x_,y_]/;y==2x:=3

f[2,4]

Find more in chapter Pattern matching.

In general, a Mathematica program P with parameters x is a statement of the form

P[x]:= expression

where

x is a pattern (or a sequence of patterns separated by commas ",")   and

expression is a  Mathematica expression. There are some special  Mathematica expressions taking over the role of programming constructs, e.g. For or If and others. These may occur in a program, but they need not.

From Individual Commands to a Program

Consider the following problem from probability calculus: An object is located at position (0,0) in a cartesian coordinate system. After every minute, the object moves either 1 unit to the right or one unit up, both with equal probability. What is the probabiliy that the object is located in (7,3) after 10 minutes?
We develop a program that simulates 10 random movements of the object and then calculate the percentage of moves ending in (7,3) when doing several tries.
Typical development of Mathematica programs proceeds as follows: We do not immediately start to write the program, we rather try each step separately and only then assemble a program once the individual steps have been tried out.

Object={0,0};

Do[Print[RandomInteger[{0,1}]],{5}]

Do[If[RandomInteger[{0,1}]==0,Object=Object+{1,0},Object=Object+{0,1}],{10}]

Object

Object={0,0};
Do[If[RandomInteger[{0,1}]==0,Object=Object+{1,0},Object=Object+{0,1}],{10}]

Object

Now, in order to get an approximation for the probability we compute the relative frequency of the event under consideration when repeating the experiment several times, i.e. we generate e.g. 10 random paths and check how often they end in (7,3)!

absFreq=0;
Do[Object={0,0};Do[If[RandomInteger[{0,1}]==0,Object=Object+{1,0},Object=Object+{0,1}],{10}];Print[Object];If[Object=={7,3},absFreq=absFreq+1],{10}];
N[(absFreq/10)]

The symbols occurring in the above code are globally accessible, i.e we can access their values also from "outside" the code.

absFreq

Object

Now we want to turn the auxiliary symbols into local values that are invisible outside the code. In addition, we want to have a variable number of repetitions of the experiment.

Clear[Object,absFreq]

RelFreq[n_]:=Module[
{absFreq=0,Object},
Do[
Object={0,0};
Do[
If[RandomInteger[{0,1}]==0,
Object=Object+{1,0},
Object=Object+{0,1}],
{10}];
If[Object=={7,3},
absFreq=absFreq+1],
{n}];
Return[N[(absFreq/n)]]
]

RelFreq[1000]

The values of local variables are now not visible anymore outside the program.

absFreq

Object

It is sometimes convenient, sometimes maybe even necessary to use global variables. In a decent programming style, whatever this is, we try, however, to keep as many variables as possible as local variables.

Local Variables, Local Values and Local Constants

A Module realizes the concept of "local variables", which have nothing to do with objects/symbols outside the module.

a=s;

Module[{a},a==90]

Module[{a},a==90]

You see: the variable a inside the Module has nothing to do with the symbol a outside the module. Moreover, each execution of the module generates a fresh version of a, such that in subsequent executions of a module you can always rely on the local variables being completely fresh objects.
Similar to a module, there is also a Block, which should be understood as a construct to introduce local values for (possibly) global objects.

Block[{a},a==90]

Block[{a=w},a==90]

a

You should see: The object a inside the block is obviously the same as the a outside, therefore the first result. However, values assigned to a inside the block have only local scope, i.e. they are only valid inside the block. When leaving the block, the original values are restored. A block is convenient for locally changing the values of global system parameters (such as e.g. $RecursionLimit), since their original values are automatically restored and one need not take care about restoring the appropriate values.
Sometimes we do not even need variables, constants are all we need. This is what With would do:

With[{a=w},a==90]

a

Invalid use of With is:

With[{a},a==90]

With[{a=100},If[a==90,a=a+1,a=a-1];a]

Compare:

Block[{a=100},If[a==90,a=a+1,a=a-1];a]

a

a=.

See chapter Evaluation for a nice application of With.

Rule–Based Programming

A programming style available through the pattern matching facility of Mathematica is the so-called rule–based programming style. This means, essentially, to avoid (deeply nested) If-Then-Else-constructions by implementing each branch as a separate function with same name but different argument patterns and let the branching happen by the pattern matching mechanism in the function call. We illustrate the idea in the example above. Instead of the code fragment

If[RandomInteger[{0,1}]==0,Object=Object+{1,0},Object=Object+{0,1}]

introduce a new function NextMove representing the two branches in the If.

NextMove[p_,0]:=p+{1,0}

NextMove[p_,1]:=p+{0,1}

Sometimes, iterative loop constructions can be substituted by recursions involving patterns, e.g.  instead of the

Do[…,{10}]

we introduce a function Move like

Move[{x_,y_}/;x+y<10]:=Move[NextMove[{x,y},RandomInteger[{0,1}]]]

Move[X_]:=X

Let's test this before we go into the final program.

Move[{0,0}]

CountSuccess[{7,3},a_]:=a+1

CountSuccess[pos_,a_]:=a

CountSuccess[Object,1]

RelFreq[n_]:=Module[{absFreq=0},
Do[
absFreq=CountSuccess[Move[{0,0}],absFreq],
{n}];
N[(absFreq/n)]]

RelFreq[1000]

Exercise: Cantor's Scheme

Implement a function Successor, which computes the successor of a positive rational number according to Cantor's diagonalisation scheme. Use rule based programming style in your program (i.e. use recursion and pattern matching for the different steps in the diagonalisation procedure).

Details: see separate notebook.