Home | Mathematics | * Maxima |     Share This Page
Files and Functions
P. Lutus Message Page

Copyright © 2007, P. Lutus

Saving and Loading your Work | Creating and Using Functions

(double-click any word to see its definition)

 
Saving and Loading your Work

From this point onward, it is very likely you will be producing some content worth preserving, so it's time to explain how to save your work, and load it later on.

Saving

Let's say you are in a work session and have produced some variable definitions and functions worth keeping. Here's how to instruct Maxima to save your work:

stringout("my_work.txt",values,functions);
my_work.txt

This will save all your defined variables and functions in a plain-text file, suitable for editing and re-use in a later Maxima session.

Default File Location

In the above example as shown, the file will be saved under your home directory, which if you are running Linux, is typically "/home/(username)/".

Windows note: Unfortunately, because of a programming error at the time of writing, under Windows the file will be saved under the wxMaxima installation directory, which is typically "C:/Program Files/Maxima-(version)/wxMaxima/". One can only hope this error will be corrected in a future version of wxMaxima so the default directory for file operations will be the user's home directory, which under Windows is "C:/Documents and Settings/(username)/".

Next example. Let's say you have made entries into Maxima in a particular order, and those entries and their order is important — you would like to preserve what you typed, just as you typed it. Here's how to do this:

stringout("my_input.txt",input);
my_input.txt

This example saves an unedited list of everything you have typed since beginning your Maxima session. To be useful, it might be edited, or parts of it extracted into another file. But this form creates a record of all your inputs for later perusal.

The possibility exists that you won't remember all these details, and you simply want to save everything. Here's how to do that:

stringout("everything.txt",all);
everything.txt

The documentation for "srtringout()" is not complete at the time of writing, but in my explorations, I've come up with this list of possible arguments to "stringout()":

  • input: all user entries since the beginning of the session.
  • values: all user variable and array assignments.
  • functions: all user-defined functions (including functions defined within any loaded packages).
  • all: all of the above. Such a list is normally useful only for editing and extraction of useful sections.
Multiple arguments can be passed to "stringout()", as shown above. I find the most useful invocation to be "stringout('filename',values,functions)".

Loading

The two most useful loading commands are "batch()" and "batchload()". These funny-sounding names go back to the early days of Fortran, when a "batch" might be a stack of 80-column program and data cards, and computers were gigantic boxes kept in airtight rooms manned by people in white lab coats. This naming style tells us how long Maxima, and its predecessor Macsyma, have been around.

There are any number of ways to create files suitable for Maxima loading. One obvious way is to save a file as shown above, using "stringout('filename',values,functions);". Such a file is quite suitable for reloading into Maxima, and it will restore all your definitions.

Another way is to write Maxima code into a file, then load it. In this approach, one might extract useful sections from saved data files, and create new entries to accomplish a particular goal. An easy way to go about this is to have a text editor and wxMaxima running at once. One would type something into the text editor, save the file in its current form, then turn to wxMaxima and issue one of these two commands:
batch("everything.txt"); (to see each instruction as it is executed)
everything.txt
batchload("everything.txt"); (to load and execute instructions silently)
everything.txt
The second option above is quieter, but it will still print out results and create graphs. Once a program is working, bug-free and has become a useful tool, the second loading option is preferred.

Example

Now for an example of loading and running a Maxima program file. Here is a listing of a very simple routine that prints a multiplication matrix:

for y:1 thru 12 do
(s:"",
for x:1 thru 12 do
s:sconcat(s,printf(false,"~4d",x*y)),
print(s));

This routine is available for download here. To get this into Maxima, use your browser to save the file on your computer, and provide the path and filename to Maxima using the "batchload()" command:

batchload("/path/to/example/file.txt");

If you have done this correctly, the following display will appear:

 1   2   3   4   5   6   7   8   9  10  11  12 
 2   4   6   8  10  12  14  16  18  20  22  24 
 3   6   9  12  15  18  21  24  27  30  33  36 
 4   8  12  16  20  24  28  32  36  40  44  48 
 5  10  15  20  25  30  35  40  45  50  55  60 
 6  12  18  24  30  36  42  48  54  60  66  72 
 7  14  21  28  35  42  49  56  63  70  77  84 
 8  16  24  32  40  48  56  64  72  80  88  96 
 9  18  27  36  45  54  63  72  81  90  99 108 
10  20  30  40  50  60  70  80  90 100 110 120 
11  22  33  44  55  66  77  88  99 110 121 132 
12  24  36  48  60  72  84  96 108 120 132 144 
              

Windows note: Because of a programming error in wxMaxima at the time of writing, you will have to use a full path to tell wxMaxima where your browser put the file. Most likely it will be located here:

