M-3: Plots, Functions, Sets, Lists, and Sequences

Maple is able to plot functions in a variety of formats. We’re going to start with the simplest usage,

> plot(sin(x), x=-Pi..Pi);

which will give you something that looks like this:

In this case, we explicitly specified the x-range, and Maple chose the y-range automatically based on the minimum and maximum values. Notice that by right-clicking (PC) or command-clicking (Mac) on the plot, you will see a number of options, including an Export option which includes the .eps format. (This may be useful for your final project! You can export to .pdf too but it has far too much whitespace. To get around this, either use the trim option of includegraphics, or export to .eps and convert from eps to pdf if necessary.)

You will also see some different options about colour, style, axes, scaling, etc. However, we’re only going to focus on the command-line versions of these options, since they are more consistently reproducible; as far as we know every option can be specified textually. For example, let’s say that we don’t like how the picture is stretched out of proportion. We can send plot() an explicit y-range of -3..3 by typing

> plot(sin(x), x=-Pi..Pi, -3..3);

and you will see that this looks a bit better. However, many people would prefer

> plot(sin(x), x=-Pi..Pi, scaling=constrained);

which has a y-axis of the right length too. Like many other Maple functions, plot is very versatile and accepts many different types of inputs and named arguments. On the help pages ?plot, ?plot/details and ?plot/options you can see some of them. (Caveat: we’ll discuss {sets} and [lists] below, which are needed to understand some of the options.)

In the example above we used the format  plot(expr, x=a..b, opts) where scaling was the only option we chose to specify. Setting a second option is done just by appending to the end of the plot call,

> plot(sin(x), x=-Pi..Pi, scaling=constrained, legend=["Sine function"]);

