Tour of Mathematica

To start this slide show, click the start button:

Clicking start will open a palette with nine buttons:

The next button shows the next slide

The back button shows the previous slide

The first button jumps to the first slide

The skip button skips to the next section

The notes button shows (or hides) lecture notes

The demo button includes examples intended for manual demonstration

The stop button stops the kernel

The reset button attempts error recovery

The close button closes all of the notebooks used in this slide show

SlideShow`controls = Notebooks[]; 
    SlideShow`source = SelectedNotebook[]; SlideShow`$ShowFirstSlide = True; 
    SetOptions[SlideShow`source, Visible -> False];

NotebookFind[SlideShow`source, "palette", All, CellTags]; 
    FrontEndExecute[
      FrontEndToken[SlideShow`source, "GeneratePalette"]];

SlideShow`controls = 
      First[Complement[Notebooks[], SlideShow`controls]]; 
    SetOptions[SlideShow`controls, Editable -> True]; 
    SetOptions[SlideShow`controls, WindowTitle -> "controls", 
      WindowMargins -> {{Automatic, 50}, {40, Automatic}}]; 
    SlideShow`reset = 
      NotebookCreate[WindowTitle -> "reset", Visible -> False]; 
    NotebookFind[SlideShow`source, "reset", All, CellTags]; 
    FrontEndExecute[{FrontEndToken[SlideShow`source, "Copy"], 
        FrontEndToken[SlideShow`reset, "Paste"], 
        FrontEndToken[SlideShow`reset, "SelectAll"], 
        FrontEndToken[SlideShow`reset, "EvaluateCells"]}]

Begin["SlideShow`"];

