**Creating a Maple procedure**

This page was not originally going to be about Maple code; Maple is, after all, simply a means to an end. This was initially going to be about the one-seventh ellipse, but that didn't turn out to be as interesting as I had originally hoped. The more interesting part, to me at least, was the Maple code that I wrote to discover conic sections similar to the one-seventh ellipse. The final procedure (if there is such a thing as a final version) is not fancy or even really elegant, but it touched on a lot of intricacies that one must deal with when writing code in Maple. In addition, someone showed some interest in the Maple programs I wrote for my first essay, and expressed a desire to write her own procedures, so I thought a small essay on writing in Maple might prove useful. This comes with the disclaimer that I have little formal knowledge of programming in general, but have some experience in using Maple's language to automate various mathematical calculations.

**An interesting task**

No one (at least that I know of) starts writing a program just because - there must be a goal in mind. The program must do something the programmer wants done. In the case of the one-seventh ellipse task, the question the programmer (me) wanted to answer was: How unique is this property of one-seventh? Now, in case you are not familiar with the one-seventh ellipse and are too lazy to click on the link I provided, I'll give a short explanation here:

It just so happens that any five points in a plane, no three of which are collinear, define a non-trivial conic section (ellipse, circle, parabola, hyperbola). This is because the equation for a conic may be written as

If you want more details on why this is so, you may find some
help here. In
any case, the above equation has 6 parameters, a0 through
a5, but we can divide the equation by one of them
to get a 1 somewhere, so it is reasonable to suspect that choosing 5 appropriate
pairs of values for *x* and *y* would
yield unique values for the remaining 5 parameters. This is not only reasonable,
but true as well. What does this have to
do with one-seventh? Well, it just so happens
that the decimal expansion of one-seventh, 0.142857... has precisely 6 numbers
in its repetend. If you pair these numbers in sequence, you can come up with
6 points in the plane: (1, 4), (4, 2), (2, 8), (8, 5), (5, 7), (7, 1), no
three of which are collinear. Well, we know that any 5 of these will define
a unique conic, in this case an ellipse, but the rather odd thing is that
the sixth point happens to lie on the ellipse as well! This does seem a bit
bizarre, but how bizarre is it really? Well, if we were to set out to find
another fraction with this property, we'd first have to find its decimal
expansion, see if it has a 6 digit repetend, seperate the repetend into 6
points, plug in 5 of them to solve for the parameters in
the conic's equation, and then plug the 6th point into this equation to
see if we get 0. This is a lot of calculating
and we might well go through many fractions without finding one, or we might
stumble upon one fairly early in our search. In either case, unless we systematically
search all possible 6 digit repetends, we'd really not be sure how often
this occurred. This is where Maple comes in.

**Input/Output**

It may help to think of a Maple procedure as a function machine,
one where we simply put something in and get something out. Of course, to
create the function machine we have to worry about how we take what goes
in and make it into what comes out, but initially it might help to just think
of the type of input/output that we want. I remember the first time I tried
to write a Maple procedure completely on my own. It seemed daunting, but
fortunately the professor that had asked me to write it stated things in
terms that helped me focus. He said, "I want a procedure where I input
a set of matrices with property X, and which returns a list of integers with
property Y." It doesn't matter what properties X and Y were now, what
matters are the phrases "*set of matrices*" and "*list
of integers*." You see, not only
does this tell us what goes in and what comes out, but it tells us how they
are organized when they go in and when they come out. How is this relevant
to our current challenge of writing a program to find fractions that share
the 'conic generation' property with one-seventh? Well, perhaps our input
should be a fraction, and our output should be a statement about whether
the property exists, something along the lines of yes/no or true/false. How
does this relate to the organization of the input and output? Well, might
things be different if the goal had been to find *numbers* that share
the 'conic generation' property with one-seventh? What's the difference between
a *number* and a *fraction*? Well, mathematically there may
be little difference, but to Maple (and probably to our own ways of thinking),
there are some key differences, for example in the ways they are represented.
This brings us to our first programming idiosyncracy - types.

