------------------------------------------------------------------------- PHYS210 2009-10-06 LAB SUMMARY l) Writing a Maple procedure that processes lists. 2) Writing a Maple procedure that outputs to a file. 3) Introduction to xmaple's plotting facilities. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1) Writing a Maple procedure that processes lists. 1a) Change to your ~/maple directory, and using your text-editor create the following Maple procedure and save it in a file called lpair. For concreteness, I'll assume you're using kate. Note that the contents of lpair (i.e. the definition of lpair) are contained between the two lines of ----'s The version I showed you during the lab didn't include all of the comments, and if you are working this exercise by yourself, you needn't reproduce all (or any!) of the comments % cd ~/maple % kate lpair ------------------------------------------------------------------------- ############################################################# # lpair: Returns list lres such that lres[i] = [l1[i], l2[i]] ############################################################# lpair := proc(l1::list, l2::list) # Define locals for building up sequence that is then # converted to list and returned, and a loop vbl. local sres, i; # Ensure that the lists are of the same length, if not # invoke error to print a message and exit. if nops(l1) <> nops(l2) then error("Input lists l1 and l2 are not of the same length"); end if; # Initialize sres to be the empty sequence sres := NULL; # Loop over the elements of l1, l2 and build up the # sequence of two element lists ... for i from 1 to nops(l1) do sres := sres , [ l1[i], l2[i] ]; end do; # Convert the built up sequence to a list, and return said # list using default value-return mechanism. [sres] end proc; ------------------------------------------------------------------------- 1b) Now create another text file, called tlpair (for 'test lpair') that contains the following maple commands (i.e. create a maple script that will exercise/text lpair). Again, enter all of the text between the lines of ----'s in tlpair ------------------------------------------------------------------------- # Enable tracing of lpair by un-commenting the following line # trace(lpair); list1 := [1, 2, 3, 4]; list2 := [a, b, c, d]; list3 := [[a,b], [b,c], [d,e], [f,g]]; list4 := [a, b, c]; listn := []; set1 := {a, b, c, d}; printf("Executing lpair(%a,%a)\n",list1,list2); lpair(list1,list2); printf("Executing lpair(%a,%a)\n",list1,list3); lpair(list1,list3); printf("Executing lpair(%a,%a)\n",listn,listn); lpair(listn,listn); printf("Executing lpair(%a,%a)\n",list1,list4); lpair(list1,list4); printf("Executing lpair(%a,%a)\n",list1,set1); lpair(list1,set1); ------------------------------------------------------------------------- 1c) Ensure that you are in your maple directory, ~/maple, then start (command-line) maple. From the maple prompt, read in lpair, and then tlpair. If you have created lpair and tlpair correctly, then you should see output as shown below. If you don't, try to fix any errors that maple reports, and re-read lpair and/or tlpair as necessary. Remember that you'll save time if you keep an editor window open while you're working with maple. Just be sure that if you're using more than one terminal window, that you have changed the working directory to ~/maple in both cases. % cd ~/maple % maple |\^/| Maple 12 (IBM INTEL LINUX) ._|\| |/|_. Copyright (c) Maplesoft, a division of Waterloo Maple Inc. 2008 \ MAPLE / All rights reserved. Maple is a trademark of <____ ____> Waterloo Maple Inc. | Type ? for help. > read lpair; local sres, i; if nops(l1) <> nops(l2) then error "Input lists l1 and l2 are not of the same length" end if; sres := NULL; for i to nops(l1) do sres := sres, [l1[i], l2[i]] end do; [sres] end proc > read tlpair; read tlpair; list1 := [1, 2, 3, 4] list2 := [a, b, c, d] list3 := [[a, b], [b, c], [d, e], [f, g]] list4 := [a, b, c] listn := [] set1 := {a, b, c, d} Executing lpair([1, 2, 3, 4],[a, b, c, d]) [[1, a], [2, b], [3, c], [4, d]] Executing lpair([1, 2, 3, 4],[[a, b], [b, c], [d, e], [f, g]]) [[1, [a, b]], [2, [b, c]], [3, [d, e]], [4, [f, g]]] Executing lpair([],[]) [] Executing lpair([1, 2, 3, 4],[a, b, c]) Error, (in lpair) Input lists l1 and l2 and not of the same length Executing lpair([1, 2, 3, 4],{a, b, c, d}) Error, invalid input: lpair expects its 2nd argument, l2, to be of type list, but received {a, b, c, d} ------------------------------------------------------------------------- 1d) EXERCISE: Enable tracing of lpair in the tlpair file, and re-read tlpair. Also Experiment with your own input to lpair. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2) Writing a Maple procedure that outputs to a file. 2a) Change to your ~/maple directory, and using your text-editor create the following Maple procedure and save it in a file called pwrsfile. Again, for concreteness, I'll assume you're using kate. Again, the contents of the file you are to create are contained between the two lines of ----'s, and the version I showed you during the lab didn't include all of the comments, which you needn't reproduce. % cd ~/maple % kate pwrsfile ------------------------------------------------------------------------- ############################################################# # pwrsfile: Routine which illustrates how to perform maple # output to a file. # # Procedure arguments # # fname: Name of output file # xmin: Minimum value of output x sequence # xmax: Maximum value of output x sequence # nx: Number of values in output x sequence ############################################################# pwrsfile := proc(fname::string, xmin::float, xmax::float, nx::integer) # Define locals vbls for the file descriptor, the sequence # of values of x values and a specific value of x local fd, xseq, x; # Check for valid arguments ... if nx < 1 then error("nx must be >= 1"); end if: if xmax <= xmin then error("xmax must be > xmin"); end if; # Generate the list of x values ... if nx = 1 then xseq := xmin; else xseq := seq(xmin .. xmax, (xmax - xmin) / (nx - 1)); end if; # Open the file for writing: if the open operation is # successful, fopen returns a "file descriptor" (generally # a small integer) which is used in subsequent file # operations, such as writing and closing. # # By default, Maple opens files so that they are written # and read as text; it is also possible to write and read # in "binary" format. Binary files store information in # a form which is "natural" for the computer, and thus will # generally look like garbage when viewed in an editor or # with more etc. However, for very large amounts of data, # it is significantly faster to read and write binary files # than text files. # # See ?fopen for more details fd := fopen(fname,WRITE); # Loop over the sequence of x values ... for x in xseq do # ... and output x, x^2, x^3 and x^4 to the file using # fprintf. Note that the first argument to fprintf is # the file descriptor returned by fopen. # # The format specification %18.8e, which is valid for # floating point values, means "output using exponential # notation" in a field that is 18 characters wide, and # with 8 digits following the decimal point. When using # an %...e format specification, be sure that the field # width is large enough to accomomdate the sign of the # number, as well as the exponent (including its sign) # A general rule of thumb is that the field width should # be >= "number of digits to the right of the decimal # point" + 7. # # Also note the use of \n in the output format specification # to generate a "new line". Otherwise, all of the output # would appear on a SINGLE line. fprintf(fd,"%18.8e %18.8e %18.8e %18.8e\n", x, x^2, x^3, x^4); end do; # Close the file. This is an important step; until a # file is closed, there is no guarantee that values output # using fprintf statements will actually BE in the file # (i.e. they could be stored in so-called "buffers" which # the operating system maintains in memory in order to # optimize the speed of input and output operations to # slow (relative to the CPU and main memory) devices such # as disk drives. # # The single argument to fclose is the file descriptor. # # Finally note that since the sole purpose of this routine # is to generate output to a file, we don't really care # what it returns to the invoking environment---e.g. it # wouldn't make any sense to assign the return value of # the routine to a Maple variable. fclose(fd); end proc; ------------------------------------------------------------------------- 2b) Now create another text file, called tpwrsfile (for 'test pwrsfile') that contains the following maple commands (i.e. create a maple script that will exercise/text prwsfile). Again, enter all of the text between the lines of ----'s in tpwrsfile ------------------------------------------------------------------------- # Testing code for pwrsfile # Enable tracing of lpair by un-commenting the following line # trace(pwrsfile); pwrsfile("output",0.0,16.0,17); ------------------------------------------------------------------------- 2c) Ensure that you are in your maple directory, ~/maple, then start (command-line) maple. From the maple prompt, read in pwrsfile, and then tpwrsfile. Then quit the maple session, and examine the contents of file 'output'. If you've created pwrsfile and tpwrsfile correctly then you find that the contents of 'output' are as below. Again, if you don't get the expected results, try to fix any errors that maple reports, and re-reading pwrsfile and/or tpwrsfile as necessary. % cd ~/maple % maple |\^/| Maple 12 (IBM INTEL LINUX) ._|\| |/|_. Copyright (c) Maplesoft, a division of Waterloo Maple Inc. 2008 \ MAPLE / All rights reserved. Maple is a trademark of <____ ____> Waterloo Maple Inc. | Type ? for help. > read pwrsfile; pwrsfile := proc(fname::string, xmin::float, xmax::float, nx::integer) local fd, xseq, x; if nx < 1 then error "nx must be >= 1" end if; if xmax <= xmin then error "xmax must be > xmin" end if; if nx = 1 then xseq := xmin else xseq := seq(xmin .. xmax, (xmax - xmin)/(nx - 1)) end if; fd := fopen(fname, WRITE); for x in xseq do fprintf(fd, "%18.8e %18.8e %18.8e %18.8e\n", x, x^2, x^3, x^4) end do; fclose(fd) end proc # Note that the following command produces NO output from Maple. > read tpwrsfile; > quit; # Examine the contents of 'output' % cat output 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 1.00000000e+00 2.00000000e+00 4.00000000e+00 8.00000000e+00 1.60000000e+01 3.00000000e+00 9.00000000e+00 2.70000000e+01 8.10000000e+01 4.00000000e+00 1.60000000e+01 6.40000000e+01 2.56000000e+02 5.00000000e+00 2.50000000e+01 1.25000000e+02 6.25000000e+02 6.00000000e+00 3.60000000e+01 2.16000000e+02 1.29600000e+03 7.00000000e+00 4.90000000e+01 3.43000000e+02 2.40100000e+03 8.00000000e+00 6.40000000e+01 5.12000000e+02 4.09600000e+03 9.00000000e+00 8.10000000e+01 7.29000000e+02 6.56100000e+03 1.00000000e+01 1.00000000e+02 1.00000000e+03 1.00000000e+04 1.10000000e+01 1.21000000e+02 1.33100000e+03 1.46410000e+04 1.20000000e+01 1.44000000e+02 1.72800000e+03 2.07360000e+04 1.30000000e+01 1.69000000e+02 2.19700000e+03 2.85610000e+04 1.40000000e+01 1.96000000e+02 2.74400000e+03 3.84160000e+04 1.50000000e+01 2.25000000e+02 3.37500000e+03 5.06250000e+04 1.60000000e+01 2.56000000e+02 4.09600000e+03 6.55360000e+04 ------------------------------------------------------------------------- 2d) EXERCISE: Enable tracing of pwrsfile in the tpwrsfile file, and re-read tpwrsfile. Experiment with different invocations of pwrsfile, changing, any or all of the input arguments. 2e) MORE CHALLENGING EXERCISE: Write a routine pwrsfilein with header pwrsfilein := proc(fname::string) which 1) Opens the file 'fname', which is assumed to be of the precise form that pwrsfile generates (i.e. four columns of numbers of the form x, x^2, x^3, x^4) 2) Reads lines from the file using fscanf, and contructs a list of lists, in which each sublist is of the form [x, x^2, x^4, x^6]o and then returns that list. Hints: See ?fscanf Example: Assuming the input file is 'output' as generated above, then pwrsfilein produces the following output > pwrsfilein("output"); 0., 0., 0., 0.], [1.00000000, 1.00000000, 1.00000000, 1.00000000], [2.00000000, 4.00000000, 8.00000000, 16.0000000], [3.00000000, 9.00000000, 27.0000000, 81.0000000], [4.00000000, 16.0000000, 64.0000000, 256.000000], [5.00000000, 25.0000000, 125.000000, 625.000000], [6.00000000, 36.0000000, 216.000000, 1296.00000], [7.00000000, 49.0000000, 343.000000, 2401.00000], [8.00000000, 64.0000000, 512.000000, 4096.00000], [9.00000000, 81.0000000, 729.000000, 6561.00000], [10.0000000, 100.000000, 1000.00000, 10000.0000], [11.0000000, 121.000000, 1331.00000, 14641.0000], [12.0000000, 144.000000, 1728.00000, 20736.0000], [13.0000000, 169.000000, 2197.00000, 28561.0000], [14.0000000, 196.000000, 2744.00000, 38416.0000], [15.0000000, 225.000000, 3375.00000, 50625.0000], [16.0000000, 256.000000, 4096.00000, 65536.0000]] +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3) Introduction to xmaple's plotting facilities. IMPORTANT: See ?plot and related topics for full information Change to your maple directory and start up xmaple % cd ~/maple % xmaple From the menu bar select File -> Save as, and save the previously untitled, and empty worksheet as plots.mws Enter the following Maple commands and remember to periodically save your work using Ctrl-S, or one of the other available worksheet saving mechanisms. Note, again, you don't have to enter the Maple comments. # Generate a basic plot using a built-in mathematical function. In such # cases, Maple determines an appropriate "sampling density" in the # independent variable to produce a smooth looking plot. > plot(sin(x), x=-2.5*Pi..2.5*Pi); # Generate the same plot but this time use "point style" rather than "line # style" and use a "box" for the plotting symbol. Also, add a title to # the plot, and use "boxed" axes. > plot(sin(x), x=-2.5*Pi..2.5*Pi, title="Plot of sin(x)", > style="point", symbol="box", axes="boxed"); # Generate some numeric values for x and sin(x) over the range -2.5*Pi to # 2.5*Pi and plot as above. Note the difference in the appearance of the # plots due to Maple's "adaptive" sampling of sin(x) in the first plot, # versus the "uniform in x" sampling in the second plot. > nx := 50; nx := 50 > vx := [seq(evalf(-2.5*Pi)..evalf(2.5*Pi), evalf(5.0*Pi/(nx -1)))]: > vsinx := map(sin,vx): > plot(vx, vsinx, title="Plot of sin(x) [fixed sampling interval]", > style="point", symbol="box", axes="boxed"); # Generate a plot with multiple dependent variables, using line style # (detault). Include a title and a legend. > plot( [sin(x), sin(2*x), sin(3*x)], x=-2.5*Pi..2.5*Pi,axes=boxed, > title="Plot of multiple functions", > legend=["sin(x)", "sin(2x)", "sin(3x)"]); # Generate a plot of the area under the curve exp(-x^2) on the interval # x = -10 .. x1, and with x1 ranging from -10 to 10. # Note how Maple makes sense of all the occurrences of 'x', # which would normally drive your calculus nuts! > plot(int(exp(-x^2), x = -10..x), x = -10..10);