Joe Riel

9660 Reputation

23 Badges

20 years, 3 days

MaplePrimes Activity


These are replies submitted by Joe Riel

The technique, which is not readily found in the Maple help pages, is to use the member selection operator (:-) to select the global name rather than the local name:
f := proc(A)
local Q;
  Q := LinearAlgebra:-JordanForm(A, 'output' = ':-Q');
  Q . Q;  # just to show you can use the local variable
end proc:
See the ?colondash help page. The third bullet explains this usage.

The frontend command is a bit tricky. The basic idea is that it replaces expressions in the arguments to a procedure with names, evaluates the procedure with the replaced arguments, then back-substitutes the expressions for the the names in the final result. The first argument passed to frontend is the procedure that is to be evaluated. The second argument is a list containing the arguments to be passed to the procedure. Remaining arguments are optional, we'll get to those in a second. Suppose that we are given the expression

y := cos(x) + 3*a*x^2:

and we want the coefficient of the x^2 term (3*a). We might try using coeff:

coeff(y, x^2)
Error, unable to compute coeff

That fails because y is not a polynomial in x. The frontend command can be used here:

frontend(coeff, [y,x^2]);
                                   3*a

To get a better handle on how this works, I'll create a modified version of frontend, called Frontend:

 Frontend := proc(f) frontend( proc() printf("%a\n",'f(args)'); f(args) end proc, _rest) end proc:

This version prints what the actual call looks like, before evaluating it:

Frontend(coeff, [y,x^2]);
coeff(O+3*a*x^2,x^2)
                                      3 a

Here we see that the actual call to coeff is coeff(O+3*a*x^2,x^2). This is clearly a polynomial in x, so coeff is able to return the desired result. You are probably wondering what the 'O' is doing in the expression. That is a frozen version of the expression cos(x). Let's try a slightly different example:

Frontend(coeff, [cos(x)+sin(x)+5*x^2,x^2]);
coeff(O+O+5*x^2,x^2)
                                       5

This time the first argument passed to coeff is O+O+5*x^2. The two O's are frozen expressions for cos(x) and sin(x). While they look the same, they are actually different names to Maple. Now let's examine the optional third argument to frontend. It must be a list of exactly two sets. By default, this argument has the value [{`+`,`*`},{}], which means that sums and products are not frozen. The first set in the list is a set of types. Any subexpressions in the list of arguments that match these types are not frozen. Let's see this in action:

 Frontend(coeff, [a*cos(x)+b*sin(x)+c*x^2, x^2], [{`+`},{}]);
coeff(O+O+O,x^2)
                                       0

