Joe Riel

9660 Reputation

23 Badges

20 years, 4 days

MaplePrimes Activity


These are answers submitted by Joe Riel

You cannot execute Maple worksheets (files with extension .mw, or the older .mws) in command-line maple.  You can, however, export the contents of a worksheet as Maple input (select the "maple input (.mpl)" option from the "File Type" in the "Export As" dialog box and then execute the resulting file using the command maple filename.mpl.  You might want to use the -F option to prevent maple from exiting when it gets to the end of the file.

There is no switch/case statement in Maple.  Use the if then construct.  For clarity I occasionally swap the left and right sides of the equation so that the case shows up first:

if   a1 = a then
elif a2 = a then
elif a3 = a then
...
end if

Here's a version that uses the deprecated networks package instead of GraphTheory.  It ran on Maple11; I don't have Maple10 lying around for a quick check.  I'm not sure whether Maple10 supports the 'nolist' option to indices, which is used in a couple of places.  You can do the same with a map(op, {indices(...)}) call.  I also modified the routine to return routes starting from any edge.

Addendum: Maple10 might not support the use of _rest.  If not, use args[3..-1] in place of it.

Addendum: Rather than calling {indices(...,'nolist')}, a nicer solution is to assign a local variable Vertices and use it in place of those calls.  Do  Vertices := {cat(``,"a".."d",1..4)}.

module route()

local sides,Side,i,s,G,Route,cnt;
export connect, ModuleApply;

    sides := {a,b,c,d};
    Side := table();

    # Generate table Side mapping vertices to sides
    for i to 4 do
        for s in sides do
            Side[cat(s,i)] := s;
        end do;
    end do;

    # Create Graph

    G := networks['new']();
    networks['addvertex']({indices(Side,'nolist')},G);
    networks['addedge']({NULL
                         , seq({a2,b||j}, j=1..4)
                         , seq({a2,c||m}, m=1..4)
                         , seq({a3,d||n}, n=1..4)
                         , seq({b3,c||m}, m=1..4)
                         , seq({b3,d||n}, n=1..4)
                         , seq({b4,a||i}, i=1..4)
                         , seq({c1,b||j}, j=1..4)
                         , seq({c4,a||i}, i=1..4)
                         , seq({c4,d||n}, n=1..4)
                         , seq({d1,a||i}, i=1..4)
                         , seq({d1,b||j}, j=1..4)
                         , seq({d2,c||m}, m=1..4)
                        }
                        , G );

    connect := proc(V, S::set)
    local s,n,v;
        if S = {} then
            cnt := cnt+1;
            Route[cnt] := [_rest];
        end if;
        if V :: 'set' then
            for v in V do
                procname(v,S minus {Side[v]}, _rest);
            end do;
        else
            for n in networks['departures'](V,G) do
                s := Side[n];
                if not s in S then
                    next;
                end if;
                procname(n, S minus {s}, _rest, n);
            end do;
        end if;
    end proc;

    ModuleApply := proc()
    local v,i;
        cnt := 0;
        Route := 'Route';
        connect({indices(Side,'nolist')}, sides);
        [seq(Route[i], i=1..cnt)];
    end proc;

end module:

route();
nops(%);

Alec's brute-force technique is compact, but wouldn't scale very well.  Here's a somewhat better approach.  While not necessary, I used GraphTheory to create a graph, however, the recursive routine that computes the routes only uses it for the Neighbors export.  This returns 1/4 the number that Alec's does because I restricted the solution to starting at edge a.  I assume that the edges are undirected.

module route()

local sides,Side,i,s,G,cnt,Route;
export connect, ModuleApply;

    sides := [a,b,c,d];
    Side := table();

    # Generate table Side mapping vertices to sides
    for i to 4 do
        for s in sides do
            Side[cat(s,i)] := s;
        end do;
    end do;

    # Create Graph

    G := GraphTheory:-Graph({NULL
                             , seq({a2,b||j}, j=1..4)
                             , seq({a2,c||m}, m=1..4)
                             , seq({a3,d||n}, n=1..4)
                             , seq({b3,c||m}, m=1..4)
                             , seq({b3,d||n}, n=1..4)
                             , seq({b4,a||i}, i=1..4)
                             , seq({c1,b||j}, j=1..4)
                             , seq({c4,a||i}, i=1..4)
                             , seq({c4,d||n}, n=1..4)
                             , seq({d1,a||i}, i=1..4)
                             , seq({d1,b||j}, j=1..4)
                             , seq({d2,c||m}, m=1..4)
                            });

    connect := proc(v, S::set)
    local s,n;
    uses GraphTheory;
        if S = {} then
            cnt := cnt+1;
            Route[cnt] := [_rest];
        end if;
        for n in Neighbors(G,v) do
            s := Side[n];
            if not s in S then
                next;
            end if;
            procname(n, S minus {s}, _rest, n);
        end do;
    end proc;

    ModuleApply := proc()
    local v;
        cnt := 0;
        Route := table();
        for v in [cat(a,1..4)] do
            connect(v, {b,c,d}, v);
        end do;
        (cnt, eval(Route));
    end proc;

end module:

(cnt,Routes) := route();
convert(Routes,'list');

Without questions this site would be much less useful, and less interesting.  A good question elicits good responses, and is just as valuable.

Is alpha really the polynomial you want as the output?  A better example would have made this much clearer, say,

  polyString := "3*x^2+x+1":

The usual method is to use parse:

  parse(polyString);

                  

You need additional structure, in particular, an inner product, on this functional space.  Do you have one?

Yes it can be done.  After saving the variables (you can use the save command, or higher level write commands), use the `stop` procedure (not the stop command).  It can be called from inside a procedure.  You'll probably  want Maple to restart automatically.  That, too, can be done with a shell script that looks at the exit code, which you can pass with `stop`.

If you happen to be using a version of Maple (say 10 or 11) on a machine that supports forking (*nix) there may be a relatively simple way to avoid the excessive memory allocation by using the fork procedure from the process package.  However, this procedure is not available in Maple 12.  The basic idea is that you run the code that allocates the large amount of memory in a separate process, returning the output to the main process via a pipe.  You will need to kill and restart that process if it allocates too much memory.  You might look at my Tine package, which uses this technique to measure memory allocation and also provides a few commands to simplify calling a procedure in a transient forked process to avoid excessive memory allocation in the main process.

The best approach, however, might be to redesign your code to avoid the excessive memory allocation.

N.B. This has been completely rewritten.

On rethinking this, I realized that this can be improved by returning a Vector rather than a list.  That has two advantages: it saves memory (each new output is not inserted into Maple's Simplification table) and it is faster because we don't have to process every element (with a call to pointto).  It also permits using the Maple compiler to handle the core of algL.  Here is the rewrite. 

Note that I used a preprocessor directive, BytesPerWord, so that the source code could conceivably be used with 64 bit Maple; however, the use of a preprocessor directive means it will only work if run through command-line maple (my usual mode of working).  You can always manually replace the few occurrences of BytesPerWord with 4 for 32 bit Maple or 8 for 64 bit Maple.  I couldn't think of a nice way to declare the Arrays in ComputePerm so that using the preprocessor directive was not required.

$define BytesPerWord 4

Permute := module()
export ModuleApply, Permute;
local ComputePerm;

    ModuleApply := Permute;
    
    Permute := proc(L :: Or(set,list,posint,range(integer)))
    local u,n,A,V;
        
        if L :: 'posint' then return procname([seq(u, u = 1..L)]);
        elif L :: 'range' then return procname([seq(u, u = L)]);
        end if;
        
        n := nops(L);
        A := rtable(1..n, sort(map(addressof,convert(L,'list'))), 'datatype=integer[BytesPerWord]');
        V := rtable(1..n, i -> pointto(A[i]));
        
        module()
        export nextvalue, finished;
        local complete,cnt,P;
            
            cnt := 0;
            P := rtable(1..n,1..2, 'datatype=integer[BytesPerWord]');
            
            complete := evalb(n=0);
            finished := () -> complete;
            
            nextvalue := proc()
            local i,j,k;
                if complete then
                    error "attempt to call nextvalue on finished iterator";
                end if;
                
                # permute V per previous computation
       
                for i to cnt do
                    (j,k) := (P[i,1],P[i,2]);
                    (V[j], V[k]) := (V[k],V[j]);
                end do;
                cnt := ComputePerm(A,P,n);
                if cnt = 0 then complete := true end if;
                return V;
            end proc;
        end module;
    end proc:
    
    # This uses Algorithm L, pp 39-40, from
    # "The Art of Computer Programming," vol 4, fasicle 2,
    # "Generating all Tuples and Permutations", Donald Knuth
                
    ComputePerm := proc(A :: Array(datatype=integer[BytesPerWord])
                        , P :: Array(datatype = integer[BytesPerWord])
                        , n :: posint
                       )
        
    local j,k,l,cnt;
        
        for j from n-1 to 1 by -1 do
            if A[j+1] > A[j] then break; end if;
        end do;
        
        if j=0 then
            return 0;
        end if;
        
        for l from n by -1 do
            if A[l] > A[j] then break; end if;
        end do;
        
        (A[j],A[l]) := (A[l],A[j]);
        cnt := 1;
        P[1,1] := j;
        P[1,2] := l;
        
        l := n;
        for k from j+1 do
            if k >=l then break; end if;
            (A[k],A[l]) := (A[l],A[k]);
            cnt := cnt+1;
            P[cnt,1] := k;
            P[cnt,2] := l;
            l := l-1;
        end do;
        return cnt;
    end proc;
    
    ComputePerm := Compiler:-Compile(ComputePerm);
    
end module:

 

P := Permute([1,2,3]):
while not P:-finished() do printf("%d\n",P:-nextvalue()); end do;
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1


N := 10:
P := Permute([seq(1..N)]):
time(proc() while not P:-finished() do P:-nextvalue() end do end proc());

                                                     135.0

 

We resolved this offline. In the unlikely case this is of interest to any one else, the problem was that 'nil', indicating that no maple initialization file is specified, was missing from maplev-executable-alist (the missing 'nil' exists in the assignment shown in the original post).  Possibly an issue using customize-group, but I wasn't able to reproduce it. 

I'm curious, does it work on Maple 9 with a range or integer input?  I suspect it may not, I think that seq(1..3) wasn't added until Maple10, but am not sure and don't have Maple 9 quickly accessible. It would be easy enough for you to fix that, just modify the start, where ranges are converted to lists of integers (if you care).

Alvaro,

Do you use GNU Emacs or Xemacs?  I'll assume the former (which is almost required).  Do other parts of the mode appear to work (highlighting, auto-indentation, etc)?   Try running the emacs command maplev-mint-buffer directly:

M-x maplev-mint-buffer

where M-x means use the meta (alt) modifier key while pressing x.  If that works, then check what key it is mapped to (in a maplev buffer):

C-h w maplev-mint-buffer

 

Note that from Maple's perspective, it makes little sense to ask for permutations of a set.  All permutations of an unordered set are equal.  With that in mind, the following should do what you want.  It accepts either a set, a list, a posint, or a range of integers as input, but always returns lists.  Being somewhat lazy this morning, I originally wrote it to handle only integers, then to generalize it used the hackware procedures addressof and pointto.  It returns a module with two exports.  In that regard it is slightly different from combinat[cartprod], that is, the export finished is a procedure not a boolean value:

GeneratePermutations := proc(L :: Or(sequential,posint,range(integer)))

    if L :: 'posint' then
        return procname([seq(1..L)]);
    elif L :: 'range(integer)' then
        return procname([seq(L)]);
    end if;

    module()
    export nextvalue, finished;
    local complete,n,A;

        n := nops(L);
        A := rtable(1..n,sort(map(addressof,convert(L,'list'))));

        complete := `if`(L=[], true, false);
        finished := () -> complete;

        # This uses Algorithm L, pp 39-40, from
        # "The Art of Computer Programming," vol 4, fasicle 2,
        # "Generating all Tuples and Permutations", Donald Knuth

        nextvalue := proc()
        local a,j,k,l;

            if complete then
                error "attempt to call nextvalue on finished iterator";
            end if;

            a := map(pointto,convert(A,'list'));

            # update A

            for j from n-1 to 1 by -1 while A[j+1] <= A[j] do end do;
            if j=0 then
                complete := true;
                return a;
            end if;

            for l from n by -1 while A[l] <= A[j] do end do;
            (A[j],A[l]) := (A[l],A[j]);

            # reverse A[j=1]..A[n]
            l := n;
            for k from j+1 while k < l do
                (A[k],A[l]) := (A[l],A[k]);
                l := l-1;
            end do;

            return a;
        end proc;
    end module;
end proc:

Here is an example

P := GeneratePermutations([a,[1,2],[1,2]]):
while not P:-finished() do P:-nextvalue(); end do;
                              [a, [1, 2], [1, 2]]
                              [[1, 2], a, [1, 2]]
                              [[1, 2], [1, 2], a]

P := GeneratePermutations(2..4):
while not P:-finished() do P:-nextvalue(); end do;
                                   [2, 3, 4]
                                   [2, 4, 3]
                                   [3, 2, 4]
                                   [3, 4, 2]
                                   [4, 2, 3]
                                   [4, 3, 2]

You might want to look at the CodeTools[Profiling] subpackage.  Look at the help pages for Profile and PrintProfiles. Profiling is useful for  determining the sections that deserves the most attention.

See the help page for LinearAlgebra[MatrixInverse].  It can compute the Penrose pseudo-inverse.  The LinearAlgebra package also has IndentityMatrix and ZeroMatrix procedures.  See LinearAlgebra,Details for a table of all procedures.

First 93 94 95 96 97 98 99 Last Page 95 of 114