]>
LinearOrdinaryDifferentialOperator1(A) is the domain of linear ordinary differential operators with coefficients in the differential ring A.
This example shows differential operators with rational function coefficients. In this case operator multiplication is non-commutative and, since the coefficients form a field, an operator division algorithm exists.
We begin by defining RFZ to be the rational functions in x with integer coefficients and Dx to be the differential operator for d/dx.
Operators are created using the usual arithmetic operations.
Operator multiplication corresponds to functional composition.
Since operator coefficients depend on x, the multiplication is not commutative.
When the coefficients of operator polynomials come from a field, as in this case, it is possible to define operator division. Division on the left and division on the right yield different results when the multiplication is non-commutative.
The results of
leftDivideleftDivideLinearOrdinaryDifferentialOperator1 and
rightDividerightDivideLinearOrdinaryDifferentialOperator1 are
quotient-remainder pairs satisfying:
leftDivide(a,b) = [q, r] such that a = b*q + r
rightDivide(a,b) = [q, r] such that a = q*b + r
In both cases, the degreedegreeLinearOrdinaryDifferentialOperator1 of the remainder, r, is less than the degree of b.
The operations of left and right division are so-called because the quotient is obtained by dividing a on that side by b.
Operations rightQuotientrightQuotientLinearOrdinaryDifferentialOperator1 and rightRemainderrightRemainderLinearOrdinaryDifferentialOperator1 are available if only one of the quotient or remainder are of interest to you. This is the quotient from right division.
This is the remainder from right division. The corresponding ``left'' functions leftQuotientleftQuotientLinearOrdinaryDifferentialOperator1 and leftRemainderleftRemainderLinearOrdinaryDifferentialOperator1 are also available.
For exact division, the operations leftExactQuotientleftExactQuotientLinearOrdinaryDifferentialOperator1 and rightExactQuotientrightExactQuotientLinearOrdinaryDifferentialOperator1 are supplied. These return the quotient but only if the remainder is zero. The call rightExactQuotient(a,b) would yield an error.
The division operations allow the computation of left and right greatest common divisors (leftGcdleftGcdLinearOrdinaryDifferentialOperator1 and rightGcdrightGcdLinearOrdinaryDifferentialOperator1) via remainder sequences, and consequently the computation of left and right least common multiples (rightLcmrightLcmLinearOrdinaryDifferentialOperator1 and leftLcmleftLcmLinearOrdinaryDifferentialOperator1).
Note that a greatest common divisor doesn't necessarily divide a and b on both sides. Here the left greatest common divisor does not divide a on the right.
Similarly, a least common multiple is not necessarily divisible from both sides.
LinearOrdinaryDifferentialOperator2(A, M) is the domain of linear ordinary differential operators with coefficients in the differential ring A and operating on M, an A-module. This includes the cases of operators which are polynomials in D acting upon scalar or vector expressions of a single variable. The coefficients of the operator polynomials can be integers, rational functions, matrices or elements of other domains.
This example shows differential operators with rational number coefficients operating on univariate polynomials.
We begin by making type assignments so we can conveniently refer to univariate polynomials in x over the rationals.
Now we assign Dx to be the differential operator DDLinearOrdinaryDifferentialOperator2 corresponding to d/dx.
New operators are created as polynomials in D().
To apply the operator a to the value p the usual function call syntax is used.
Operator multiplication is defined by the identity (a*b) p = a(b(p))
Exponentiation follows from multiplication.
Finally, note that operator expressions may be applied directly.
This is another example of linear ordinary differential operators with non-commutative multiplication. Unlike the rational function case, the differential ring of square matrices (of a given dimension) with univariate polynomial entries does not form a field. Thus the number of operations available is more limited.
In this section, the operators have three by three matrix coefficients with polynomial entries.
The operators act on the vectors considered as a Mat-module.
The matrix m is used as a coefficient and the vectors p and q are operated upon.
Now form a few operators.
These operators can be applied to vector values.
A list is a finite collection of elements in a specified order that can contain duplicates. A list is a convenient structure to work with because it is easy to add or remove elements and the length need not be constant. There are many different kinds of lists in Axiom, but the default types (and those used most often) are created by the List constructor. For example, there are objects of type List Integer, List Float and List Polynomial Fraction Integer. Indeed, you can even have List List List Boolean (that is, lists of lists of lists of Boolean values). You can have lists of any type of Axiom object.
The easiest way to create a list with, for example, the elements 2, 4, 5, 6 is to enclose the elements with square brackets and separate the elements with commas.
The spaces after the commas are optional, but they do improve the readability.
To create a list with the single element 1, you can use either [1] or the operation listlistList.
Once created, two lists k and m can be concatenated by issuing append(k,m). appendappendList does not physically join the lists, but rather produces a new list with the elements coming from the two arguments.
Use consconsList to append an element onto the front of a list.
To determine whether a list has any elements, use the operation empty?empty?List.
Alternatively, equality with the list constant nilnilList can be tested.
We'll use this in some of the following examples.
Each of the next four expressions extracts the firstfirstList element of k.
The last two forms generalize to k.i and k(i), respectively, where and n equals the length of k.
This length is calculated by #.
Performing an operation such as k.i is sometimes referred to as indexing into k or elting into k. The latter phrase comes about because the name of the operation that extracts elements is called elteltList. That is, k.3 is just alternative syntax for elt(k,3). It is important to remember that list indices begin with 1. If we issue k := [1,3,2,9,5] then k.4 returns 9. It is an error to use an index that is not in the range from 1 to the length of the list.
The last element of a list is extracted by any of the following three expressions.
This form computes the index of the last element and then extracts the element from the list.
We'll use this in some of the following examples.
List elements are reset by using the k.i form on the left-hand side of an assignment. This expression resets the first element of k to 999.
As with indexing into a list, it is an error to use an index that is not within the proper bounds. Here you see that k was modified.
The operation that performs the assignment of an element to a particular position in a list is called seteltseteltList. This operation is destructive in that it changes the list. In the above example, the assignment returned the value 999 and k was modified. For this reason, lists are called mutable objects: it is possible to change part of a list (mutate it) rather than always returning a new list reflecting the intended modifications.
Moreover, since lists can share structure, changes to one list can sometimes affect others.
Change the second element of m.
See, m was altered.
But what about k? It changed too!
An operation that is used frequently in list processing is that which returns all elements in a list after the first element.
Use the restrestList operation to do this.
To remove duplicate elements in a list k, use removeDuplicatesremoveDuplicatesList.
To get a list with elements in the order opposite to those in a list k, use reversereverseList.
To test whether an element is in a list, use member?member?List: member?(a,k) returns true or false depending on whether a is in k or not.
As an exercise, the reader should determine how to get a list containing all but the last of the elements in a given non-empty list k.reverse(rest(reverse(k))) works.
Certain lists are used so often that Axiom provides an easy way of constructing them. If n and m are integers, then expand [n..m] creates a list containing n, n+1, ... m. If n > m then the list is empty. It is actually permissible to leave off the m in the dot-dot construction (see below).
The dot-dot notation can be used more than once in a list construction and with specific elements being given. Items separated by dots are called segments.
Segments can be expanded into the range of items between the endpoints by using expandexpandSegment.
What happens if we leave off a number on the right-hand side of ..?
What is created in this case is a Stream which is a generalization of a list. See StreamXmpPage for more information.
Initialisations
All Lyndon words with a, b, c to order 3
All Lyndon words of with a, b, c to order 3 in flat list
All Lyndon words of with a, b to order 5
Let's try factoring
Checks and coercions
Initialisations
Let's make some trees
Query the trees
Coerce to the monoid
Check ordering
Navigate the tree
Check ordering
It is sometimes useful to be able to define a function given by the result of a calculation.
Suppose that you have obtained the following expression after several computations and that you now want to tabulate the numerical values of f for x between -1 and +1 with increment 0.1.
You could, of course, use the function evalevalExpression within a loop and evaluate expr twenty-one times, but this would be quite slow. A better way is to create a numerical function f such that f(x) is defined by the expression expr above, but without retyping expr! The package MakeFunction provides the operation functionfunctionMakeFunction which does exactly this.
Issue this to create the function f(x) given by expr.
To tabulate expr, we can now quickly evaluate f 21 times.
Use the list [x1,...,xn] as the third argument to functionfunctionMakeFunction to create a multivariate function f(x1,...,xn).
In the case of just two variables, they can be given as arguments without making them into a list.
Note that the functions created by functionfunctionMakeFunction are not limited to floating point numbers, but can be applied to any type for which they are defined.
For more information, see ugUserMakePage in Section ugUserMakeNumber .
Function are objects of type Mapping. In this section we demonstrate some library operations from the packages MappingPackage1, MappingPackage2, and MappingPackage3 that manipulate and create functions. Some terminology: a nullary function takes no arguments, a unary function takes one argument, and a binary function takes two arguments.
We begin by creating an example function that raises a rational number to an integer exponent.
The twisttwistMappingPackage3 operation transposes the arguments of a binary function. Here rewop(a, b) is power(b, a).
This is
Now we define square in terms of power.
The curryRightcurryRightMappingPackage3 operation creates a unary function from a binary one by providing a constant argument on the right.
Likewise, the curryLeftcurryLeftMappingPackage3 operation provides a constant argument on the left.
The constantRightconstantRightMappingPackage3 operation creates (in a trivial way) a binary function from a unary one: constantRight(f) is the function g such that g(a,b)= f(a).
Likewise, constantLeft(f) is the function g such that g(a,b)= f(b).
The currycurryMappingPackage2 operation makes a unary function nullary.
The * operation constructs composed functions.
Use the ** operation to create functions that are n-fold iterations of other functions.
This is a list of Mapping objects.
This is a list of applications of those functions.
Use the recurrecurMappingPackage1 operation for recursion:
g := recur f means g(n,x) == f(n,f(n-1,...f(1,x))).
This is a factorial function.
Constructed functions can be used within other functions.
This is
Here shiftfib is a unary function that modifies its argument.
By currying over the argument we get a function with private state.
The Matrix domain provides arithmetic operations on matrices and standard functions from linear algebra. This domain is similar to the TwoDimensionalArray domain, except that the entries for Matrix must belong to a Ring.
There are many ways to create a matrix from a collection of values or from existing matrices.
If the matrix has almost all items equal to the same value, use newnewMatrix to create a matrix filled with that value and then reset the entries that are different.
To change the entry in the second row, third column to 5, use seteltseteltMatrix.
An alternative syntax is to use assignment.
The matrix was destructively modified.
If you already have the matrix entries as a list of lists, use matrixmatrixMatrix.
If the matrix is diagonal, use diagonalMatrixdiagonalMatrixMatrix.
Use setRowsetRowMatrix and setColumnsetColumnMatrix to change a row or column of a matrix.
Use copycopyMatrix to make a copy of a matrix.
This is useful if you intend to modify a matrix destructively but want a copy of the original.
Use subMatrixsubMatrixMatrix to extract part of an existing matrix. The syntax is subMatrix(m, firstrow, lastrow, firstcol, lastcol).
To change a submatrix, use setsubMatrixsetsubMatrixMatrix.
If e is too big to fit where you specify, an error message is displayed. Use subMatrixsubMatrixMatrix to extract part of e, if necessary.
This changes the submatrix of d whose upper left corner is at the first row and second column and whose size is that of e.
Matrices can be joined either horizontally or vertically to make new matrices.
Use horizConcathorizConcatMatrix to append them side to side. The two matrices must have the same number of rows.
Use vertConcatvertConcatMatrix to stack one upon the other. The two matrices must have the same number of columns.
The operation transposetransposeMatrix is used to create a new matrix by reflection across the main diagonal.
Axiom provides both left and right scalar multiplication.
You can add, subtract, and multiply matrices provided, of course, that the matrices have compatible dimensions. If not, an error message is displayed.
This following product is defined but n * m is not.
The operations nrowsnrowsMatrix and ncolsncolsMatrix return the number of rows and columns of a matrix. You can extract a row or a column of a matrix using the operations rowrowMatrix and columncolumnMatrix. The object returned is a Vector.
Here is the third column of the matrix n.
You can multiply a matrix on the left by a ``row vector'' and on the right by a ``column vector.''
Of course, the dimensions of the vector and the matrix must be compatible or an error message is returned.
The operation inverseinverseMatrix computes the inverse of a matrix if the matrix is invertible, and returns "failed" if not.
This Hilbert matrix is invertible.
This matrix is not invertible.
The operation determinantdeterminantMatrix computes the determinant of a matrix provided that the entries of the matrix belong to a CommutativeRing.
The above matrix mm is not invertible and, hence, must have determinant 0.
The operation tracetraceSquareMatrix computes the trace of a square matrix.
The operation rankrankMatrix computes the rank of a matrix: the maximal number of linearly independent rows or columns.
The operation nullitynullityMatrix computes the nullity of a matrix: the dimension of its null space.
The operation nullSpacenullSpaceMatrix returns a list containing a basis for the null space of a matrix. Note that the nullity is the number of elements in a basis for the null space.
The operation rowEchelonrowEchelonMatrix returns the row echelon form of a matrix. It is easy to see that the rank of this matrix is two and that its nullity is also two.
For more information on related topics, see ugIntroTwoDimPage in Section ugIntroTwoDimNumber , ugProblemEigenPage in Section ugProblemEigenNumber , ugxFloatHilbertPage in Section ugxFloatHilbertNumber , PermanentXmpPage , VectorXmpPage , OneDimensionalArrayXmpPage , and TwoDimensionalArrayXmpPage .
The domain Multiset(R) is similar to Set(R) except that multiplicities (counts of duplications) are maintained and displayed. Use the operation multisetmultisetMultiset to create multisets from lists. All the standard operations from sets are available for multisets. An element with multiplicity greater than one has the multiplicity displayed first, then a colon, and then the element.
Create a multiset of integers.
The operation insert! adds an element to a multiset.
Use remove! to remove an element. If a third argument is present, it specifies how many instances to remove. Otherwise all instances of the element are removed. Display the resulting multiset.
The operation count returns the number of copies of a given value.
A second multiset.
The union of two multisets is additive.
The intersect operation gives the elements that are in common, with additive multiplicity.
The difference of s and t consists of the elements that s has but t does not. Elements are regarded as indistinguishable, so that if s and t have any element in common, the difference does not contain that element.
The symmetricDifference is the union of difference(s, t) and difference(t, s).
Check that the union of the symmetricDifference and the intersect equals the union of the elements.
Check some inclusion relations.
The domain constructor MultivariatePolynomial is similar to Polynomial except that it specifies the variables to be used. Polynomial are available for MultivariatePolynomial. The abbreviation for MultivariatePolynomial is MPOLY. The type expressions
and
refer to the domain of multivariate polynomials in the variables x and y where the coefficients are restricted to be integers. The first variable specified is the main variable and the display of the polynomial reflects this.
This polynomial appears with terms in descending powers of the variable x.
It is easy to see a different variable ordering by doing a conversion.
You can use other, unspecified variables, by using Polynomial in the coefficient type of MPOLY.
Conversions can be used to re-express such polynomials in terms of the other variables. For example, you can first push all the variables into a polynomial with integer coefficients.
Now pull out the variables of interest.
Restriction:
Axiom does not allow you to create types where MultivariatePolynomial is contained in the coefficient type of Polynomial. Therefore, MPOLY([x,y],POLY INT) is legal but POLY MPOLY([x,y],INT) is not.
.
Multivariate polynomials may be combined with univariate polynomials to create types with special structures.
This is a polynomial in x whose coefficients are quotients of polynomials in y and z.
Use conversions for structural rearrangements. z does not appear in a denominator and so it can be made the main variable.
Or you can make a multivariate polynomial in x and z whose coefficients are fractions in polynomials in y.
A conversion like q :: MPOLY([x,y], FRAC UP(z,INT)) is not possible in this example because y appears in the denominator of a fraction. As you can see, Axiom provides extraordinary flexibility in the manipulation and display of expressions via its conversion facility.
For more information on related topics, see PolynomialXmpPage , UnivariatePolynomialXmpPage , and DistributedMultivariatePolynomialXmpPage .
The None domain is not very useful for interactive work but it is provided nevertheless for completeness of the Axiom type system.
Probably the only place you will ever see it is if you enter an empty list with no type information.
Such an empty list can be converted into an empty list of any other type.
If you wish to produce an empty list of a particular type directly, such as List NonNegativeInteger, do it this way.
The Octonions, also called the Cayley-Dixon algebra, defined over a commutative ring are an eight-dimensional non-associative algebra. Their construction from quaternions is similar to the construction of quaternions from complex numbers (see QuaternionXmpPage ).
As Octonion creates an eight-dimensional algebra, you have to give eight components to construct an octonion.
Or you can use two quaternions to create an octonion.
You can easily demonstrate the non-associativity of multiplication.
As with the quaternions, we have a real part, the imaginary parts i, j, k, and four additional imaginary parts E, I, J and K. These parts correspond to the canonical basis (1,i,j,k,E,I,J,K).
For each basis element there is a component operation to extract the coefficient of the basis element for a given octonion.
A basis with respect to the quaternions is given by (1,E). However, you might ask, what then are the commuting rules? To answer this, we create some generic elements.
We do this in Axiom by simply changing the ground ring from Integer to Polynomial Integer.
Note that quaternions are automatically converted to octonions in the obvious way.
Finally, we check that the normnormOctonion, defined as the sum of the squares of the coefficients, is a multiplicative map.
Since the result is 0, the norm is multiplicative.
The OneDimensionalArray domain is used for storing data in a one-dimensional indexed data structure. Such an array is a homogeneous data structure in that all the entries of the array must belong to the same Axiom domain. Each array has a fixed length specified by the user and arrays are not extensible. The indexing of one-dimensional arrays is one-based. This means that the ``first'' element of an array is given the index 1. See also VectorXmpPage and FlexibleArrayXmpPage .
To create a one-dimensional array, apply the operation oneDimensionalArray to a list.
Another approach is to first create a, a one-dimensional array of 10 0's. OneDimensionalArray has the convenient abbreviation ARRAY1.
Set each ith element to i, then display the result.
Square each element by mapping the function onto each element.
Reverse the elements in place.
Swap the 4th and 5th element.
Sort the elements in place.
Create a new one-dimensional array b containing the last 5 elements of a.
Replace the first 5 elements of a with those of b.