------------------------------------------------------------------------- PHYS210 MAPLE PROGRAMMING LAB 3 ------------------------------------------------------------------------- o Additional documentation for Maple Programming Maple 7 Programming Guide http://laplace.phas.ubc.ca/210/Doc/maple/ProgrammingGuide7.pdf (available via course notes page), and locally at /home/phys210/maple/ProgrammingGuide7.pdf o Structure/contents are distinct from other Maple Programming Guide introduced in previous lab CHAPTERS 1 AND 2 of Maple 7 Guide ARE PARTICULARLY USEFUL FOR NOVICE PROGRAMMERS ------------------------------------------------------------------------- SAMPLE SOLUTION TO THE 'mysum' EXERCISE FROM PREVIOUS LAB ------------------------------------------------------------------------- o Can be found in ~phys210/maplesolns/myprocs3soln ------------------------------------------------------------------------- o Change your working directory to ~/maplepgm2, and start xmaple in the background from the command line % cd ~/maplepgm2 % xmaple & o Again, should you wish, point your browser (or a tab in your browser) to /home/phys210/maplepgm2/index.html so that you can click on the links to see the contents of the various files in ~/maplepgm2 o Read the file 'procs2' into your xmaple session > read procs2; ------------------------------------------------------------------------- "TRACING" EXECUTION (OPERATION) OF A PROCEDURE ------------------------------------------------------------------------- o Maple provides a simple yet powerful "tracing" facility that allows one to see the input value of arguments to procedures, the values returned by any of the statements executed in the procedure, and the return value from the procedure o Very useful feature that allows us to see what is happening "inside" a procedure and thus for debugging the procedure, once syntax errors have been removed o IMPORTANT: In order to get full tracing information, ensure that every statement uses the ';' as a terminator, if ':' is used (recall that ':' suppresses output), then the tracing info for that statement will NOT appear o Syntax trace(); untrace(); o 'trace' turns on tracing, 'untrace' turns it off o Example: > trace(myfactorial); myfactorial o Note how 'trace' echoes the name of the procedure ... if you mistype the procedure name, or otherwise pass it an argument that is NOT the name of the procedure, it will not echo anything > trace(myfctorial); o Now let's see how the tracing works ... > myfactorial(4); {--> enter myfactorial, args = 4 val := 1 val := 2 val := 6 val := 24 24 <-- exit myfactorial (now at top level) = 24} 24 o Now turn off tracing ... > untrace(myfactorial); myfactorial > myfactorial(4); 24 ------------------------------------------------------------------------- o IMPORTANT: Can enable tracing for ANY procedure that you write, but only useful once SYNTAX errors have been eradicated o IMPORTANT: Recommended practice for use of trace when implementing procedures in a source file; assume that we are coding a procedure, 'myproc'; then include trace statement IN THE FILE, and FOLLOWING the definition of the procedure myproc := proc( ... ) . . . end proc; trace(myproc); We want to do this since every time a procedure is redefined (which happens when we re-read the source file), Maple will effectively execute 'untrace' for that procedure (i.e. turn tracing off). Including the trace command after the end of the procedure definition ensures that tracing remains enabled. Also you can disable tracing by "commenting out" the trace command; i.e. insert # before the command: #trace(myproc); and re-enable as necessary by deleting the # ------------------------------------------------------------------------- EXAMPLES OF PROCEDURES THAT MANIPULATE LISTS ------------------------------------------------------------------------- o IMPORTANT: Exit your current xmaple session o Now, let's implement the following procedure ... Header: ladd := proc(l1::list(algebraic), l2::list(algebraic)) Functionality: Given two equal-length lists of algebraic quantities, returns a list whose elements are the sums of the corresponding elements of the input lists o Restart xmaple from the bash command line, and from the directory ~/maplepgm2 % pwd /home/phys210/maplepgm2 % xmaple & o Using gedit, and also working in the directory ~/maplepgm2, create a file 'ladd', that contains the definition of the procedure 'ladd', by following along as I type in my definition o Note that in this case, the name of the file and the name of the single procedure defined in that file are both 'ladd' .... INTERLUDE, AS WE WORK ON ladd ... o Further tests of procedure, with both valid and invalid input, try some of your own > ladd( [1, 2, 3, 4], [10, 20, 30, 40] ); [11, 22, 33, 44] > ladd( [w, z, y], [a, 2*b, 3*c] ); [w + a, z + 2 b, y + 3 c] > ladd( [1, 2], [a, b, c] ); Error, (in ladd) Input lists l1 and l2 are not of equal length > ladd( 1, [3, 4] ); Error, invalid input: ladd expects its 1st argument, l1, to be of type list(algebraic), but received 1 > ladd( [], [] ); [] o Again, modify text file, save it, re-read into maple, test procedure as necessary ... keep in mind that you can enable/disable tracing using > trace(ladd); > untrace(ladd); ------------------------------------------------------------------------- o IMPORTANT: For the remaining examples, be sure to examine the full procedure definitions (including comments) in the file 'procs2'; note that one of these is a fully commented version of 'ladd' Again, you can view the definitions from within a browser window by pointing the browser to /home/phys210/maplepgm2/index.html and clicking on the 'procs2' link ------------------------------------------------------------------------- o IMPORTANT: Exit xmaple, then restart it, ensuring that the working directory is still ~/maplepgm2 % pwd /home/phys210d/maplepgm2 % xmaple & o Input the procedure definitions from 'procs2' > read procs2; ------------------------------------------------------------------------- o lpair: Header: lpair := proc(l1::list, l2::list) Functionality: Returns list whose elements are 2-element lists containing corresponding elements of list arguments 1' and 'l2' ------------------------------------------------------------------------- o Examples: > lpair( [1, 2], [a, b] ); [[1, a], [2, b]] > lpair( [u, v, w, [x, y]], [[a, b], c, d, e] ); [[u, [a, b]], [v, c], [w, d], [[x, y], e]] > lpair( [1, 2, 3], [a, b] ); Invalid, since input lists are not of the same length o Examine definition of 'lpair' in 'procs2' and at the maple command line > op(lpair); proc(l1::list, l2::list) local s, i; if nops(l1) <> nops(l2) then error "Input lists are not of equal length" end if; s := NULL; for i to nops(l1) do s := s, [l1[i], l2[i]] end do; [s] end proc o Test procedure, with both valid and invalid input > lpair( [1, 2], [a, b] ); [[1, a], [2, b]] > lpair( [ [1, 2], 3, 4], [a, [b, c], d] ); [[[1, 2], a], [3, [b, c]], [4, d]] > lpair( [1, 2, 3], [a, b] ); Error, (in lpair) Input lists are not of equal length > lpair(1, [a, b, c] ); Error, invalid input: lpair expects its 1st argument, l1, to be of type list, but received 1 o Try a call with tracing enabled > trace(lpair); lpair > lpair( [1, 2, 3], [a, b, c] ); {--> enter lpair, args = [1, 2, 3], [a, b, c] s := s := [1, a] s := [1, a], [2, b] s := [1, a], [2, b], [3, c] [[1, a], [2, b], [3, c]] <-- exit lpair (now at top level) = [[1, a], [2, b], [3, c]]} [[1, a], [2, b], [3, c]] > untrace(lpair); ------------------------------------------------------------------------- o ljoin: Header: ljoin := proc(l1::list, l2::list) Functionality: Returns list whose elements are those of 'l1' followed by those of 'l2'. ------------------------------------------------------------------------- o Examples > ljoin( [1, 2, 3, 4], [a, b, c, d] ); [1, 2, 3, 4, a, b, c, d] o Examine definition of 'ljoin' in 'procs2' and at the maple command line > op(ljoin); proc(l1::list, l2::list) [l1[], l2[]] end proc o Note the simplicity of the definition ... o Test procedure, with both valid and invalid input > ljoin( [1, 2, 3, 4], [a, b, c, d] ); [1, 2, 3, 4, a, b, c, d] > ljoin( [1, 2, 3, [4, 5] ], [a, b, c] ); [1, 2, 3, [4, 5], a, b, c] > ljoin( [1, 2, 3, 4], [] ); [1, 2, 3, 4] > ljoin( [], [] ); [] > ljoin( 1, [a, b] ); Error, invalid input: ljoin expects its 1st argument, l1, to be of type list, but received 1 ------------------------------------------------------------------------- INTRODUCTION TO MAPLE'S PLOTTING FACILITIES ------------------------------------------------------------------------- o Maple has powerful plotting capabilities, both for 2D (x-y) and 3D (x-y-z) plots o Will only take a brief look at 2D plots here, use the online help facility via > ?plot and > ?plot/options for full details on making 2D plots. You might also be interested in making 3D plots. See > ?plot3d for more details o Most useful form for us plot(f, x = x0..x1 ); where f - expression in independent variable x x - independent variable x0, x1 - left and right endpoints of horizontal range o Try the following > plot( 6*sin(2*x)*sin(3*x) - 1, x = 0 .. 4 ); o We can easily plot several functions/expressions by combining them into a list ... > plot( [sin(x), cos(x), tan(x) ], x = -2*Pi .. 2*Pi ); o Try some examples of your own!! ------------------------------------------------------------------------- EXERCISE 1) ------------------------------------------------------------------------- o In ~/maplepgm2/myprocs4 write a procedure 'lprod' as follows Header: lprod := proc(l1::list(algebraic), l2::list(algebraic)) Functionality: lprod returns a list whose elements are the products of the corresponding elements of 'l1' and 'l2'. o 'lprod' should operate analogously to 'ladd'. In particular, it should use the 'error' command to exit with an error message if the input lists are not of the same length o Example: > lprod( [2, 4, 6], [3, 4, 9] ); [6, 16, 54]; o Best if you start from scratch, rather than copying/modifying 'ladd' o Test your procedure using both valid and invalid input. Following the strategy advocated previously, I suggest that you code suitable tests in a separate file ~/maplepgm2/tmyprocs4 whose first statement is read myprocs4; ------------------------------------------------------------------------- EXERCISE 2) OPTIONAL IF YOU WOULD RATHER SPEND THE TIME ON HOMEWORK ------------------------------------------------------------------------- o In ~/maplepgm2/myprocs4 write a procedure 'myplot3' as follows Header: myplot3 := proc(f::algebraic, xmin::algebraic, xmax::algebraic) Functionality: Makes a single plot of f and its first two derivatives (i.e. three curves on the same graph) on the domain xmin .. xmax o IMPORTANT: When you invoke 'mplot3', 'f' should be an expression in 'x', and you should use 'x' in the specification of the horizontal range (a.k.a. domain) in the 'plot' statement. o Thus you should expect to see plots for calls such as myplot3(cos(2*x), 0, 3*Pi); myplot3(x^3, -1, 1); myplot3(exp(x), 0, 2); but for myplot3(cos(y), 0, Pi); an error message such as Warning, expecting only range variable x in expression sin(y) to be plotted but found name y is likely to be displayed (along with an empty plot), and this is OK ------------------------------------------------------------------------- EXERCISE 3) OPTIONAL IF YOU WOULD RATHER SPEND THE TIME ON HOMEWORK o Modify your definition of ladd so that it requires both input lists to be of non-zero length, using, as usual, error to print a diagnostic message and exit the procedure if that condition is not met ------------------------------------------------------------------------- ------------------------------------------------------------------------- FREE TIME TO WORK ON HOMEWORK, DISCUSS TERM PROJECTS ETC. -------------------------------------------------------------------------