📜 ⬆️ ⬇️

Programming in maxima

Maxima lesson


Introduction

Maxima is a free computer algebra system (Computer algebra system - CAS) based on Common Lisp. In its functionality, it is hardly inferior to other modern paid CAS, such as Mathcad, Mathematica, Maple; can carry out analytical (symbolic) calculations, numerical calculations, build graphs (using gnuplot). It is possible to write scripts and even translate them into Common Lisp code with subsequent compilation. Since maxima was written from lisp developed by programmers, its syntax may seem a bit confusing, since the language is immediately imperative and functional. I will try to explain precisely these moments and to explain the essence of the functional approach in an accessible way, and I will not at all focus on specific mathematical functions: they are fairly easy to master on my own. This article discusses exactly the features of the calculus and syntactic structures of maxima.

Shells

Of course, calling the maxima interpreter from the console is not very convenient. We want to look at beautiful formulas that are rendered using latex. Therefore, for beginners, I would advise to put the wxMaxima shell. If you are fond of TeXmacs, you can configure it as a shell (to be honest, I have not tried it). Well, for emacs lovers there is imaxima , for working in a buffer. It is put literally out of the box.

Acquaintance

At first glance, everything is simple: we enter an expression that ends with a semicolon, we get the answer. You can try maxima as a calculator, calculate the sum of two numbers, calculate the sine of an angle, etc. Digging deeper what is happening.
Atoms

Symbols, numbers and logical constants true and false are the simplest objects of the system. All the other expressions and structures of the language are built from them, so they are called atomic (indivisible) or just atoms.
Variables


The system distinguishes between free and designated variables. Marked variables are bound variables, variables to which some value is assigned. When interpreting, the variable name is replaced with its value. You can set a variable using the ":" sign. Free variables are not associated with any value, and we can operate on them abstractly, for example, add two character expressions.
Calculation context

When computing each command, its computational context is formed. It is a set of relationships between variable names and their values, as well as some interpretation parameters. There are two computational contexts: local and global. Global context - common to all interpreted commands, determines the current state of the interpreter. The local context is created for the duration of the execution of one command, and is valid only for it. Links and parameters of the local context are the highest priority.

Here, the value of the variable a is taken from the global context, and for the local, the option to expand the works is set, further works will not unfold by themselves.
Lock computing


Let's try to add two variables. And now we put in front of them a single quotation symbol. This is a blocking operator. If we put it before the variable name - as a result we will get the name of this variable, before calling the function - the symbolic expression of the function call. What for? Sometimes you may need to use one function to process an expression of another function and get a function or a number at the output, such as the calculation of an indefinite integral. In other words, you have the opportunity to represent the expression as data and manipulate it. However, if you try to stop the calculation of the sum of two numbers, the calculations will not stop. This is due to the fact that the single quote operator does not stop the simplest simplification of an expression (simple operations on numbers, reduction of fractions). Also, the calculations will not stop if you try to calculate the value of the function of a rational (float) argument.
And so, the Maxima system does not distinguish between algorithmic functions and mathematical functions, in which they are one language element. In the terminology of the interpreter itself, the operators that can be computed are called verb, those operators that so remain in non-computed form are called noun. To initiate the calculation of all nouns, it is necessary to set the option nouns in the context of calculations.

')
Calculations

We have learned that the interpreter distinguishes between concepts of a symbolic expression and its calculations. When does the calculation occur? The most obvious case is when we try to calculate an expression (2 + 3, for example). Entered expression - got its value. Calculated the function of the argument - got the value. Introduced the name of the variable - got its value. We have learned that the value of a variable can be both an atom and a symbolic expression. When is the calculation still going on? The calculation takes place when assigning a variable to a value. The value to the right of the colon is calculated before the assignment, so when assigning a variable to a symbolic expression, we put a quotation mark to stop this calculation. There is a special type of assignment (operator two colons), when both the expression on the right and the expression on the left are evaluated. Also, before calculating a function, all its arguments are evaluated.

The result of calculating the variable a on the left is the variable b.

Example

Consider a simple example - the construction of the set of all subsets. As it turned out, Maxima has built-in types for working with sets, and, alas, no such function. Let's write it.

First, let's look at what is set. Apparently, the sets in Maxima are based on a different data structure — simply linked lists. What is the list everyone understands. They have three main functions for working with them: getting the element in the head of the list (first), getting the list consisting of the original without the first element (rest), adding a new element to the beginning (cons) and combining two lists (append). Similar functions exist in any lisp implementation, but more often, they are called a little differently: car, cdr, cons, append, respectively.

How did you usually imagine an algorithm for solving such a problem? One could imagine the subsets in the form of a characteristic vector and enumerate them all. However, we will show exactly the functional approach. It is easy to see that each element enters exactly half of the subsets. This simple fact is already enough to build a recursive algorithm. We remove one element a from set A. The set of all subsets of A will consist of the union of the set of all subsets A \ a and the set of all subsets A \ a, where a is added to each element. With the help of the last statement, one can reduce the dimension of the problem as much as recursively, reducing it to a trivial case. To implement, we need an additional function of two parameters (an element and a set of sets) that would add the specified element to each set.

Note that the function declaration happens almost as in mathematics. It should be noted that in determining the right side after the equal sign is not calculated. (In order to define a function so that its definition is calculated, it is necessary to use the form define). Here comes the new computational form if. It works the same as imperative languages. When the condition is met, the expression is then evaluated after then, if not, after the else. Now we write the desired function.

Let's try to count something.

the end

Well that's all. In the next article it would be nice to describe the implementation of the steepest gradient descent.

Source: https://habr.com/ru/post/153853/


All Articles