**Maple Types**

Though mathematically 1/7 = 0.142857142857..., I doubt that
our brains react precisely the same way when they see 1/7 as they do when
they see 0.142857142857...; I know mine doesn't. It turns out that Maple
doesn't think about them identically either, it classifies them differently.
It classifies 1/7 as a *fraction* and
0.142857142857... as a *float*. Why is this? Well, Maple has finite
memory and no matter how far it carries the repetition 142857, if it's only
repeated finitely many times then we are really just seeing an approximation
of the number intended. I'm not sure why Maple programmers used the term
float, but I like to think it is because the value Maple sees is floating
somewhere
near the value intended, and how close it floats depends on how many decimal
places we want to use. In any case, both *fraction* and *float* are
examples of **types*** *inside the Maple structure. There
are many other types, and a few of them will be immediately relevant to our
problem. In fact, I already mentioned two other Maple types, the *set* and
the *list*. What's different about these? Maple thinks of a *set* much
in the same way mathematicians do (thankfully, Maple programmers had substantial
mathematical background, so the terminology is often obvious), it's an unordered
collection where each element occurs once. Thus, in Maple's thinking {1,
2, 3, 4, 5} = {5, 5, 4, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, 5}. A *list* is
different in that it's an ordered collection that preserves the number of
times an element occurs. So, for Maple, [1, 2, 3, 4, 5] is different then
[2, 1, 3, 4, 5] and both of these are different from [1, 1, 2, 3, 4, 5].
To find out what type Maple is assigning to a given object, *x*, we
can just ask it, using the command whattype(*x*); which brings us
to another programming idiosyncracy - syntax.

**Maple Syntax**

Syntax refers to the rules and structure for language. This
deals both with the ordering of words and also with the punctuation that
indicates when a thought is complete. We deal with this in English all the
time - a period denotes that a sentence (or chunk of thought) is complete
while rearranging the word order inside a chunk (sentence) can drastically
confuse the meaning or destroy the meaning all together. Sometimes we are
not very careful about the ordering, but with Maple we have to be. For example,
sometimes I'll ask my wife something like "Remind me that tomorrow I
need to buy green peppers." to which she'll sarcastically and immediately
reply,
"Don't forget that tomorrow you need to buy green peppers." However,
I can preempt her joke by being more precise and asking "Tomorrow, remind
me that I need to buy green peppers." Notice the difference? Maple does
notice differences like these, so precision is key. So, what is Maple's syntax?
Well, Maple operates primarily by means of functions. That is, its
commands require an input and they give an output and the input is usually
entered in much the same way we use function notation. Thus, whattype is
a function
in Maple, and to input something into it, like 1/7, we'd type whattype(1/7)
and Maple
would think of this as us asking for the image of 1/7 under the function
whattype. Of course, Maple programmers realize that our conventional notation
is not always done in terms of functions, and they've honored this wherever
possible. Thus, we wouldn't type plus(3, 4) to add 3 and 4, we'd just type
3 + 4 and Maple can handle it. Typing whattype(1/7) isn't the whole story,
however. What we want is to view the result of the function whattype applied
to 1/7, and so we'd need to use a semi-colon ';'. So, if we type whattype(1/7);
and then hit enter, we'll see the response *fraction*. One may also
use the colon ':' to evaluate the input through the function without showing
the output. Typing whattype(1/7): and then hitting enter doesn't show
us anything except a new command line, but rest assured that Maple has evaluated
1/7 through the function whattype. Hiding the output can be useful if a particular
output is rather unruly and you don't need to see it so much as you need
to use it in further calculations. It's important to remember that ; completes
a thought for Maple, and if the thing you type is not logical without it,
you'll likely get an error. Example: executing whattype(B) whattype(A); gives
me an error, because it's not a type of thought Maple understands. whattype(B)
is incomplete in and of itself, it needs ; or : just like a sentence
is incomplete without a period. Full thoughts must be ended by ; or : or
else
Maple doesn't
know what you mean. This doesn't mean 3 + 4 should be executed as 3; + 4;
because, while 3 and 4 can be complete thoughts by themselves, 3 + 4 is also
a complete thought by itself so 3 + 4; is the way it should be executed.
In addition, Maple is cAsE sEnSiTiVe, so executing Whattype(1/7); is different
than executing whattype(1/7); which can be both a curse and a blessing.