Unlike the default, subexpressions of type `*` are frozen. That leads to an error, since the c*x^2 term was frozen. One way to avoid that is to include the term x^2 in the second set of the third argument. Expressions in the second set are not frozen (the first set consists of types not to freeze, the second set consists of expressions not to freeze.

 Frontend(coeff, [a*cos(x)+b*sin(x)+c*x^2, x^2], [{`+`},{x^2}]);
coeff(O+O+c*x^2,x^2)
                                       c

Now try calling frontend with the coefficient of x^2 set to 1 and without including x^2 in the set of expression not to freeze.

Frontend(coeff, [a*cos(x)+b*sin(x)+x^2, x^2], [{`+`},{}]);

coeff(O+O+x^2,x^2)
                                       1

Notice that the x^2 term was not frozen. frontend never freezes, as a single expression, an exponent of an integer. That includes an expression of the form 1/expr, which is represented internally in Maple as expr^(-1). With that in mind, we now return to the original problem, which was computing the eigenvectors of a Matrix of functional expressions. First, let's pass use the default third argument:

Frontend(LinearAlgebra:-Eigenvectors,[<,<0|f(b)>>]);
LinearAlgebra:-Eigenvectors(O)
Error, (in LinearAlgebra:-Eigenvectors) invalid input:
LinearAlgebra:-Eigenvectors expects its 1st argument, A, to be of type
Matrix(square) but received O

That didn't work. We need to prevent frontend from freezing the complete Matrix. To do that, include the type Matrix in the set of types that are not to be frozen.

 Frontend(LinearAlgebra:-Eigenvectors,[<,<0|f(b)>>],[{Matrix},{}]);
LinearAlgebra:-Eigenvectors(Matrix(2, 2, [[O,0],[0,O]]))
                               [f(b)]  [0    1]
                               [    ], [      ]
                               [f(a)]  [1    0]

That works. Consider a slightly more complicated case:

Frontend(LinearAlgebra:-Eigenvalues,[<,>],[{Matrix},{}]);
LinearAlgebra:-Eigenvalues(Matrix(2, 2, [[O,O],[O,O]]))
    [
    [f(b) + 1/2 f(a)

                2                                       2               1/2]
     + 1/2 (f(b)  - 2 f(b) (f(a) + f(b)) + (f(a) + f(b))  + 4 f(b) f(a))   ]

    [
    [f(b) + 1/2 f(a)

                2                                       2               1/2]
     - 1/2 (f(b)  - 2 f(b) (f(a) + f(b)) + (f(a) + f(b))  + 4 f(b) f(a))   ]

That is correct, but the result is more complicated than necessary because frontend froze the polynomials inside the Matrix. To prevent that we can include the sum and product types in the set of types not to freeze, along with Matrix:

Frontend(LinearAlgebra:-Eigenvalues,[<,>],[{Matrix,`+`,`*`},{}]);
LinearAlgebra:-Eigenvalues(Matrix(2, 2, [[O+O,O],[O,O]]))
               [                                         2 1/2]
               [f(b) + 1/2 f(a) + 1/2 (4 f(b) f(a) + f(a) )   ]
               [                                              ]
               [                                         2 1/2]
               [f(b) + 1/2 f(a) - 1/2 (4 f(b) f(a) + f(a) )   ]

The frontend command is a bit tricky. The basic idea is that it replaces expressions in the arguments to a procedure with names, evaluates the procedure with the replaced arguments, then back-substitutes the expressions for the the names in the final result. The first argument passed to frontend is the procedure that is to be evaluated. The second argument is a list containing the arguments to be passed to the procedure. Remaining arguments are optional, we'll get to those in a second. Suppose that we are given the expression

y := cos(x) + 3*a*x^2:

and we want the coefficient of the x^2 term (3*a). We might try using coeff:

coeff(y, x^2)
Error, unable to compute coeff

That fails because y is not a polynomial in x. The frontend command can be used here:

frontend(coeff, [y,x^2]);
                                   3*a

To get a better handle on how this works, I'll create a modified version of frontend, called Frontend:

 Frontend := proc(f) frontend( proc() printf("%a\n",'f(args)'); f(args) end proc, _rest) end proc:

This version prints what the actual call looks like, before evaluating it:

Frontend(coeff, [y,x^2]);
coeff(O+3*a*x^2,x^2)
                                      3 a

Here we see that the actual call to coeff is coeff(O+3*a*x^2,x^2). This is clearly a polynomial in x, so coeff is able to return the desired result. You are probably wondering what the 'O' is doing in the expression. That is a frozen version of the expression cos(x). Let's try a slightly different example:

Frontend(coeff, [cos(x)+sin(x)+5*x^2,x^2]);
coeff(O+O+5*x^2,x^2)
                                       5

This time the first argument passed to coeff is O+O+5*x^2. The two O's are frozen expressions for cos(x) and sin(x). While they look the same, they are actually different names to Maple. Now let's examine the optional third argument to frontend. It must be a list of exactly two sets. By default, this argument has the value [{`+`,`*`},{}], which means that sums and products are not frozen. The first set in the list is a set of types. Any subexpressions in the list of arguments that match these types are not frozen. Let's see this in action:

 Frontend(coeff, [a*cos(x)+b*sin(x)+c*x^2, x^2], [{`+`},{}]);
coeff(O+O+O,x^2)
                                       0

Unlike the default, subexpressions of type `*` are frozen. That leads to an error, since the c*x^2 term was frozen. One way to avoid that is to include the term x^2 in the second set of the third argument. Expressions in the second set are not frozen (the first set consists of types not to freeze, the second set consists of expressions not to freeze.

 Frontend(coeff, [a*cos(x)+b*sin(x)+c*x^2, x^2], [{`+`},{x^2}]);
coeff(O+O+c*x^2,x^2)
                                       c

Now try calling frontend with the coefficient of x^2 set to 1 and without including x^2 in the set of expression not to freeze.

Frontend(coeff, [a*cos(x)+b*sin(x)+x^2, x^2], [{`+`},{}]);

coeff(O+O+x^2,x^2)
                                       1

Notice that the x^2 term was not frozen. frontend never freezes, as a single expression, an exponent of an integer. That includes an expression of the form 1/expr, which is represented internally in Maple as expr^(-1). With that in mind, we now return to the original problem, which was computing the eigenvectors of a Matrix of functional expressions. First, let's pass use the default third argument:

Frontend(LinearAlgebra:-Eigenvectors,[<,<0|f(b)>>]);
LinearAlgebra:-Eigenvectors(O)
Error, (in LinearAlgebra:-Eigenvectors) invalid input:
LinearAlgebra:-Eigenvectors expects its 1st argument, A, to be of type
Matrix(square) but received O

That didn't work. We need to prevent frontend from freezing the complete Matrix. To do that, include the type Matrix in the set of types that are not to be frozen.

 Frontend(LinearAlgebra:-Eigenvectors,[<,<0|f(b)>>],[{Matrix},{}]);
LinearAlgebra:-Eigenvectors(Matrix(2, 2, [[O,0],[0,O]]))
                               [f(b)]  [0    1]
                               [    ], [      ]
                               [f(a)]  [1    0]

That works. Consider a slightly more complicated case:

Frontend(LinearAlgebra:-Eigenvalues,[<,>],[{Matrix},{}]);
LinearAlgebra:-Eigenvalues(Matrix(2, 2, [[O,O],[O,O]]))
    [
    [f(b) + 1/2 f(a)

                2                                       2               1/2]
     + 1/2 (f(b)  - 2 f(b) (f(a) + f(b)) + (f(a) + f(b))  + 4 f(b) f(a))   ]

    [
    [f(b) + 1/2 f(a)

                2                                       2               1/2]
     - 1/2 (f(b)  - 2 f(b) (f(a) + f(b)) + (f(a) + f(b))  + 4 f(b) f(a))   ]

That is correct, but the result is more complicated than necessary because frontend froze the polynomials inside the Matrix. To prevent that we can include the sum and product types in the set of types not to freeze, along with Matrix:

Frontend(LinearAlgebra:-Eigenvalues,[<,>],[{Matrix,`+`,`*`},{}]);
LinearAlgebra:-Eigenvalues(Matrix(2, 2, [[O+O,O],[O,O]]))
               [                                         2 1/2]
               [f(b) + 1/2 f(a) + 1/2 (4 f(b) f(a) + f(a) )   ]
               [                                              ]
               [                                         2 1/2]
               [f(b) + 1/2 f(a) - 1/2 (4 f(b) f(a) + f(a) )   ]
The standard command line version of maple has this ability (the -l option engages it). See the latex_filter help page.
Hmm. On second thought my suggestions may not work for the Maple 10 version of ImageTools. It doesn't have the View command, though it does have a Preview command (substantially slower, alas). Create is also different, the newer version has more options (like format and copy). You can, however, use the Matrix command to change a grayscale image to a Matrix:
img := Matrix(img);
Hmm. On second thought my suggestions may not work for the Maple 10 version of ImageTools. It doesn't have the View command, though it does have a Preview command (substantially slower, alas). Create is also different, the newer version has more options (like format and copy). You can, however, use the Matrix command to change a grayscale image to a Matrix:
img := Matrix(img);
MapleV-mode can talk directly to command-line maple. For example, to send the current buffer to cmaple, use the maplev-cmaple-send-buffer command, which is mapped to C-c C-c b. Use C-c C-c g to goto (pop to) that buffer. You will probably have to configure your .emacs file to tell it where the maple executables lie. Do you use the mint commands with maplev-mode (C-c ret [b p])? I find them especially useful for eliminating errors.
Do you mean maple-mode or maplev-mode (that's the one I wrote). If the latter, don't be shy about suggesting improvements or complaining about deficiencies. Alas, my ISP, on which I had a home page, went away a few months ago and I haven't got around to getting another to distribute the source for maplev-mode. Maybe I'll put it here.
The StringTools:-Join command is what you want. By default it joins symbols or strings in a list to create a string, separating the words with a space. The optional second argument is the string used to join the words. In your case you want an empty string:
lst := [a,a,c]:
StringTools:-Join(lst,"");
                            "aac"
You can also use cat, as J. Tarr pointed out. If you make the first argument the empty string, the result will be a string, not a symbol (and vice-versa, when catenating strings, if the first argument is the blank symbol, ``). No need to use seq, just unlist the list with the empty selection operator ([], see ?selection):
cat("", lst[]);
                 "aac"
While it doesn't directly apply to this problem, you might look at StringTools[Permute].
Maple rtables are not subject to "last name evaluation." See ?last_name_eval for a description of this concept. However, Maple rtables are passed by reference, so Roman's example works as intended. Also Maple arrays and matrices, which differ from Arrays and Matrices, are not initialized to zero:
m := matrix(2,2):
M := Matrix(2,2):
m[1,1],M[1,1];
                 m[1,1], 0
Maple rtables are not subject to "last name evaluation." See ?last_name_eval for a description of this concept. However, Maple rtables are passed by reference, so Roman's example works as intended. Also Maple arrays and matrices, which differ from Arrays and Matrices, are not initialized to zero:
m := matrix(2,2):
M := Matrix(2,2):
m[1,1],M[1,1];
                 m[1,1], 0
Concerning your final paragraph, you can easily work around it by reassigning the print routine for piecewise:
`print/piecewise` := proc() 'piecewise'(args) end proc:
printlevel := 10:
simplify(piecewise(x<0,1,x<1,2,3));
{--> enter PiecewiseTools:-Is, args = x < 0
...
                                          piecewise(x < 0, 1, x < 1, 2, 1 <= x, 3)
...
It is not true that modules do not save local assignments. That is, when a module is saved to a repository, assigments that define the current state of the local variables are also saved. The values of the local variables are restored when the module is loaded from the repository. The usual reason for using an initialization procedure (say ModuleLoad) is to assign global variables.
The URI that Scott gave is invalid. Regardless, the reason problem that the original poster is having a problem is that there is no Maple repository in the directory, so the call to savelib is merely writing a .m file. Using with on a .m file does not load the package. You can load it by doing
read "MyModule.m":
A better solution is to use LibraryTools:-Save, which will create an archive if one doesn't exist:
LibraryTools:-Save('MyModule', "/home/rno/math/maple/lib/mylib.mla"):
Here's a less efficient but more compact version, using a functional style of programming. A trivial advantage is that it is easier to add new verifications (I added record), since they only appear once.
VerifyTools:-AddVerification(
    'nested' = proc(x, y, ver:=NULL)
        whattype(x)=whattype(y)
        and ormap(t -> (x::t and verify(x,y,'t'('nested'(ver))))
                  , [Vector,Matrix,Array,array,set,list,relation,range,record])
        or verify(x, y, ver);
    end proc ):
First 179 180 181 182 183 184 185 Last Page 181 of 195