Mathematica-Speak: Scalars and Vectors and Matrices, oh my! 11 July 2014 If this is your first time using Mathematica, see the tutorial at http://www.wolfram.com/broadcast/screencasts/handsonstart/ For an excellent set of pointers, see http://www.bandgap.cs.rice.edu/personal/adrice_swong/public/WebPages/mathematica/MathTips.htm There is also some useful stuff in the tutorial http://www.math.duke.edu/education/ccp/materials/linalg/mmatutor/contents.html In all of the following, text in this weird font indicates a Mathematica function or statement. If you are completely unsure of your Mathematica skills, work through the following in detail and ask for help! A Mathematica notebook (.nb file) consists of as many ‘cells’ as you want. Cells are containers for input and output, denoted by the ever-growing lines along the right-hand margin of the screen. When you type some stuff and hit Enter, you are just adding lines to the same cell. When you hit Shift-Enter, you’ll (most likely) see some output and be put into a new cell. Or you can insert new cells just be hitting Enter in between two existing cells. BTW, the Shift-Enter key combination is known as ‘Execute.’ You should quickly learn how to organize what you’ve done and how to do things more quickly and efficiently (although some students go most of the semester without realizing they don’t have to retype everything each time). For example, you should never have to cut and paste a number from one cell to another; access your outputs by storing them as named variables (hint: don’t name all your variables ‘x’). Sadly, no prizes for clever variable names (although I am partial to ‘exx,’ ‘wye’ and ‘zee’). Scalars OK, so these are just numbers. However, a scalar variable need not have a value. Setting s=2 and executing 5 s gives 10; executing 5 s t will get you 10 t (unless you forget to put a space between the s and t, because Mathematica happily thinks st is a new variable name which doesn’t have a value. Like all good computer programs, Mathematica remembers values associated with variables for a long time. This can lead to frustrating results, particularly after a long late night session, when you forgot that you did y = x + 1 early on and then can’t remember why y has some value that now makes no sense. The Clear[ ] function is a useful one to use from time to time. Vectors Mathematica considers a vector to be a list vee ={1,2,3,4,5,6,7,8,9,10}, defined as the comma-separated stuff inside the list brackets { }. The list’s components can be numbers, variables or even expressions (the list powersofx = {1, x, x2, x3} is valid – and very useful). There is no internal distinction between what we normally think of as a “row” or “column” vector; Mathematica thinks a vector is just a list and the default form of display is the row as shown. Referring to the list’s given name returns the entire vector. The usual vector addition is indicated by the symbol "+" and scalar multiplication (scalar times vector = vector) is shown with an asterisk or a space. Mathematica happily multiplies all components of a vector by the scalar in one shot: if s is a scalar and vee = {v1, v2, v3, v4}, s vee yields the vector with values {s v1, s v2, s v3, s v4}. Maybe that’s why s is known as a scalar. Note that Mathematica is maddeningly literal: if you typed svee, it thinks you’ve referred to a new variable, not the product of scalar s and vector vee. Spaces have meaning, in more ways than one. When you are ready to multiply two vectors, use a dot: ewe.vee or Dot[ewe,vee] is the correct vector (dot) product. If you type ewe vee, you get back a vector consisting of the first element of ewe multiplied by the first element of vee, etc; that is most definitely not the same as Dot[ewe,vee]. Does Dot[ewe, vee] always equal Dot[vee, ewe]? There are several built-in functions to help you create vectors, with Range[ ] and Table[ ] being the most useful (learning how to use them saves a lot of typing). As an example, these two expressions return the same thing: Range[10] Table[i, {i, 1, 10}] In the Table statement, the specification within the list brackets means that the index or counter variable i will run from 1 to 10. You should also try the shortcut Table [i, {10}]. You are always free to check Mathematica Help for proper syntax. Recall that you can obtain help for any command by typing a ? in front of the command name; for example, ?Idontknowwhathisfunctiondoes or something similar. When in doubt about the command’s name, use ‘function browser’ or ‘find selected function’ under Help. Note: certain symbols are reserved and may NOT be used for variable names. These include all the capital letters that Mathematica uses for built-in functions: D, E, I, N, O, etc. Even though we won’t be doing much in the way of integration in this course, be wary of C. 2 Matrices We mere humans describe a matrix as a “rectangular array of numbers,” thus consisting of rows and columns. The number of rows is always given first: An mxn matrix has m rows and n columns; an nxn matrix is square. Mathematica describes a matrix as (what else?) a list of lists. That’s nice, but the gotcha is that the lists being listed are always the rows of the matrix. a b For example, m = {{a,b},{c,d}} is the matrix . We can obtain the matrix c d a c b d which is the list {{a,c}, {b,d}} by either re-typing the elements in the desired order or doing the transpose operation on the original matrix: Transpose[m] or equivalently m//Transpose. If you’ve never seen the // operator before, it is a shorthand way of applying a simple command to the prior variable or statement. No spaces here. Formatting note: A list of lists requires those annoying double list brackets. To show a matrix m in the usual square or rectangular form, use m//MatrixForm or m//TraditionalForm. Otherwise, you’re stuck with your list of lists. To display any vector x as a column, use the same functions: x//MatrixForm or x//TraditionalForm. Not much difference, except TraditionalForm uses a slightly prettier font than MatrixForm. However, you must NOT include //MatrixForm within the definition of a matrix: notgood = {{1,1}, {2,4}}//MatrixForm associates the variable type MatrixForm with the name notgood so you can’t do algebra on the values: notgood + notgood returns the utterly unusable and marginally understandable 1 1 1 1 1 1 1 1 1 , 1 , 2 , 4 2 4 2 4 2 4 2 4 You can create mxn matrices and n-dimensional vectors directly from Palettes Basic Math Assistant Advanced, using the icon shown at left. To add additional rows, press Enter while holding the control key down (control-enter). To add additional columns, press the comma key while holding the control key down (control-,). Even if you use this form of input, you need to include the //MatrixForm in order to display what you have entered as a nice-looking matrix. 1 1 is entered using the input palette and filling in the little 2 4 boxes with the desired values. Example: m 3 That displays as {{1,1}, {2,4}}, but could be made pretty with the suffix //MatrixForm: m = {{1,2},{3,4}}; m//MatrixForm The m = produces no output because of the terminating semicolon. And yes, you can put more than one command on a single line. Or we can be even tighter, storing and displaying in a single statement: MatrixForm[m = {{1,2},{3,4}}] Length[m] is the number of rows in matrix m. If the variable row is a valid row number in m, Length[m[[row]]] gives the number of columns (ie, the length of that row of the matrix). The above statement illustrates how we use different numbers of square brackets to mean different things: One pair of square brackets [ ] indicates the argument of a function (here the built-in function Length[ ] returns the number of elements in whatever is inside the [ ]); Two pairs [[ ]] indicate elements picked from a list (Since m[[row]] is a row of m, its Length[ ] is the number of columns in m). That means a single element of a matrix can be obtained with m[[row,col]]. You’ll soon learn that counting square brackets is a necessary evil. Dimensions[m] returns a list: {number of rows, number of columns}, whether or not the matrix has values in all elements – you can do a limited amount of work with partially empty matrices. Dimensions[m]//First will give the number of rows (also given by the Length[m]; Dimensions[m]//Last the number of columns. Yes, there are multiple ways to do things in Mathematica; perhaps that’s why it costs so much. Using the versatile Table statement mat= Table[i j-1,{i,4},{j,4}]; mat//MatrixForm yields the prettily formatted matrix Table doesn’t mind having two index variables (indicated by the two sets of stuff in { }). The indices i and j are row and column, respectively; each starts at 1 and increments by 1. Each element of the matrix above is thus the result of the algebraic operation row col - 1. 4 Note that you can specify each element in a table as a vector: Table[{i-1,i,i+1}, {i,1,4}] produces a list of 4 vectors, each of length 3: {{0,1,2},{1,2,3},{2,3,4},{3,4,5}}. That’s a 4x3 matrix! Handy function to generate an mxn matrix of random integers (and illustrate how to define a function) randMat[m_,n_,low_,hi_]:= Table[RandomInteger[{low, hi}],{m},{n}] When you execute the above, you get no output because := specifies ‘delayed execution.’ You’ve defined the function, but it hasn’t done anything yet. The built-in function RandomInteger[ ] gives integer values between low and hi, which are specified inside list brackets with the function call. The output matrix has m rows and n columns, because we put those values inside list brackets within the Table - they are the table’s indices. In the function definition, these variable names appear with trailing underscores inside the square brackets and are thus identified as parameters required by the function. The function’s parameters are given values when the function is called: randMat[5,3,0,9]//MatrixForm If we had left off the //MatrixForm, we could assign the function output to a variable and begin using it immediately. A=randMat[5,3,-5,5]; B=randMat[5,3,-1,1]; A+B {{-3,-3,-1},{3,-4,2},{-2,0,2},{-3,-6,1},{0,2,-4}} Note that in order for addition of these matrices to work they must have the same number of rows and columns! Why do we only see the result of the matrix addition? Joining Tables If you need a matrix that consists of repetitive values and don’t like to keep double indexing straight, you can build it piece by piece: A = Join[ Table[{1,j},{j,1,6}],Table[{2,j},{j,1,6}], Table[{3,j},{j,1,6}],Table[{4,j},{j,1,6}], 5 Table[{5,j},{j,1,6}],Table[{6,j},{j,1,6}] ] {{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{2,1},{2,2},{2,3},{2,4},{2,5},{ 2,6},{3,1},{3,2},{3,3},{3,4},{3,5},{3,6},{4,1},{4,2},{4,3}, {4,4},{4,5},{4,6},{5,1},{5,2},{5,3},{5,4},{5,5},{5,6},{6,1},{6,2},{6 ,3},{6,4},{6,5},{6,6}} This result is a 36x2 matrix of all possible combinations of two integers between 1 and 6, like all possible rolls of a pair of dice. If you want to get fancy, the easier way (less typing) is to nest two Table statements: dice= Flatten[ Table[ Table[{i,j},{j,1,6}], {i,1,6}], 1] The inner table (with the index j) represents the second number in each pair; this takes on the values 1 – 6 for each value of the outer index i. Nesting the Tables ordinarily produces a multi-level list of lists, each of the length specified inside the { } brackets; the peculiar Flatten[nestedlist, 1] removes one level of such listing, so that the resulting list is indeed our 36 pairs of dice rolls. Try it without Flatten[ ]; it’s not the same! We can then obtain the values of all these rolls: roll= Table[Total[dice[[i]]],{i,1,Length[dice]}] And the probability of each roll: probs= Table[Count[roll,k],{k,2,12}]/Length[dice] which is verified by adding the probabilities: Total[probs] You should verify that these examples do what they say – and that you can write such statements of your own: Build the same tables for rolls of three dice. Matrix family values To extract the value of a single element from matrix m, use double bracket notation m[[row, col]] for the value at the position in the matrix given by (row, col). To extract an entire row, use m[[row]]; to extract a column, use m[[All, col]]. You get the same result using either m[[row]] or Part[m, row]. Recall that Mathematica treats these 6 extracted single-dimensional objects, whether they started life as rows or columns, as plain old lists and displays them as such. You can either get or assign values to pieces of a matrix by using double brackets: mat[[2]] = {1,2,3,4}; sets the four values in the second row of matrix mat. To set the second column’s values, use mat[[All, 2]] = {1,2,3,4}. However, if the dimensions of the matrix you are trying to use doesn’t match your assignment, you’ll get a mess. Use with care! You can extract a submatrix using the Take[ ] function, as in these examples: gets the third and fourth rows: gets the third and fourth columns: Useful trick: Mathematica allows negative row, column numbers; these signify counting from the right or bottom rather than the usual left or top. Thus the lower right element of matrix m is m[[-1,-1]]. So here is the matrix above with the last row removed {1,-2} signifying rows 1 through the next to last. Here is the matrix with the last column removed 7 and here we get the submatrix with everything but last row and last column. Very Important Operations Dot products of two vectors are found using a period: v.w or the equivalent operation Dot[v,w]. You will get a result if you just typing v w, but you may not like it. The full power of the dot operator (.) appears when matrices are involved. a). If p and q are properly sized matrices, then p.q is their matrix product. b). If m is an m × n matrix and v is an n-vector, then m .v gives the vector result of m multiplying v. What would be the result of Length[m . v]? Taking m = n = 3 for example, if m1, m2, m3 are the rows of m and v = {v1,v2,v3}, then Mathematica defines m .v to be {m1.v, m2.v, m3.v}. This is standard matrix multiplication: the dot products are each the scalar result of each of the rows of m multiplying the column-vector v, resulting in what we could consider a column-vector (and Mathematica treats as a list). Note that you must have the correct length for matrix and vector: mat.Take[mat,{1,2}] doesn’t work. A smattering of other potentially useful commands: IdentityMatrix[n] – generates an identity matrix I of order (rows and columns) n. An identity matrix is always a square matrix. DiagonalMatrix[list] – puts the elements in list on the main diagonal of a square matrix of order equal to the Length[list]. If entering values instead of an already existing list, you must use { } around them to make them a list: DiagonalMatrix[{1,2,3,4}] 8 Transpose[m] – the transpose of a matrix has its row and column elements flipped, ie, the ith row of A becomes the ith column of Transpose[A]. Append[m, v] – adds vector v as a row at the bottom of matrix m. Lengths had better match! Append[{m[[1]]}, v] will make a new matrix with row 1 of m and vector v. Note the list brackets around m[[1]]. This can also be done with Join[{m[[1]]}, {v}] – but now both the matrix and the vector has to have list brackets. Annoyed by list brackets yet? If not, you will be! Prepend[{m[[1]]}, v] will make a new matrix with vector v on top of row 1 of m. You can add columns with Prepend and Append, but you have to Transpose first (and then Transpose back.) Try it! Det[m], Tr[m] –determinant and trace are all important matrix operations. MatrixPower[m, n] – multiplies matrix m by itself n times. This is repeated matrix multiplication, not raising each element of m to the nth power. Norm[v] – magnitude of vector v, equivalent to the square root of v.v, which is v12 v2 2 ... vn 2 Normalize[v] – vector v divided by its magnitude, the result is a unit vector UnitVector[k] – unit vector, with a 1 in the kth component (everything else is 0). Handy trick: Row-swapping in three easy steps on one line: temp = m[[2]]; m[[2]] = m[[3]]; m[[3]] = temp; How would you swap two or more columns? Fancy built-in functions (which may not always work the way you want) LinearSolve[m, b] – also solves m.x = b for vector x, but the built-in algorithm doesn’t always work so we must not rely upon it! To solve the equations represented by the matrix equation m.x = b, where m is a given nxn matrix and b is a given n-vector, you may sometimes be able to find the unknown nvector x using the built-in inverse function and the single statement x=Inverse[m].b. This only works if m has an inverse (and thus Inverse can only handle square matrices). And solving that problem in more general circumstances is what this course is about. RowReduce[m] – Gauss-Jordan Elimination, but you’ll be doing this by hand (some of the time). 9 NullSpace[m] – solutions to the equation m.x = 0 Eigenvalues[ ], Eigenvectors[ ], Eigensystem[ ] – we’ll get to them in time MatrixPlot[m] – what were they thinking? We will actually see a use for this later! More about Plotting You’ll learn a lot about the various flavors of Plot3D[ ] as we move along. Here are some samples for starters. Three equations in three unknowns: Plot3D[{2x - y, x + 3y, x - 5y},{x,-1,1},{y,-1,1}, AxesFalse, PlotStyle{Red,Green,Blue}, MeshFalse] Mesh is just that annoying crosshatching that Mathematica normally puts on a plotted surface. Setting the Mesh to False turns it off. Mathematica makes the right arrow when you type followed by > . Notice that PlotStyle within the Plot3D statement sets the style of each plotted function in the order specified. On the other hand, this is just a single plane composed of points {x= 2s - t, y= s+3t, z=s - 5t}: ParametricPlot3D[ {2s - t, s + 3t, s - 5t}, {s,-1,1},{t,-1,1}, MeshFalse, AxesLabel{x,y,z}] That color (whatever it is) is the default. Note the use of labeled axes; always a good idea. 10 Here’s a vector from the origin: Graphics3D[ {Thick, Red, Dashed, Arrow[{{0,0,0}, {1,2,1}}] }, AxesTrue, AxesLabel{x,y,z}] Now we are using Graphics, rather than Plot: The style specification isn’t in PlotStyle, it is within a list that must come before the plotted object. However, specifications about the plot’s frame and axis style (which are not the PlotStyle) show up after the object in question. Apparently Plot and Graphics were written by two groups of programmers who did not talk to each other. 1.0 2.0 z 0.5 1.5 1.0 y 0.5 0.0 0.0 0.0 0.5 1.0 x To show a plane that has this vector as a normal (perpendicular), we have to use two separate graphics, combining them within a Show[ ]: vec = Graphics3D[ {Thick, Red, Dashed, Arrow[{{0,0,0}, {1,2,1}}]}, AxesTrue, AxesLabel{x,y,z}]; Show[vec, Plot3D[-x - 2y, {x,-1,1}, {y,-1,1}, MeshFalse]] Don’t believe that’s a normal vector to the plane? There’s a simple way to test it. Try it! Note that Show passes the plot element styles from the first thing it encounters. We didn’t have to specify Axes within the Plot3D because they were already there inside the graphics element we called ‘vec.’ And note further that the contents of Show is not a list! Past members of this class have taken the programmers of Mathematica to task for such peculiarities as these: “Those Wolfram guys are scrubs!” - P. Taffet, ‘13 11 Problem Set 0 (why not?) Back in the good ol’ days when our Calc BC with Mathematica course was simply known as ‘Math 3,’ we had a challenge problem involving the calculation of using various historical formulae. a. One such form (attributed to Leibniz, but actually the work of a much older Indian mathematician) begins with the fact that tan 1 1 and proceeds by forming a power series 4 expansion for the arctan function at x = 1. How many terms in the series are needed to obtain correct to 12 decimal places? Develop a plot of the error in this expansion as a function of the number of terms; for reference, the value of the first term (n = 0) is simply 4. How do you define error in this context? b. A better formula is that of the 17th century British mathematician John Machin: 1 1 . Perform a similar series expansion and compare (via a plot of 16 tan 1 4 tan 1 5 239 the error) these two approaches, this time using 24 decimal places as your standard. What is meant by ‘better’ in this context? 12