Okay, so now we can execute a Maple command, with the option of viewing or hiding the output. The next thing we need to learn how to do is to define a variable. Though the notation is not universal, it's not uncommon to see a mathematician write something like A := whatever. The := (colon followed immediately by equals) means 'define.' So A := whatever means A is defined to be whatever. Maple uses this notation the same way. If I type A := 4; and then hit enter, Maple will record that A is defined to be 4. Then, whenever I type A later in that Maple session, Maple will think of 4. This is immensely useful. Suppose I have a huge list of numbers I want to work with, but I obviously don't want to type the list over and over again. I can use the define feature like this: L := [1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5]; and by hitting enter Maple knows that if I later just type L, I really mean the whole list. This can also be used for changing values, like the following example. Let's say I type (and execute by hitting enter) A := x + y; and then later I type x := 4; and y := 5; What will Maple think of when I type A? It will think of 9 = (4 + 5). If, even later, I change x to 6 by executing x := 6; then Maple begins to think of A as 11 from then on. We will use this later.

I encourage you to open this Maple
worksheet and walk through the examples, just so you're sure you've got it.
**(You may want to right-click and save the file first, and then open
it from there, especially if your browser tries to open it and displays something
about an XML file.)** I know right now that it doesn't seem like
we can do very much, but we're off
to
a good
start.
Maple
is a
tremendously
powerful
set
of programs
and
so a bit of complexity is to be expected. The next thing we'll talk about
is indexing -the way we know how far along we are in a sequence.
In written notation we use subscripts, as in the parameters a0 through
a5 in the equation for the conic (though my text
editor doesn't let me put them as subscripts, you saw that they were subscripts
in the equation). Maple will display this indexing as subscripts when it
returns a result to
us that
contains
them, but in the input we use something different. Let's say I have a list
L, with 10 elements in it, L := [a, b, c, d, e, f, g, h, i, j]; like so.
To tell Maple I want the 4th item in L, I'd execute L[4]; and I'd get back
d. To ask for the 3rd through 7th items, I'd type L[3..7]; and would get
back a sublist [c, d, e, f, g]. Why do I get a sublist with the [] instead
of just the letters c, d, e, f, g? That's a convention decided upon by whomever
wrote the original Maple code (aka Maplesoft)
and is one of the quirks we just have to deal with. As with any convention,
sometimes it's useful and sometimes it's annoying, but it's still there.
In any case, this indexing will prove indispensible as we begin programming.
One other nice feature is the ability to ask for items in reverse order,
for example executing L[- 1]; returns j and so on. Be careful though, about
asking for an index that doesn't exist - executing L[11]; will return
the error
'invalid subscript selector,' which is an error you will probably become
all too accquainted with as you
struggle
through your first few programs.

Finally, you should know that Maple largely ignores white-space. That is, it recognizes a space between words but it doesn't differentiate between 1 space and 15 spaces. The # symbol also has a specialized function. Typing # lets Maple know that we are just entering text to read and that it shouldn't think about what follows as commands. Programmers use this to leave notes in their code for other programmers and for purposes of debugging. You'll see an example soon.

**Maple Vocabulary**