SlideShow`source = 
        With[{nb = 
              Select[Notebooks[], 
                SameQ[WindowTitle /. 
                      Options[#], "Source for Tour of Mathematica"] &]}, 
          If[Length[nb] > 0, nb[[1]], 
            NotebookPut[
              Notebook[{Cell["No source notebook", "Text", 
                    FontSize -> 24, ShowCellBracket -> False]}, 
                WindowSize -> {250, 70}, 
                WindowMargins -> {{Automatic, 50}, {40, Automatic}}, 
                WindowTitle -> "Error", WindowElements -> {}, 
                WindowFrameElements -> "CloseBox"]]]];

SlideShow`nb = 
        With[{nb = 
              Select[Notebooks[], 
                SameQ[WindowTitle /. 
                      Options[#], "Tour of Mathematica"] &]}, 
          If[Length[nb] > 0, nb[[1]], 
            NotebookCreate[WindowTitle -> "Tour of Mathematica", 
              DelimiterFlashTime -> 0, Magnification -> 2, 
              WindowSize -> {760, 560}, 
              WindowMargins -> {{20, Automatic}, {Automatic, 20}}, 
              StyleDefinitions -> "Training.nb", 
              ScreenStyleEnvironment -> "Slides"]]];

SlideShow`notes = 
        With[{nb = 
              Select[Notebooks[], 
                SameQ[WindowTitle /. Options[#], "notes"] &]}, 
          If[Length[nb] > 0, nb[[1]], 
            NotebookCreate[Visible -> True, WindowTitle -> "notes", 
              WindowSize -> {520, 120}, 
              WindowMargins -> {{20, Automatic}, {20, 
                    Automatic}}]]];

SlideShow`$EvaluationToggle = False;

SlideShow`ShortPause := Do[2 + 2, {10000}]

SlideShow`TypeInput[p_] := 
      If[StringQ[p], 
        Scan[(NotebookWrite[nb, #]; ShortPause) &, Characters[p]], 
        NotebookWrite[nb, p]]

SlideShow`HeadingCell[data_] := 
      MemberQ[{"Title", "Section", "Subsection"}, 
        Part[NestWhile[First, 
            data, (Head[#] =!= Cell || Length[#] < 2) &], 2]]

SlideShow`ShowSlide[data_]:=

\(SlideShow`NextSlide[p_] := 
      If[$EvaluationToggle, $EvaluationToggle = False; 
        FrontEndExecute[FrontEndToken[nb, "EvaluateCells"]], 
        Module[{data}, SelectionMove[source, Next, CellGroup]; 
          data = NotebookRead[source]; 
          If[data === {}, SelectionMove[source, Previous, CellGroup], 
            If[First[data] === "start demo", 
              If[p, SelectionMove[source, Next, CellGroup]; 
                data = NotebookRead[source], 
                NotebookFind[source, "end demo", Next]; 
                SelectionMove[source, Next, CellGroup]; 
                data = NotebookRead[source]]]; 
            If[First[data] === "end demo", 
              SelectionMove[source, Next, CellGroup]; 
              data = NotebookRead[source]]; 
            If[SameQ[Last[data], CellTags -> "notes"], 
              FrontEndExecute[{FrontEndToken[notes, "SelectAll"], 
                  FrontEndToken[source, "Copy"], 
                  FrontEndToken[notes, "Paste"], 
                  FrontEndToken[notes, "ScrollNotebookStart"]}]; 
              SelectionMove[source, Next, CellGroup]; 
              data = NotebookRead[source]]; 
            If[Last[data] === "Input", 
$EvaluationToggle = True; 
              SelectionMove[nb, After, Notebook]; 
              TypeInput[data[\([1]\)]], 
If[
                SameQ[Last[data], 
                  CellTags -> "evaluate"], \($Line--\); 
                FrontEndExecute[FrontEndToken[source, "EvaluateCells"]], 
                If[HeadingCell[data], 
                  FrontEndExecute[{FrontEndToken[source, "Copy"], 
                      FrontEndToken[nb, "SelectAll"], 
                      FrontEndToken[nb, "Paste"], 
                      FrontEndToken[nb, "ScrollNotebookStart"]}], 
                  SelectionMove[nb, After, Notebook]; 
                  NotebookWrite[nb, data]]]]]]]\)

SlideShow`NotesToggle := 
      SetOptions[notes,  
        Visible -> Not[TrueQ[Visible /. Options[notes]]]]

SlideShow`PreviousSlide := 
        Module[{data}, 
$EvaluationToggle = False; 
          While[SelectionMove[source, Previous, CellGroup]; 
            data = NotebookRead[source]; 
            Which[First[
                  data] === "end demo", 
NotebookFind[
                source, "start demo", Previous]; True, HeadingCell[data], 
              SelectionMove[source, Previous, Cell]; 
              SelectionMove[source, Before, Cell]; NextSlide[True]; False, 
              Last[data] === (CellTags -> "first"), 
              NextSlide[True]; False, True, True]]];

SlideShow`FirstSlide := ($EvaluationToggle = False; 
        NotebookFind[source, "first", All, CellTags]; 
        SetSelectedNotebook[notes]; 
        SetSelectedNotebook[nb]; 
FrontEndExecute[
          FrontEndToken[source, "EvaluateCells"]])

If[SlideShow`$ShowFirstSlide, SlideShow`$ShowFirstSlide = False; 
      SlideShow`FirstSlide]

SlideShow`SkipSlide := ($EvaluationToggle = False; 
        While[SelectionMove[source, Next, CellGroup]; 
          data = NotebookRead[source]; 
          Which[data === {}, SelectionMove[source, Previous, CellGroup]; 
            False, First[data] === "start demo", 
            NotebookFind[source, "end demo", Next]; True, 
            HeadingCell[data], SelectionMove[source, Previous, Cell]; 
            SelectionMove[source, Before, Cell]; 
NextSlide[
              True]; False, True, True]])

SetSelectedNotebook[nb]; End[]; $Line = 0;

$Line = 0; SlideShow`NextSlide[True];

This is a tour of calculations that you can do using Mathematica without doing any programming. This session covers much of the same material that is covered in the Tour of Mathematica section of The Mathematica Book, except for interface features, such as notebooks and typesetting, and programming features, all of which is covered in separate sessions.

Tour of Mathematica

Here is a list of topics for this session. I will not here be going through each of these topics and systematically describing all of the functionality in each area. What I will do instead in each area is comment on the available functionality and describe some of the general issues that will be relevant when you come to exploring those areas of the system.

Tour of Mathematica

The first topic is system organization. If you installed Mathematica yourself or if you examined your computer after installation you may have noticed that the installer put hundreds of files and programs and notebooks and other components on your computer. All of these components are organized around two main programs: the part that does the calculations, which we call the kernel, and the part that manages the interface, which we call the notebook interface, or the notebook front end.

Components of Mathematica

Here is a drawing of that organization. The part of Mathematica that manages what you see on the screen is the notebook interface, and the part of Mathematica that does the calculations is the kernel. Communication between the two programs is through MathLink. In a typical operating cycle you type something in to a notebook using the notebook interface, send your calculation over to the kernel, the kernel does the calculation, sends the result back, and the result gets displayed in the notebook.
Since the only part that you usually see is the notebook interface, you can in many cases ignore what is going on internally and think of Mathematica as one big program. In other cases, however, it is useful to know which part of the program is doing what.

\(\(Block[{inlevel, outlevel, fef, fe, kf, k, sh, s, pi, po, in, result, 
          as, ra, la, g}, 
        inlevel = 1.5; 
outlevel = 
          0.9; 
fef = 
          Line[{{0, 0.2}, {0, 2.2}, {3, 2.2}, {3, 0.2}, {0, 
                0.2}}]; 
fe = 
          Text[StyleForm["notebook interface", 
              FontFamily -> "Helvetica", 
              FontSize -> 14], {1.5, \(- .2\)}]; 
kf = 
          Circle[{5.6, 1.3}, {1.2, 1}]; 
k = 
          Text[StyleForm["kernel", FontFamily -> "Helvetica", 
              FontSize -> 14], {5.6, \(- .1\)}]; 
sh = 
          1.25; 
s = {Text[
              StyleForm["  2
+ 2

  4", 
FontFamily -> "Courier", FontSize -> 12, 
                FontWeight -> "Bold"], {5.8, sh}], {Thickness[
                0.004], 
              Line[{{5.55, sh - 0.15}, {6.03, 
                    sh - 0.15}}]}}; 
pi = 
          Text[StyleForm["In[1]:=", FontFamily -> "Helvetica", 
              FontColor -> RGBColor[0, 0, 1]], {0.6, 
              inlevel}]; 
po = 
          Text[StyleForm["Out[1]=", FontFamily -> "Helvetica", 
              FontColor -> RGBColor[0, 0, 1]], {0.6, 
              outlevel}]; 
in = 
          Text[StyleForm["2 + 2", 
              FontSize -> 12, FontFamily -> "Courier", 
              FontWeight -> "Bold"], {1.4, 
              inlevel}]; 
result = 
          Text[StyleForm["4", FontSize -> 12, 
              FontFamily -> "Courier"], {1.2, 
              outlevel}]; 
as = 
          0.14; 
ra = {Line[{{2.2, inlevel}, {5.1 - as, 
                  inlevel}}], 
            Polygon[{{5.1 - as, inlevel + as}, {5.1 + as, 
                  inlevel}, {5.1 - as, inlevel - as}}], 
            Text[StyleForm["input", FontFamily -> "Helvetica", 
                FontSize -> 12], {3.7, 
                inlevel + 0.25}]}; 
la = {Line[{{2.0 + as, 
                  outlevel}, {5.3, outlevel}}], 
            Polygon[{{2.0 + as, outlevel + as}, {2.0 - as, 
                  outlevel}, {2.0 + as, outlevel - as}}], 
            Text[
              StyleForm["result", FontFamily -> "Helvetica", 
                FontSize -> 12], {3.7, 
                outlevel + 0.25}]}; 
g = 
          Graphics[
            Rectangle[{0, 0}, {1, 1}, 
              Graphics[{Thickness[0.01], fe, fef, k, kf, Thickness[0.008], s, 
                  pi, po, in, result, ra, la}, AspectRatio -> 0.3]], 
            AspectRatio -> 0.3]; 
NotebookWrite[
          SlideShow`nb, 
          Cell[GraphicsData["PostScript", 
              DisplayString[g]]]]];\)\)

For example, the kernel and the notebook interface can run on different computers, in which case the file system that is available to each part of Mathematica is the file system that is available for a program running on that computer. If you are reading and writing data files with the kernel, those files would normally be files on the computer that is running the kernel, and if you are opening and closing notebooks, the notebook files would be the files on the computer the is running the notebook interface.

The kernel and the notebook interface can run on separate computers

The topic for the present session is primarily functionality of the kernel, although for many things the two are inseparable. When making a plot, for example, the kernel can do the calculations to construct the image but the interface is needed to display that image. Typesetting and notebooks are for the most part interface functionality, and will be discussed later.

This is a tour of kernel functionality

The first topic on the tour is symbolic calculations.

Tour of Mathematica

Here is a list of some of the symbolic functions in Mathematica. The functions that are probably the most widely recognizable are functions for calculus like Integrate and FourierTransform, and the functions for solving equations, like Solve. To better understand what you can expect from these functions, it is useful to know that essentially all of these functions are based at some level on polynomial operations, such as Factor, which factors polynomials, Apart, which does partial fraction decomposition, and Together, which collects things over a common denominator.

Symbolic operations

({{Integrate, Limit}, {D, Series}, {Derivative, Solve}, {DSolve, Simplify}, {Expand, Apart}, {Together, Factor}, {PolynomialGCD, Collect}, {FourierTransform, LaplaceTransform}, {GroebnerBasis, PolynomialReduce}})

If what you want to accomplish can somehow be broken down into basic polynomial operations then it can usually be done.

Polynomial operations

({{Expand, Apart}, {Together, Factor}, {FactorSquareFree, Resultant}, {Decompose, FactorList}, {PolynomialGCD, Collect}, {Coefficient, CoefficientList}, {GroebnerBasis, PolynomialReduce}})

For example, Expand is a basic polynomial operation.

Expand[(1+x+y)^3]

And Factor is a basic polynomial operation.

Factor[1+2x+x^2+2y+2x y+y^2]

Combining terms over a common denominator is a basic polynomial operation.

Together[1/(1+x)+y/(1+x)^2]

Partial fraction decomposition is a basic polynomial operation. The Apart function does partial fraction decomposition. You can use the Apart function with one argument, but I wouldn't recommend that, since the second argument specifies the variable with respect to which to do the partial fraction decomposition, and if you omit the second variable then Apart will just pick something, and that may not be the variable that you want.

Apart[(1+x+y)/(1+x)^2,x]

Another basic operation is picking out coefficients of a polynomial. Here is an example using CoefficientList to pick out the coefficients of powers of x in this polynomial.

CoefficientList[b x^2+x y +(1+x)^3,x]

Even if you are not interested directly in polynomial operations, it is still useful to know about the internal importance of polynomials, since this will help you to anticipate what you can or cannot expect from symbolic calculations, and perhaps design your calculations to take advantage of the strengths of computer algebra. I have several illustrations of that, the first being a discussion of how Solve works.

Solve

The basic Solve algorithm handles polynomials

Here is a simple Solve example. To understand what Solve did, you can think about how you might solve these equations by hand. The process basically involves three steps. The first step would be to eliminate variables between these equations to get an equation in one variable, the next step is to find the roots of that equation, and the last step is to back-substitute those roots into the remaining equations.

Solve[{x==y,x^2+y^2==2},{x,y}]

Although it is perhaps not essential to know this, the underlying algorithm that Solve uses to do the first step, combining the equations to get an equation in on variable, is called construction of a GroebnerBasis.

GroebnerBasis[{x-y,x^2+y^2-2},{x,y}]

Then the second step is root extraction, for which the Solve function calls another function called Roots, and then substitute those roots into the original equation.

Roots[-1+y^2==0,y]

Non-polynomial equations are solved by converting them to polynomial equations.

Solving non-polynomial equations

Non-polynomial equations are solved by converting them to polynomial equations.

For example, this equation is solved by recognizing that although it isn't a polynomial in x, it is a polynomial in Cos[x], then solving for Cos[x] using the polynomial equation solver, and taking the arccosine of those solutions to get values of x.
This example illustrates one issue that comes up when solving non-polynomial equations, which is that, as indicated by the warning message, Solve will not necessarily find all of the solutions.  In this example, since Cos[x] is periodic, if x is a solution then so is x+2nPi, where n is any integer, so this equation has an infinite number of solutions.  Solve isn't equipped to return an infinite number of solutions, and so generates this warning message to indicate that it may have missed some of the solutions.

Solve[Cos[x]^2==b,x]

Another effect is illustrated by this example, where, since the Sqrt function in Mathematica is defined to be the positive square root, this result is not technically correct, since if b is negative this equation has no solution.

Solve[Sqrt[x]==b,x]

If the symbolic parameter b is replaced by a negative number, then Solve correctly reports that there is no solution.

Solve[Sqrt[x]==-2,x]

Thinking about how Solve came up with this solution, it might seem that there should have been a solution. Solve solves Sqrt[x]==-2 by squaring both sides of the equation to get a polynomial equation, which in this case gives x==4, so one might wonder what happened to that solution. In fact Solve came up with this solution and rejected it, because although this solution solves the polynomial equation, it does not solve the original equation. Solutions that are introduced like this in the process of converting a non-polynomial equation into a polynomial equation are called parasitic solutions. Parasitic solutions are rejected by the solution verifier in Solve.  If you for some reason want to see these parasitic solutions, you can turn the solution verifier off using the option VerifySolutions->False.

Solve[Sqrt[x]==-2,x,VerifySolutions->False]

Non-polynomial equations are solved by converting them to polynomial equations.

Solve for large examples

Simple examples sometimes have large solutions.

To illustrate that, here is an example of a pair of equations that has a solution that goes on for several pages.

Solve[{x^3+x==y,y^2==y+1},{x,y}]

If I use really small characters I can get this result to fit mostly on the screen, but this is just a simple pair of equations. If there were more equations or higher-order polynomials, the calculation could overwhelm the computational resources of any realistic computer, or take an unrealistically large amount of time, even for a calculation like this that is conceptually straightforward.

SelectionMove[SlideShow`nb, Previous, Cell]; 
    SetOptions[NotebookSelection[SlideShow`nb], 
      Magnification -> 0.5]

In summary, some suggestions when working with Solve are to first try to get your calculation into a system of polynomial equations. If that doesn't work, or if it is difficult, keep in mind that issues like parasitic solutions and not finding all solutions can come up for non-polynomial equations. Even if you have polynomial equations, computing symbolic solutions can require more time and computer memory than you have available, and finally, for really large problems unless you absolutely need a symbolic solution it is reasonable to look for ways to get what you want by computing solutions numerically.

Suggestions for using Solve

Another prominent topic in symbolic computation can broadly be described as "simplification", which transforming expressions into any more convenient form. The obvious problem is that simple in one situation or for one person may not be the same thing as simple in another situation or for someone else. A consequence of this ambiguity is that some simplifications are easy and some simplifications are not so easy.

Simplification

"Simple" has different meanings in different situations

As an example, here is an expression involving trigonometric functions. There are of course an infinite number of forms in which one might imagine writing this expression.

expr=Cos[x]^2+3Cos[x]^2Sin[x]-Sin[x]^2-Sin[x]^3

For example, one very convenient form for many purposes is to write this expression as complex exponentials. This is convenient for operations such as symbolic integration, since the integral is then nearly trivial. This transformation is done by a function called TrigToExp. So this one possible meaning for "simple".

TrigToExp[expr]

If I want to retain trigonometric functions there are many other possibilities. For example, there is a function called TrigReduce that will make this considerably shorter.

TrigReduce[expr]

There are perhaps a hundred functions that you might consider for transforming this expression into something that might arguably be considered simpler, or at least more convenient. In many cases, however, you just want the expression to be smaller and don't want to have to dig through hundreds of functions to find a function that will do it. One function that is intended for such occasions is Simplify, which works by applying a collection of transformations and returning the expression that it thinks is simplest.

Simplify[expr]

FullSimplify works the same way except that it applies even more transformations, and here gets the same result that TrigReduce got. Of course, TrigReduce was a lot faster, since it went straight to TrigReduce, while FullSimplify tried hundreds or probably thousands of other transformations before it found something equivalent to TrigReduce,

FullSimplify[expr]

Many simplifying transformations only apply for certain values of the variables.

Simplification with assumptions

The second argument of Simplify or FullSimplify can include assumptions about parameters.

For example, here is an expression that might come up and that obviously can be simplified if x is positive and n is an integer.

expr=Sqrt[x^2]+Sin[2n π+x]

The assumption that x is positive can be included by inserting x>0 as the second argument in Simplify.

Simplify[expr,x>0]

The assumption that n is an integer can be inserted by including Element[n,Integers] as the second argument in Simplify.

Simplify[expr,Element[n,Integers]]

The Element[n,Integers] assumption can be inserted in more traditional notation by entering the ∈ character. This character is in the BasicInput palette, or you can enter it using the alias elem, or there are other ways to enter it that will be discussed when we get to the section on typesetting.

Simplify[expr,n∈Integers]

Both assumptions can be entered by including them in a list.

Simplify[expr,{x>0,n∈Integers}]

Or both assumptions can be included using && between the assumptions, which is the notation for the logical And function. I usually prefer the && notation because I like the aesthetics of it, but it doesn't make any difference.

Simplify[expr,x>0&&n∈Integers]

Clear expr before moving on.

Clear[expr]

Continuing on the subject of simplification I would like to make a few remarks about controlling the form of results.

Controlling the form of results

As an illustration, here is a integral which is computed and gives the result in terms of a logarithm. This result is mathematically correct for all values of x, but, for example, if the parameter b is bigger than x, then this logarithm is complex, so I might want to get this result as Log[b-x] rather than Log[-b+x]. These results differ by a constant of integration, so both results are correct.

result=Integrate[1/(x-b),x]

Simplify by itself will not do this, because the result is already simple, and Simplify finds no reason to change it.

Simplify[result,b>x]

Another function to consider in this situation is ComplexExpand, which will break this expression up into real and imaginary parts.

ComplexExpand[result]

You can combine transformations now to get a result which may be useful, since it does contain the result Log[b-x] that we want, and the rest is obviously a constant and can be considered as the constant of integration.

Simplify[ComplexExpand[result],b>x]

Another way to get this result is to tell Simplify not to use its default notion of what is simple but to instead program your own definition of "simple". You can program your own definition of "simple" and pass that definition to Simplify using the ComplexityFunction option. This definition says that the simpleness of an expression p is the number of leaves in the expression plus 100 multiplied by the number of times that -b+x occurs.  This is a programmatic way of instructing Simplify to do whatever it has to do to get rid of -b+x.

MyDefinitionOfSimple[p_]:=LeafCount[p]+100Count[p,-b+x]

This will get a result with Log[b-x] plus a constant, which is about as close as we can realistically get to the original objective, which was to just get Log[b-x] as the result.

Simplify[result,b>x,ComplexityFunction->MyDefinitionOfSimple]

Clear result before moving on.

Clear[result]

Some conclusions about getting symbolic results into particular forms:
Getting results into a particular form is straightforward if the form that you want corresponds to a form generated by a standard function, especially a standard polynomial operation, such as full expanded or fully factors.  Conversely, getting a result into any other form can be very difficult, and perhaps not worth the effort.
Second, Simplify and FullSimplify are among the few functions in the current version of Mathematica that take assumptions about parameters, which can be very useful.
And finally, although Simplify and FullSimplify are wonderful functions, keep in mind that these functions work by applying a long list of transformations and using the simplest result, and that process can be very time consuming and can use a lot of memory if some of those transformations are time-consuming or use a lot of memory.

Suggestions about simplification

Another important area of symbolic computation is symbolic calculus. Here are some of the functions that are included with Mathematica for symbolic calculus. In most cases these functions pretty much do what you would expect them to do, and you can just look them up in the documentation and type in your example.

Symbolic calculus

({{D, Derivative}, {Integrate, FourierTransform}, {Series, LaplaceTransform}, {Limit, ZTransform}, {DSolve, DiracDelta}})

For example, here is an input that computes a symbolic derivative using the D function.

D[x Cos[x],x]

For functions that are unknown or that are not differentiable like Abs[x] the result is represented using Derivative, which is formatted with the prime notation that you see here.

D[Abs[x],x]

You can see Derivative more explicitly by using FullForm, which tells Mathematica not to use any special notations in displaying the result. This is the notation that you would use if you wanted to enter your Mathematica inputs using nothing but letters, numbers, commas, and square brackets. This means the first derivative of a function Abs with respect to its first argument and evaluated at x.

FullForm[D[Abs[x],x]]

Here is an integral. Notice that this particular result does not exclude the possibility that b is minus one. The Integrate function is designed like the Solve function and most other functions in Mathematica to assume generic values of the parameters, and usually does not check for values that might be pathological.

Integrate[x^b,x]

Here is an example where Solve does something similar. This result does not allow for the possibility that b might be zero.

Solve[b x==1,x]

Some definite integrations will, however, report inequality assumptions about parameters. Here is a definite integral where the result is returned using an If expression.

Integrate[Exp[-b x],{x,0,Infinity}]

Definite integration is another operation like Simplify and FullSimplify that allows you to specify assumptions about parameters, except that in Integrate this is done using an option.

Integrate[Exp[-b x],{x,0,Infinity},Assumptions->(b>0)]

There are many other symbolic calculations that you can do using Mathematica. Whether or not Mathematica will be able to do a calculation you want to do usually depends on whether or not there is an algorithm to do it. Getting results into a particular form is an example of something that is very difficult to do because there isn't an algorithm to do it. There are many functions, however, where there are algorithms even though those algorithms may not be widely known.

Other symbolic algebra

The existence of a function or package to do something depends mostly on whether or not there is a general computer algorithm to do it.

For example, there is an algorithm for solving certain classes of recursion relations. To get the functions that do that it is necessary to load a package. This is the notation for loading a package called DiscreteMath RSolve. There will be a separate discussion later about what a package is and about this notation and what it means to load a package.

<<DiscreteMath`RSolve`

This defines a function RSolve which can be used to solve recursion relations like the one shown in this example. The result is returned as a list of rules, like the result from Solve.

RSolve[{b x[n]==x[n-1]+1,x[0]==a},x[n],n]

Another interesting package is that InequalitySolve package which defines functions for solving inequalities. Again, it turns out that there is an algorithm to do this type of calculation.

<<Algebra`InequalitySolve`

Here is an example showing the use of the InequalitySolve function.

InequalitySolve[Abs[x^2+1]>3,x]

The next topic is linear algebra, which was mentioned earlier. Most of what I want to say about linear algebra here has to do with symbolic linear algebra.

Tour of Mathematica

Vectors and matrices can be constructed using Table and Array.

Constructing matrices

For example, this input generates a 3 by 3 matrix of random numbers.

Table[Random[],{3},{3}]

The functionality of Array can be seen in a simple example. This input constructs a matrix in which the elements are of the form b[i,j].

Array[b,{3,3}]

This same result can also be constructed using Table.

Table[b[i,j],{i,1,3},{j,1,3}]

Here are some of the functions that are available for working with matrices in Mathematica. This is the same list as was shown in the introduction segment.

Matrix functions

({{Eigenvalues, Eigenvectors}, {Eigensystem, SchurDecomposition}, {LinearSolve, QRDecomposition}, {Det, CholeskyDecomposition}, {MatrixExp, LUDecomposition}, {MatrixPower, LUBackSubstitution}, {Tr, SingularValues}, {Transpose, JordanDecomposition}, {Inverse, PseudoInverse}})

Most of the functions that operate on matrices in Mathematica work for symbolic matrices as well as for numerical matrices. Symbolic results are often convenient, but symbolic matrix computations can require a large amount of time and memory.

Symbolic linear algebra

Symbolic results are often convenient, but can be computationally demanding.

To illustrate that, here is an input that constructs a general 2 by 2 matrix and computes the inverse of that matrix.

Inverse[Array[b,{2,2}]]

This does the same calculation for a general 3 by 3 symbolic matrix.

Inverse[Array[b,{3,3}]]

Since I am not really interested here in the actual result, but only in the size of the result, I can used ByteCount to estimate the number of bytes used to store the expression.

ByteCount[Inverse[Array[b,{3,3}]]]

Here is that result for a 4 by 4 matrix.

ByteCount[Inverse[Array[b,{4,4}]]]

Here is that result for a 5 by 5 matrix.

ByteCount[Inverse[Array[b,{5,5}]]]

Here is a useful and very general technique for estimating the amount of memory that might be required to store the result for the inverse of a large matrix. This input uses the Table function to generate a list of results, and each result give the size of the matrix and uses the ByteCount function to show the amount of memory used to store the inverse. By studying this result we can see that the memory requirement grows by about a factor of 10 for each step in the size of the matrix, and that the inverse of a general 6 by 6 matrix already uses about ten megabytes of memory.
From this result one can correctly conclude that the practical limit to general operations on symbolic matrices is matrices with dimension about 6 by 6, which is not a very big matrix in practical calculations, where people routinely need to work with matrices more like a thousand by a thousand with a million elements.

Table[{k,ByteCount[Inverse[Array[b,{k,k}]]]},{k,6}]

Another important topic that I will mention just briefly so that you will know that the functions are there are functions for discrete Fourier transform using the FFT algorithm. The functions are Fourier and InverseFourier.

Discrete Fourier transforms

({{Fourier}, {InverseFourier}})

Here is an example showing Fourier to compute the discrete Fourier transform of a list of real numbers.

ft=Fourier[{1.7,2.3,5.8,2.5,1.0}]

And here is the corresponding inverse discrete Fourier transform which returns the original list, or more generally, since this is a numerical operation with inexact numbers, it will return the original list to within numerical error.

InverseFourier[ft]

Having explained that symbolic linear algebra is sometimes impractical except for relatively small matrices, the obvious question is what to do about that. One solution of course is to use numerical methods.

Tour of Mathematica

To quantify the comparison of symbolic and numerical calculations, here is an example comparing time and memory requirements for symbolic and numerical matrix inverse.

Numeric and symbolic matrices

First time and get the memory requirement using the Timing and ByteCount functions for the inverse of a 270 by 270 random matrix.

Timing[ByteCount[Inverse[Table[Random[],{270},{270}]]]]

Roughly the same amount of time and about 20 times as much memory is used for computing the inverse of a 6 by 6 matrix. It is not uncommon to be able to do a numerical computation millions of times over with less time and memory than is required to do a symbolic computation once. Symbolic linear algebra is still useful, but time and memory requirements are the main limitations.

Timing[ByteCount[Inverse[Array[b,{6,6}]]]]

What I would mainly like to discuss under numerical computation is not numerical linear algebra but numerical operations on functions. Many symbolic functions have numerical counterparts.  The ND function is used for numerical differentiation, the NIntegrate function is used for numerical integration, and so forth.

Numerical operations

({{ND, NIntegrate}, {NLimit, FindRoot}, {FindMinimum, NDSolve}, {NSum, NProduct}})

Here for example is a numerical integral using NIntegrate, which uses the same syntax as the corresponding symbolic integral using Integrate.

NIntegrate[Exp[-x Cos[x]],{x,0,10}]

Numerical root finding can be done using the FindRoot function.

Numerical solutions of equations

FindRoot

The result is returned as a list of rules.

solution=FindRoot[Exp[x]==4 Sin[x],{x,0}]

You can pick out the value of x by applying the solution as a replacement to x.

x/.solution

If you want to assign this result as the value of something, you can put this replacement operation on the right side of an assignment. This input assigns the value of x at the solution as the value of a variable xval.

xval=x/.solution

You can even assign this value as the value of x, although that would lead to obvious problems if you later try to use x as a variable again.

x=x/.solution

For example, the solution here is a rather peculiar replacement rule. The FindRoot function used a different starting value for x, and so converged to a different root. The assigned value of x was inserted on the left side of the rule.

FindRoot[Exp[x]==4 Sin[x],{x,1}]

To avoid similar problems like this, I will clear x before moving on.

Clear[x,xval]

Numerical minimization can be done using a function called FindMinimum.

Minimization

FindMinimum

Here is an example showing the use of FindMinimum. The result is a list that gives the value of the function at the minimum and a list of rules giving the values of the variables at that minimum.

FindMinimum[Sin[x] Cos[y],{x,1},{y,1}]

Numerical approximation can be done using the NSum function, and numerical products can be computed using NProduct.

Numerical sums and products

({{NSum}, {NProduct}})

Here is an example showing a use of NSum to do an infinite sum.

NSum[Exp[-n],{n,0,Infinity}]

This sum can also be evaluated symbolically, since it is just a simple geometric sum.

expr=Sum[Exp[-n],{n,0,Infinity}]

The symbolic and numeric results can be compared by computing a numerical approximation for the exact result using the N function.

N[expr]

Clear expr before moving on.

Clear[expr]

You can also do linear programming in Mathematica, which means constrained minimization of a linear function subject to linear constraints. There is a well-known algorithm called a simplex algorithm for solving this problem, which is implemented in Mathematica in the functions ConstrainedMin, ConstrainedMax, and LinearProgramming, all of which access exactly the same internal algorithm.
There is not a built-in function in Mathematica for constrained nonlinear optimization. There are third-party packages that will do this.

Linear programming

({{ConstrainedMin}, {ConstrainedMax}, {LinearProgramming}})

Here is an example showing the use of ConstrainedMin. The first argument is the linear function to minimize, the second argument gives the linear constraints in terms of inequalities, and the last argument is a list of the variables. All of these inputs can also be specified as coefficient matrices. The LinearProgramming function takes coefficient matrices instead of functions and inequalities with the variables given explicitly, but otherwise does the same calculation.

ConstrainedMin[x + y - 3 z, 
  {x < y, 2 z < 3 x, x < 4}, 
  {x, y, z}]

The most elaborate numerical function in Mathematica is NDSolve, which is the function that constructs numerical solution of differential equations. The NDSolve function can do initial value problems, some boundary value problems, and partial differential equations in 2 variables, (or 1+1 variables).

Differential equations

NDSolve provides solvers for

Here is an example showing the use of NDSolve to solve an initial value problem. You may recognize this pair of differential equations as a simple harmonic oscillator.

NDSolve example

The first argument is a list of equations giving the differential equations and the initial values. Here there are two differential equations and two initial values. Derivatives are entered using prime notation, so, for example, f'[x] denotes the first derivative of a function f. The second argument lists the two functions to solve for, and the last argument is a list giving the independent variable and the range of the independent variable. The result, as with the result from Solve, is a list of solutions and each solution is a list of rules.  The right side of each rule is an InterpolatingFunction expression that represents the solution. In this example there is only one solution, and that solution involves rules for the two functions f and g.

sol = NDSolve[
   {f'[x] + g[x] == 0, 
    g'[x] == f[x], f[0] == 0, 
    g[0] == 1}, {f, g}, 
   {x, 0, 10}]

This result can be used much like the results from Solve, except that now the solutions are functions rather than numbers or simple expressions. For example, this input gives the value of f[5].

f[5]/.sol

That result is a list containing a number rather than a number because I applied all of the solutions to f[5], rather than the first (and only) solution. This picks out just the one solution, so the result is a number.

f[5]/.sol[[1]]

This plots the solution function f.

Plot[f[x]/.sol[[1]],{x,0,10}]

This plots both f and g. If you interpret this as describing a simple harmonic oscillatory, then f could be the position and g could be the velocity.

Plot[{f[x]/.sol[[1]],g[x]/.sol[[1]]},{x,0,10}]

That is the end of the mathematical part of the tour. The next topic is graphics.

Tour of Mathematica

We saw this list of plotting functions earlier in the introduction.

Plotting

({{Plot, Plot3D}, {ContourPlot, DensityPlot}, {ParametricPlot, ParametricPlot3D}, {LogPlot, LogLinearPlot}, {LogLogPlot, PolarPlot}})

Here is a contour plot, using syntax which follows the same pattern as related functions. The point I wanted to add here is that plotting functions are essentially numerical functions. ContourPlot works by evaluating the function on a 15 by 15 grid and then drawing contours as best as it can through those points. Most of the jaggedness that you see in this plot comes from the fact that the underlying grid is actually fairly course.  There are features of this function that change on a scale smaller than you get from a 15 by 15 grid.

SetOptions[ContourPlot, ImageSize -> {150, 150}]; 
    SlideShow`NextSlide[True];

ContourPlot[Sin[x y],{x,0,4},{y,0,4}]

The number of grid points is controlled by the value of the PlotPoints option. The default value is 15.

Options[ContourPlot,PlotPoints]

Here is a plot of the same function but with a higher resolution.

SetOptions[ContourPlot, ImageSize -> {150, 150}]; 
    SlideShow`NextSlide[True];

ContourPlot[Sin[x y],{x,0,4},{y,0,4},PlotPoints->50]

The other point I wanted to add here about plotting and graphics is that, to construct a plot, after starting with data or computed points on a function, the graphics expression is constructed from graphics primitives, graphics directives, and graphics options.

Graphics expressions

Graphics expressions are constructed from graphics primitives, graphics directives, and graphics options.

To illustrate how all of these things work together, here is a typical graphics expression, which has a head of Graphics, a Line primitive that draws one line, a Thickness directive to make all subsequent lines thicker, another Line primitive, and finally the option Axes->True to draw axes on the plot.

Graphics[{Line[{{0, 0}, {2, 2}}], Thickness[0.025], 
        Line[{{0, 1}, {2, 1}}]}, Axes -> True]

The Show function can be used to generate an image corresponding to this graphics expression. This same structure is used for all graphical output in Mathematica. The output is a Graphics expressions which displays as dash Graphics dash, but that is just the display form.

SelectionMove[SlideShow`source, Next, Cell]; 
    FrontEndExecute[{FrontEndToken[SlideShow`source, "Copy"], 
        FrontEndToken[SlideShow`nb, "Paste"]}]; 
    SelectionMove[SlideShow`nb, Previous, Cell];

Show[
      Graphics[{Line[{{0, 0}, {2, 2}}], Thickness[0.025], 
          Line[{{0, 1}, {2, 1}}]}, Axes -> True]]

FrontEndExecute[FrontEndToken[SlideShow`nb, "EvaluateCells"]]; 
    SelectionMove[SlideShow`source, Next, Cell]; 
    FrontEndExecute[
      FrontEndToken[SlideShow`source, "EvaluateCells"]]

Do[FrontEndExecute[
        FrontEndToken[SlideShow`nb, "ScrollLineUp"]], {3}]

Here first are some graphics primitives.Graphics primitives are expressions based on Line or Point or Polygon that generates geometric elements of the plot.

Graphics primitives

({{Line, Circle, Cuboid}, {Point, Text, Rectangle}, {Polygon, Disk, Raster}, {RasterArray, PostScript, Text}})

Graphics directives are expressions based on items from this list, that specify the color of lines or points or polygons, the size of points, the thickness of lines, and so forth.

Graphics directives

({{GrayLevel, CMYKColor}, {Hue, Thickness}, {RGBColor, PointSize}, {SurfaceColor, FaceForm}, {EdgeForm, StyleForm}, {Dashing, AbsoluteThickness}, {AbsoluteDashing, AbsolutePointSize}})

Graphics options control a variety of characteristics of the plotting process. Some of graphics options we've already seen. Here are some frequently-used graphics options.

Graphics options

({{PlotPoints, PlotJoined}, {PlotStyle, Ticks}, {Axes, AxesLabel}, {Frame, FrameLabel}, {GridLines, PlotRange}, {DefaultFont, Epilog}})

There are a variety of situations in which you might want to construct graphics expressions or parts of graphics expressions directly.

Drawing

The illustrating from the beginning of this presentation was constructed using Mathematica. Constructing a drawing like this, although possible, can be fairly time-consuming. Future versions of Mathematica are expected to include more sophisticated features for interactive graphics.

\(\(Block[{inlevel, outlevel, fef, fe, kf, k, sh, s, pi, po, in, result, 
          as, ra, la, g}, 
        inlevel = 1.5; 
outlevel = 
          0.9; 
fef = 
          Line[{{0, 0.2}, {0, 2.2}, {3, 2.2}, {3, 0.2}, {0, 
                0.2}}]; 
fe = 
          Text[StyleForm["notebook interface", 
              FontFamily -> "Helvetica", 
              FontSize -> 14], {1.5, \(- .2\)}]; 
kf = 
          Circle[{5.6, 1.3}, {1.2, 1}]; 
k = 
          Text[StyleForm["kernel", FontFamily -> "Helvetica", 
              FontSize -> 14], {5.6, \(- .1\)}]; 
sh = 
          1.25; 
s = {Text[
              StyleForm["  2
+ 2

  4", 
FontFamily -> "Courier", FontSize -> 12, 
                FontWeight -> "Bold"], {5.8, sh}], {Thickness[
                0.004], 
              Line[{{5.55, sh - 0.15}, {6.03, 
                    sh - 0.15}}]}}; 
pi = 
          Text[StyleForm["In[1]:=", FontFamily -> "Helvetica", 
              FontColor -> RGBColor[0, 0, 1]], {0.6, 
              inlevel}]; 
po = 
          Text[StyleForm["Out[1]=", FontFamily -> "Helvetica", 
              FontColor -> RGBColor[0, 0, 1]], {0.6, 
              outlevel}]; 
in = 
          Text[StyleForm["2 + 2", 
              FontSize -> 12, FontFamily -> "Courier", 
              FontWeight -> "Bold"], {1.4, 
              inlevel}]; 
result = 
          Text[StyleForm["4", FontSize -> 12, 
              FontFamily -> "Courier"], {1.2, 
              outlevel}]; 
as = 
          0.14; 
ra = {Line[{{2.2, inlevel}, {5.1 - as, 
                  inlevel}}], 
            Polygon[{{5.1 - as, inlevel + as}, {5.1 + as, 
                  inlevel}, {5.1 - as, inlevel - as}}], 
            Text[StyleForm["input", FontFamily -> "Helvetica", 
                FontSize -> 12], {3.7, 
                inlevel + 0.25}]}; 
la = {Line[{{2.0 + as, 
                  outlevel}, {5.3, outlevel}}], 
            Polygon[{{2.0 + as, outlevel + as}, {2.0 - as, 
                  outlevel}, {2.0 + as, outlevel - as}}], 
            Text[
              StyleForm["result", FontFamily -> "Helvetica", 
                FontSize -> 12], {3.7, 
                outlevel + 0.25}]}; 
g = 
          Graphics[
            Rectangle[{0, 0}, {1, 1}, 
              Graphics[{Thickness[0.01], fe, fef, k, kf, Thickness[0.008], s, 
                  pi, po, in, result, ra, la}, AspectRatio -> 0.3]], 
            AspectRatio -> 0.3]; 
NotebookWrite[
          SlideShow`nb, 
          Cell[GraphicsData["PostScript", 
              DisplayString[g]]]]];\)\)

Mathematica is an ideal system, however, for generating images that originate with data, or for images that are generated by computation. See the Graphics Gallery in The Mathematica Book for examples.

HelpBrowserLookup["MainBook", "G.2.19"]

HelpBrowserLookup["MainBook", "G.2.29"]

SetSelectedNotebook[SlideShow`notes]; 
    SetSelectedNotebook[SlideShow`nb];

The next topic on this tour is a discussion of external files, such as will be of interest if you want to read data files in to Mathematica or write data out from Mathematica. The central comment I wanted to make here is the relationship between this functionality and the next topic, which is MathLink.

Tour of Mathematica

Here are some of the functions that are available for reading and writing data and formatted files in Mathematica. The most general functions for reading and writing data, which can in principle be used to read or write any file format, are the first few functions on this list, like OpenWrite, which opens a file for writing, Write and WriteString, which writes information to that file, Read, which reads data elements from a file, and so forth.

External files

({{OpenWrite, OpenAppend}, {OpenRead, Read}, {ReadList, Write}, {WriteString, Display}, {Put, Save}, {PutAppend, Get}, {Import, Export}, {TeXSave, HTMLSave}})

Here is a typical example of writing a number to a file and reading the number back in to Mathematica. First, open the file for writing. OpenWrite opens a stream to the file.

s=OpenWrite["file"]

This writes a number to that stream.

Write[s,123.456]

This closes the stream.

Close[s]

This opens the stream to the file for reading.

s=OpenRead["file"]

This reads a number from the stream.

Read[s,Number]

This closes the stream to the file. This general strategy of opening, writing or reading, and closing files can be used with strings, numbers, Mathematica expressions, binary data, or any other file elements. The most difficult issue in many cases is getting a specification of the file format.

Close[s]

Working out how to read and write particular file formats can be laborious, which is why the functions Import and Export are included. These functions are already programmed to handle many common file formats.

Special file formats

({{Import, Export}, {TeXSave, HTMLSave}})

Here is a list of the file formats that can be imported using Import in this version of Mathematica.

$ImportFormats

And here is a list of the formats that can be exported. Included in these lists are graphics and image formats that would be difficult to read and write using lower-level functions.

$ExportFormats

Finally, here are a few comments about MathLink, to illustrate the type of thing that you can do and roughly what is involved with using it, and to relate back to these functions for reading and writing files.

Tour of Mathematica

To illustrate a bit of how MathLink works, I will here demonstrate setting up a link to an external program that has already been compiled as one of the examples that is included with Mathematica.

MathLink example

This input tries to open a link to a program called "addtwo", which is already compiled on this computer. The exact way that Mathematica finds the link works differently on different computers. On this computer, since this program isn't in the default path to look for programs to link, the computer asks me to find the file.

link=Install["addtwo"]

This introduces a function called AddTwo that adds two numbers.

?AddTwo

For example.

AddTwo[4,7]

The interesting part is to notice how this works. This function is calling an external compiled program to do the addition. You can see the rule that is invoked by using a double question mark, which works like the single question mark notation, except it reveals more information. Notice here that the definition of AddTwo involves functions like ExternalCall that perform the actions of writing arguments to the external program and reading the result from that program back in to Mathematica.

??AddTwo

An instructive way to demonstrate a bit more of what is going on here is to read and write information directly, rather than by calling the AddTwo function. To write information to the link to the external program, I use a function called LinkWrite. The CallPacket function is there because this particular external program was set up using a general mechanism that you can read about in the online MathLink tutorial to take CallPacket expressions that contain the function arguments rather than just the function arguments 4 and 7. This is useful if the external program involves more than one function. The CallPacket expression tells the external program to which function the arguments should be passed. This particular external program only defines one function, so the CallPacket is unnecessary overhead included for the purpose of the example.

LinkWrite[link,CallPacket[0,{4,7}]]

Having written the function arguments to the link I can read the result back from the link using LinkRead.

LinkRead[link]

I can repeat that operation with different arguments.

LinkWrite[link,CallPacket[0,{1000,25}]]

and get another result.

LinkRead[link]

When I am finished with the external program, I can close the link and shut down the external program using LinkClose

LinkClose[link]

To set up a MathLink connection to an external program you typically need three things. The first is Mathematica and MathLink which is easy if you have Mathematica, because MathLink is included with Mathematica. The second is a C-language interface to the other program. If you want to connect to a spreadsheet program, for example, you would need to figure out the C-language interface to that other program -- that is, how the other program communicates with C programs. The third is a C compiler, and knowledge of how to use it. This isn't needed if the program to which you want to connect is already set up, as in my example, but it is needed otherwise.
In the overwhelming majority of cases, the most difficult items are the second two, which do not relate directly to Mathematica. The need take the time to figure out MathLink and a C-language interface to another program and a C compiler, even though all of those things may be simple, so probably the biggest obstacle to writing MathLink programs.

Setting up MathLink connections

And finally I wanted to relate this back to the earlier topic of reading and writing files. You can exchange information with other programs using MathLink or through files. Some people have wondered, for example, if they absolutely need MathLink in order to get data from an spreadsheet or database in to Mathematica, and the answer is no. If you want to exchange information on the fly or if you want other conveniences of a direct connection, then MathLink is useful, but you can still write data to a file from Mathematica and read it in to the other program, or write data from the other program in to Mathematica, without using MathLink.

Communication with external programs