"C:/Documents and Settings/(username)/My Documents/maxima_mult_matrix.txt"

wxMaxima Note:

There are some file saving and loading features in wxMaxima that create and read files with the suffix ".wxm", it appears they represent an easy way to save and load an entire session, but as these features are entirely undocumented at the present time, I think I will resist trying to describe them and their purpose until the program's author does.

Creating and Using Functions

Easy Examples

In the simplest cases, one can create a useful function with a few keystrokes:

average(a) := sum(a[i],i,1,length(a))/length(a)

As explained in the section above, this definition will be saved along with all other user-defined content with the command "stringout('filename',values,functions)".

The reason for creating functions is to encapsulate and name useful operations and algorithms, just as the reason for creating variables is to encapsulate and name useful values.

Here is an example. There is no "log10(x)" function in Maxima (or in many other places), because there isn't a pressing need for this to be explicitly defined. But there almost always is a "log(x)" function that produces a natural logarithm for its input argument. Let's use the "log(x)" function to create a "log10(x)" function:

log10(x) := log(x)/log(10.0);

Now let's test our new function:

log10(1e6);
5.999999999999999

Oh, well, nothing is perfect. I'll spare my readers a tedious exposition on why this is not equal to exactly 6.00000 (it has to do with conversion between binary and decimal number bases). Suffice it to say we have a useful function derived from existing functions.

Not so easy

Not all function writing is as straightforward as the above example. It sometimes happens that one would like to capture the result of a prior calculation and make it into a new function. This is a bit more complex. Here's an example:

    Create the desired expression:
    a*x^2+b*x+c=0;
    a x2 + b x + c = 0
    solve(%,x);

    At this point we need to introduce a new practice. To avoid a lot of confusion as these examples get more complex, let's get into the habit of saving intermediate results under distinctive variable names:

    eq:a*x^2+b*x+c=0;
    a x2 + b x + c = 0
    sol:solve(eq,x);

    This variable assignment will turn out to be very important for what's coming up next. Now we want to capture the quadratic solution created above and put it into a function that will accept any arguments for a, b and c, and produce numerical results for numerical arguments.

    Without going into all the details of how Maxima organizes and stores its results, it should suffice to say that we have saved the two roots of the quadratic equation in a list named "sol", and the list can be accessed by way of an index. Like this:

    sol[1];

    sol[2];

    Okay, that's a good start — we can access the two roots independently. But for use in a function definition, we need to get rid of the "x = " part of the expression. Here's how we do that:

    rhs(sol[1]);

    rhs(sol[2]);

    Now let's try to build a function out of these pieces:
    quad(a,b,c) := [ rhs(sol[1]), rhs(sol[2]) ];

    Okay, we seem to have created the function. Does it work? Let's test it:

    quad(1,2,3);

    Well, no, that's wrong. We should have seen each appearance of a, b and c replaced with the numerical values provided in the function call. The reason for this failure is subtle, but I include this example because it is a common problem. Here is the solution:

    quad(a,b,c) := ev([ rhs(sol[1]), rhs(sol[2]) ]);

    This change works because the right-hand expression is evaluated ("ev()") before being assigned to the function definition, and the evaluation replaces references to list contents with the contents themselves. Let's test this new form:

    quad(1,2,3);

    Yes! That's the right result for those arguments (note the presence of "i", which signifies that the result is complex). Now we can enter any desired arguments to our new "quad()" function and get the two roots of the quadratic equation for those values. To reduce the output to simple numeric quantities, we need only express it this way:

    float(quad(1,5,3));
    [-4.302775637731995,-0.69722436226801]

    Here is a concise set of instructions to get to this result, one that can be placed in a file and read by Maxima:

    eq:a*x^2+b*x+c = 0;
    sol:solve(eq,x);
    quad(a,b,c) := ev([rhs(sol[1]),rhs(sol[2])]);

    You may also get these instructions as a Maxima-readable file by clicking this download link.

    Just to show my readers how powerful this approach can be, I just made some small editorial changes in the above example, and created this variation:

    eq:a*x^3+b*x^2+c*x+d = 0;
    sol:solve(eq,x);
    cubic(a,b,c,d) := ev([rhs(sol[1]),rhs(sol[2]),rhs(sol[3])]);

    Click this download link for a file containing this example.

    Here's an example cubic solution:
    cubic(1,2,3,4);
    (Click Here to see the result in graphic form)

    Remember about these examples that declaring a function in the default way —

    f(x) := x^2;
    f(x) := x2
    — is only guaranteed to work in the simplest cases. Remember that the function "ev()" (meaning evaluate) can be used to solve some of the more difficult assignment problems.
 

Home | Mathematics | * Maxima |     Share This Page