Now that we've gotten a bit of syntax and typing down, we can worry about the vocabulary - the actual words, or in this case, functions that we will be using. Building a vocabulary large enough to accomodate your needs is largely a matter of experience, but some of the commands are the precise equivalent of what you'd expect them to be from their mathematical meanings. For example, there is a Matrix command and a Transpose command, and, as you'd expect, the Matrix command arranges its inputs into a matrix and the Transpose command transposes the matrix it receives as input. For any Maple command, if you want to view the help page that describes exactly how the input should be entered, you can type ?command and help will appear. So, if I type in integrate(x^3, x, 4, 5); and don't get the integral of x^3 evaluated from 4 to 5, but rather the symbolic integration (without the constant), I can type ?integrate to find out that I needed to execute integrate(x^3, x = 4..5); to get 369/4. A warning is in order, however. Maple's help files are written for the Maple proficient, not for the Maple beginner, so they can be a bit difficult to understand. I know this because I used to be employed proofreading them for a professor who wrote many Maple procedures and the associated helpfiles. Anyway, don't give up if you struggle, just take a break and then come back. One other quirk about Maple vocabulary, again a convention decided upon by Maplesoft, is that the various functions are arranged into packages. Transpose is part of the LinearAlgebra package. Why do we care? Well, to allow Maple to boot up faster, many packages aren't loaded initially and have to be added before the commands will work. So, if you open a blank Maple worksheet and type in a Matrix named M and then type Transpose(M); you will be out of luck until you execute with(LinearAlgebra): Click here to see an example. This is a good example of where you might use : instead of ; because typing with(LinearAlgebra); gives a big sequence of the names of the functions in the LinearAlgebra package. This can be a bit of a pain, especially when Maplesoft tries to upgrade Maple's packages. Most new versions of Maple have both a LinearAlgebra package and the package it supplanted, linagl. This means there is a transpose command in the linalg package as well as the Transpose command in the LinearAlgebra package. In most cases use the newer packages (if you know what they are) because they work a bit better, but that is a topic for a different essay.

There are a few absolutely essential pieces of Maple vocabulary for us. One is the proc command. This command tells Maple we are going to begin writing a procedure. If my procedure needs to be named Brian and it will have input parameters n and m, I'd write Brian := proc(n, m) ...code here... end proc; or end proc: as you desire. There are some slight extensions of this available, but this should do us for now. Another vital piece is the if/then statement. This asks Maple to check the Boolean value of a statement and then, depending on that value, to carry out a specific action or sequence of actions. There is also the for/do loop and while/do loop. The for/do loop tells Maple to carry out a command a specified number of times, while the while/do loop tells Maple to repeat the command until a certain condition is met. Finally, the break command tells Maple to exit the for/do loop or while/do loop it's currently operating in and proceed with the next step in the program. I think this will all make a bit more sense as we try our hand at writing some code.

**Let's get started!**

Let's practice by writing a small Maple program to find the
slope between two points. We'll try and flesh it out here and then execute
it in a Maple worksheet to see if it works. We know the formula for slope
requires that we have two ordered pairs, the points (x1,
y1)
and (x2, y2) and we also know
that we want our output to be a single value, m. Well, how might one enter
2 ordered pairs? Maple treats ( ) as either parantheses for operations or
as in function notation, so we can't use them. The key is that these are
ordered, so we turn our thoughts to the *list* type that was discussed
earlier. Someone could think of the notation [3, 4] as the point (3, 4) without
too much difficulty, so let's run with that. We've got two inputs, point
1 and point 2, let's refer to them as p1 and p2 and off we go!

slope := proc(p1, p2); # Here we've given our process a name and said that we'll have two input values called p1 and p2.

mtop := (p1[2] - p2[2]); # These next three steps are basically the whole program. We have Maple compute the difference of the y-values and the difference of the x-values and then compute the quotient and call it m.

mbottom := (p1[1] - p2[1]);

m := mtop/mbottom;

RETURN(m) end proc; # This tells Maple to output m and then to end the procedure. Let's put this into Maple and test it!

That's pretty cool, but now comes the inevitable part of programming - unanticipated troubles. What happens if someone runs the program above on the points [3, 4], [3, - 6]? Aargh!! We get something about an error called numeric exception:division by zero. Technically, nothing is wrong with this, but it's hardly the kind of output we want from our program. We'd much rather that the slope program actually returned something besides an error, like the word 'undefined' or maybe even infinty. Let's rework the problem with an if/then statement to make this happen:

slope := proc(p1, p2);