Try this and see what it gives you.  Note: we’re using "double quotes" here to define a String/text chunk literal, while we introduced the 'single quote' in the previous lesson (just before introducing restart) which does delayed evaluation (see ?'). Finally `back-quotes` are used to write symbol literals (but we have some feedback from students saying this does not work on a Mac).

Functions

How can we define a new mathematical function in Maple? Let’s try to define a function to compute the square of a number. The first thing you might try is

> square(x) := x^2;

and while this seems ok, the result is not effective: square(4) does not work if you try it on the next line. (What you’ve done is hard-code a single input/output pair, so calling square(x) works, but square(y) doesn’t.) The correct way to define this sort of function is the following:

> square := x -> x^2;

Try it and confirm that square(4) works on the next line. Note: the motivation for this notation is that we want to redefine square to mean “the function which maps any \(x\) to \(x^2\).” The mathematical notation for such a function is \(x \mapsto x^2\) (\mapsto in LaTeX), and Maple’s mimicing that concept.

In the above definition, we’re adhering very closely to the mathematical definition of a function: a map that specifies, for every input, a single output value. Consequently, when we use square with plot, it is no longer necessary to refer to the variable name x: try it for yourself by running the command

 > plot(square, -4..4);

Verify that it is a plot of the square function over the domain [-4, 4].

Just like in mathematics, Maple can define a function that takes in more than one argument. This is done using the syntax

> «function name» := («arg1», «arg2») -> «function definition»;

(Three or more arguments are also possible.) For example,

> gaussian2D := (x, y) -> exp(-x^2-y^2)/Pi;

will define a function representing the probability density of the standard bivariate Gaussian. Check that it works:

> gaussian2D(1, 1/2);        # gives exp(-5/4)/Pi
> evalf(gaussian2D(1, 1/2)); # gives 0.091197...

Exercise (nickname: stamps)

A philatelist values stamps according to the function

\displaystyle\textrm{value}=\frac{\exp(a/d)+a^3d^{-2}}{a+d}

where a is the age of the stamp and d is its damagedness. By defining a function and evaluating it at several points, determine which of the following 4 stamps is the most valuable: a = 10, d = 8; a = 25, d = 19; a = 30, d = 23; or a = 50, d = 37.

Let’s return to the gaussian2D example: we can even plot it as a 3-D graph. This is done with the plot3d command. Type in either one of the following commands:

> plot3d(gaussian2D, -2..2, -2..2);
> plot3d(gaussian2D(a, b), a=-2..2, b=-2..2);

and you’ll get a picture like the following:

Right-click on it to access the style options, and in particular choose the Manipulator drop-down menu and select Rotate. This will let you interactively rotate the plot by clicking on it and dragging your mouse in different directions.

Sets and Lists

Sets and lists are the two fundamental structured data types in Maple. Here are two examples:

> mySet := {1, 2, 3};
> myList := [1, 2, 3];

What is the difference between a set and a list? The difference, like in mathematics, is that a set has no inherent order on its elements and does not allow repeats, while order and repetition are important for lists. (Sometimes you might mathematically say tuple instead of a list.) We can verify this as follows:

> evalb({1, 2, 3} = {3, 1, 2, 1});  # true
> evalb([1, 2, 3] = [3, 2, 1]);     # false

One place where you’ll need to use a list is if you want to plot multiple functions on the same set of axes. Try

> plot([sin(x), cos(x)], x=-Pi..Pi, legend=["Sine", "Cosine"]);

Here is a question worth understanding: why do we logically have to use a list here, and not a set?

An example application of sets is to use as an argument to solve, when we want to solve multiple equations for multiple unknowns. Try

> solve({x+y = 1, 2*x - 3*y = 4}, {x, y});

Here, solve would also be happy to accept a list… often you can use either unless one is logically required.

Exercise (nickname: 3d)

Using solve, find the intersection points of the following three surfaces in \mathbb{R}^3 (real Euclidean 3-space):

  1. the sphere centred at (-1, -1, -1) with radius 13
  2. the set of all points at distance \(\sqrt{130}\) from the z-axis (this is an infinite hollow cylindrical surface)
  3. and the plane {(x, y, z) | x+y+z = 16}.

Hints:

You will not be able to graph these surfaces to visualize the answer; they are not “functions” (for example, a sphere would not pass the vertical line test). Rather, keep in mind that solve is used to solve a system of equations. What equation represents each surface?

  1. If you do not know this equation, you should be able to find it by searching online quite easily, but it will likely be centered at (0, 0, 0). Use your knowledge of transformations in 2D to shift the sphere in a negative direction.
  2. In two dimensions, how do you write the equation of a vertical line? In this 3D analogy, your equation for this will not use z. Your equation then will look like the equation of a two dimensional shape that is \(\sqrt{130}\) from the origin.
  3. You have been given this equation.

My last note is that there is one complex solution, which may make you think you have received the wrong output. If you wish to only find real solutions, substitute RealDomain[solve] for solve.

More about sets

You can take the intersection, union, and difference of sets using the Maple operators named intersect, union, and minus.

> ({1, 2, 3} union {2, 3, 4}) minus {2}; # gives {1, 3, 4}

More about lists

Once you have a list, you can access individual elements using indices: [1] refers to the first item, [2] is the second, etc.

> names := ["alice", "bob", "carl", "doris"];
> names[2];                           # gives "bob"
> names[2] := "robert";               # change 2nd value
> names;                              # ["alice, "robert", "carl", "doris"]

Caveat: you can only set someList[i] to a value when someList already exists and has length at least i. This generally means that in order to use lists as data structures, you must explicitly initialize them, e.g. with someList := [seq(0, i=1..desiredLength)]. For advanced usage we’d use Arrays — they won’t be covered in detail but we’ll mention them again at the end of the case study in lesson M-7.

Gluing lists and converting sets/lists with op

Occasionally you may want to convert a set to a list or vice-versa. One way to accomplish this is with the op() function, which strips a list or set of its parentheses. Say that we’ve defined names as above; then

 > op(names);

will give back the comma-delimited sequence

“alice”, “bob”, “carl”, “doris”

without any surrounding brackets or braces. This is an expression sequence. Wrapping an expression sequence in {} turns it in to a set, and wrapping it in [] turns it in to a list, and in this way you can convert sets to lists and vice-versa. Furthermore, you can concatenate two expression sequences using commas: for example,

> [op(names), "ed", "fritz"];

will give back the list

[“alice”, “bob”, “carl”, “doris”, “ed”, “fritz”]

Small print: op() has other purposes too, such as extracting parts of a Maple expression, but we leave this out of our lessons. See ?op for the details.

Creating Sequences

You can create your own sequences programmatically in Maple by using the seq() command. The syntax is identical to that for sum(): you type seq(«expr», «var»=«low»..«high») where «var» is the name of the index variable. A sequence is created by listing all of the values of «expr» as the index variable ranges from  «low» to «high». For example,

> seq(i^2, i=1..5);

will give back the sequence 1, 4, 9, 16, 25. Often, but not always, you will want to wrap the entire call to seq in a container, such as [seq(...)] to give a list or {seq(...)} to give a set.

A typical use of [] is to create point plots. To do this, we represent a data point by the ordered pair [x-coordinate, y-coordinate]. Then, we pass plot a list of points, i.e. a nested list. The following example creates a plot of four data points:

> plot([[0, 0], [1, 1], [2, 4], [3, 8]], style=point, symbolsize=20);

Here’s what it should look like when you execute that line; the two style options are just included to make the points easier to see.

While this is cool, it would be great to be able to make a point plot without writing down the whole list explicitly, when the points follow a regular pattern. This can be done by using seq. For example, if we wanted to plot \(\sin(x/2)\) at all integer points from 0 to 30, we’d use the command

> plot([seq([i, sin(i/2)], i=0..30)], style=point, symbolsize=20);

It is very instructive to look closely at exactly how seq was used. The expression being repeated over and over by seq is [i, sin(i/2)], as i goes from 0 to 30. So this creates a list of data points. Immediately surrounding the call to seq there is another pair of [brackets], which dumps all of these points into a list, and this list is what is plotted. We could write equivalently using more lines:

> seqOfPoints := seq([i, sin(i/2)], i=0..30);
> listOfPoints := [seqOfPoints];
> plot(listOfPoints, style=point, symbolsize=20);

Exercise

(Not to be handed in.) Modify the previous example so that the x-coordinate is \(\cos(i/4)\). The end result should look like an infinity sign.

Note: you can also see ?plot/parametric for another way of doing parametric plots like the above.

For the next exercise, which will be the last item in this lesson, we need a way to count the number of elements in a set. The nops() function accomplishes this:

> nops({1, 2, 1, 3, 10, 9, 2});
# gives back 5, the number of elements in {1, 2, 3, 9, 10}

Exercise (nickname: times)

How many distinct integers can be expressed in the form \(a \times b\) where both a and b are integers between 1 and 100 (inclusive)?

Optional advice if you need help:

If you need some advice on how to proceed, try the following. The main idea is that you need to use seq twice in a nested fashion: one seq() expression will be inside of the other one. Be careful that you will need to use two different variables for their respective indices (probably a for one and b for the other would make the most sense). Wrap the outer call to seq in {set braces} to turn it in to a set.

You can define functions and variables if you like, or you can solve the whole problem in a single line. It is up to you.

To test your approach on a smaller test case: if we had written 6 instead of 100, the correct answer would be 18. (An explicit listing of all such numbers is: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 30, 36.)

These are course notes for the University of Waterloo's course Math 600: Mathematical Software.
© 2012—. Written and developed by David Pritchard and Stephen Tosh. Contact (goes to the CEMC)