mtop := (p1[2] - p2[2]);

mbottom := (p1[1] - p2[1]);

m := mtop/mbottom;

if mbottom = 0 then RETURN(infinity) end if;

RETURN(m) end proc;

How does this work? What!? It didn't work? Let's figure out
why. Ok, I'll admit that this was a contrived mistake to teach you another
valuable piece of Maple vocabulary, the trace command. The trace command
reveals the inner calculations a process runs through on the way to it's
output (well, not all of them, but all those that form a complete chunk and
are ended by ;) so we can often use this to debug a program. On a new
command line, execute trace(slope); and then rerun the slope procedure with
the
points [3, 4], [3, - 6]. One interesting thing about Maple that wasn't immediately
obvious to me (though now it seems that way) is that it is time dependent
on its executions, not placement dependent. Thus, I can execute trace(slope);
below slope([3, 4], [3, - 6]); and then move the cursor back up to reexecute
the slope procedure and trace is in effect. Thus, it doesn't matter where
your parameters are defined or where a procedure was run, it only matters
if it has already been run before you try and do something with it. You can
force Maple to forget what it has already run by executing restart; or by
hitting the restart button in the panel (it looks like a circular blue arrow
with a secondary red tip in my version). Anyway, the trace feature should
reveal that the program correctly
computed mtop
to be -10 and mbottom to be 0 and then ran into the error. Now it hits us,
Maple returns the error *as soon as* it discovers it, which is before
the if/then statement we put in. So, let's move the if/then statement up
and try again.

slope := proc(p1, p2);

mtop := (p1[2] - p2[2]);

mbottom := (p1[1] - p2[1]);

if mbottom = 0 then RETURN(infinity) end if;

m := mtop/mbottom;

RETURN(m) end proc;

Now, turn off trace by running untrace(slope); and then execute slope([3, 4], [3, -6]); What do you get? ∞ of course!

**The One-Seventh Ellipse Code**

Okay, let's move on to something more challenging - the problem
we were initially interested in. Earlier, we decided that the input should
be a *fraction* and the output should be a Boolean result like true
or false. So what happens in between? Let's take a crack at writing a program,
with extensive programming notes to assist us. To expedite the execution,
we'll do it all in a Maple worksheet.

Once you've worked through all that you've hopefully got a better grip on how to write simple programs in Maple and you also have some nice little code to check fractions for the property that one-seventh has, namely the existence of a conic like the one known as the one-seventh ellipse. Now we can begin to answer the question of 'how bizarre is this property' of one-seventh? In other words, do lots of other fractions have it as well? To answer this, you can see the results in a series of three Maple worksheets (they each take about 1.5 hours if you execute them, but you can simply open them and view the output) or three html files (I recommend just looking at the html, unless you want to grab the results from Maple in some sort of searchable form). That should help you see why I felt the original question wasn't as interesting as the programming that went into constructing an answer for it.

Maple Worksheet 1, Maple Worksheet 2, Maple Worksheet 3

Okay, okay I know what you are saying now, at least if you looked at the Wolfram link I provided about the one-seventh ellipse. "But 1/7th was even more special in that it had a conic through both (1, 4), (4, 2), (2, 8), (8, 5), (5, 7), (7, 1) and through (14, 42), (42, 28), (28, 85), (85, 57), (57, 71), (71, 14), its double digit pairs!" Well, this is true, but it turns out that 1/7th is still not unique in that regard either. I'm not going to show you the Maple program I used to do it, partially because I want you to write your own to check my results but also because I'm a bit embarrased at how long it takes to execute, but I'll let you see a Word document (or a text file, if you prefer) with all the fractions with 6 digit repetends that have both the single digit conic and the double digit conic. There are certainly more than I expected. In any case, there are now all sorts of interesting questions we can ask, such as: "How are these fractions distributed?" or "Are there any fractions with a 7 digit repetend with all 7 points on a conic?" or "Are there any fractions with not only a single and double digit conic, but also a triple digit conic?" For answers to these and more questions, I refer you to this.