acer

32333 Reputation

29 Badges

19 years, 319 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are replies submitted by acer

The idea is that it's not necessary to reach and fix all the tutorials, to make an effect here. Not even most. Just some. The most "popular" ones, by google ranking, say. The one's which come up in the first 5 pages of google search results, say, would be a decent start.

Suggesting that all such tutorials in the world be edited, by anyone, would be a crazy idea. I wasn't suggesting that at all.

acer

The matrix/vector objects have last-name-eval, while Matrix/Vector objects do not. I don't see how this difference could not cause serious and possibly insurmountable difficulties in a wrapper approach.

It's also not just that people shouldn't use linalg because it's old syntax. It's also more awkward syntax. The idea is to show them the nicer, cleaner syntaxes. Wrapper approaches perpetuate things which are not pretty (LNE, evalm, `&*`, etc).

acer

I meant that Maplesoft might consider doing it. The tutorials, in particular, are mostly very elementary.

Of course, I do not know how many there are out there. But things get ranked in google for concrete reasons. The more high ranked linalg tutorials that get replaced with LinearAlgebra equivalents, then the better the first search results would become on average.

I just think that eight out of ten, as google search results pointing to the wrong packages, is a sign that some new action should be considered.

acer

Yes, that was one of my points. If the universities/colleges have not taken the time to update their tutorials, then someone could (likely, relatively easily) do it for them.

acer

Interesting.

With the menu-driven Postscript exporter in Classic, `-p/2` produces plusminus Pi/2 when using the SYMBOL font, but works OK and produces -Pi/2 with the programmatic exporter. But `-3p/2` produces plusminus in both.

A curious bug. I'm glad that adding a space after the minus sign was some sort of workaround.

acer

Interesting.

With the menu-driven Postscript exporter in Classic, `-p/2` produces plusminus Pi/2 when using the SYMBOL font, but works OK and produces -Pi/2 with the programmatic exporter. But `-3p/2` produces plusminus in both.

A curious bug. I'm glad that adding a space after the minus sign was some sort of workaround.

acer

You're very welcome. You caught the fact that when using the plotsetup command  (to specify the "ps" driver) the extra space after the minus sign may not be necessary, yes?

My first try would be to use Maple's Standard interface. Robert Israel's reply seemed nice (as usual).

I didn't see where you might have written why you prefer to use Classic over Standard. I use Standard with Worksheets instead of Documents, and 1D Maple input instead of 2D Math input (as the global defaults for all new sessions, configurable under the Options menus) when I want to use a GUI.

acer

You're very welcome. You caught the fact that when using the plotsetup command  (to specify the "ps" driver) the extra space after the minus sign may not be necessary, yes?

My first try would be to use Maple's Standard interface. Robert Israel's reply seemed nice (as usual).

I didn't see where you might have written why you prefer to use Classic over Standard. I use Standard with Worksheets instead of Documents, and 1D Maple input instead of 2D Math input (as the global defaults for all new sessions, configurable under the Options menus) when I want to use a GUI.

acer

Alec, I was not trying to trash anyone's code or cause offence. I am trying to figure out what was meant by the term "compiler". I see that Fred Lunnon also posted his code here on Mapleprimes, and specifically asked about suggestions for it.

Looking closer, it does not look appropriate to use Compiler:-Compile on the initbagperm procedure. That does indeed set up the arrays (which be switched to Arrays of a suitable datatype) which then get passed into procedure nextbagperm which does the hard work. So nextbagperm would be the natural Compiler target.

Initial experimentation indicates some speed-up buy using Compiler:-Compile. At least a factor of 5 at a smaller size. I've posted that as a reply to the original code as posted here on Mapleprimes.

acer

One would want to double-check the actual results, to make sure that each version of the code below produced the same thing.

Here is a run of three versions: the original nextbagperm, a "typed" nextbagperm, and a Maple-Compiled nextbagperm. The second is about seven times slower than the first. The third is about five times faster than the first.

    |\^/|     Maple 12 (X86 64 LINUX)
._|\|   |/|_. Copyright (c) Maplesoft, a division of Waterloo Maple Inc. 2008
 \  MAPLE  /  All rights reserved. Maple is a trademark of
 <____ ____>  Waterloo Maple Inc.
      |       Type ? for help.
> initbagperm := proc (rank)
> global  R_, P_, Q_, D_;
> local m, j, r, r_1, r_m;
> m := nops(rank); r := sort(rank);
> if m <= 0 then print(`bagperm: length <= 0`)
> else r_1, r_m := r[1], r[m];
> R_ := Array(0..m+3, [r_1-1, seq(r[j], j = 1..m), r_1-1, r_m+1, r_m+2],datatype=integer[4]);
> P_ := Array(0..m+3, [0, seq(j, j = 1..m), 0, m+1, m+2],datatype=integer[4]); # permed identities
> Q_ := Array(0..m+3, [0, seq(j, j = 1..m), m+2, m+3, 0],datatype=integer[4]); # inverse locations
> D_ := Array(0..m+3, [0, seq(+1, j = 1..m), 0, +1, +1],datatype=integer[4]); # permed drifts
> fi; NULL end:
>
> nextbagperm := proc (R_, P_, Q_, D_)
> local i, j, k, l, d, e, p;
# locate earliest unblocked element at j, starting at blocked element 0
> j, i, d := 0, 0, 0;
> while R_[j] >= R_[i] do
> D_[j] := -d; # blocked at j; reverse drift d pre-emptively
> j := Q_[P_[j]+1]; d := D_[j]; i := j+d; # next element at j, neighbour at i
> if R_[j-1] <> R_[j] then l := j # save left end of run in l
> elif d < 0 then i := l-1 fi od; # restore left end at head of run
# shift run of equal rank from i-d,i-2d,...,l to i,i-d,...,l+d
> k := i; if d < 0 then l := j fi;
> e := D_[i]; p := P_[i]; # save neighbour drift e and identifier p
> while k <> l do
> P_[k] := P_[k-d]; Q_[P_[k]] := k;
> D_[k] := -1; k := k-d od; # reset drifts of run tail elements
> R_[l], R_[i] := R_[i], R_[l]; # transpose user ranks
> D_[l], D_[i] := e, d; # restore drifts of head and neighbour
> P_[l], Q_[p] := p, l; # wrap neighbour around to other end
> j end:
>
> nextbagperm_typed := proc (R_::Array(0..18,datatype=integer[4]),
>                      P_::Array(0..18,datatype=integer[4]),
>                      Q_::Array(0..18,datatype=integer[4]),
>                      D_::Array(0..18,datatype=integer[4]))
> local i :: integer, j :: integer, k :: integer, l :: integer,
>       d :: integer, e :: integer, p :: integer;
# locate earliest unblocked element at j, starting at blocked element 0
> j, i, d := 0, 0, 0;
> while R_[j] >= R_[i] do
> D_[j] := -d; # blocked at j; reverse drift d pre-emptively
> j := Q_[P_[j]+1]; d := D_[j]; i := j+d; # next element at j, neighbour at i
> if R_[j-1] <> R_[j] then l := j # save left end of run in l
> elif d < 0 then i := l-1 fi od; # restore left end at head of run
# shift run of equal rank from i-d,i-2d,...,l to i,i-d,...,l+d
> k := i; if d < 0 then l := j fi;
> e := D_[i]; p := P_[i]; # save neighbour drift e and identifier p
> while k <> l do
> P_[k] := P_[k-d]; Q_[P_[k]] := k;
> D_[k] := -1; k := k-d od; # reset drifts of run tail elements
> R_[l], R_[i] := R_[i], R_[l]; # transpose user ranks
> D_[l], D_[i] := e, d; # restore drifts of head and neighbour
> P_[l], Q_[p] := p, l; # wrap neighbour around to other end
> j end:
>
> compiled_nextbagperm_typed := Compiler:-Compile(nextbagperm_typed):
>
> parts := [5, 5, 5]; # chosen partition of set
                              parts := [5, 5, 5]
 
> n := nops(parts): m := add(parts[i], i = 1..n): # length and weight
> symb := [seq(seq(i, j = 1..parts[i]), i = 1..n)]:
> cardi := combinat[multinomial](m, op(parts)): # number of bag-perms
>
> kernelopts(printbytes=false);
                                     true
 
>
> st:=time():
> initbagperm(symb, R_,P_,Q_,D_):
> n := 1: print(n, [seq(R_[i], i = 1..m)]):
               1, [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]
 
> while nextbagperm(R_,P_,Q_,D_) <= m and n < cardi + 2 do
>   n := n+1;
>   #print(n, [seq(R_[i], i = 1..m)]);
> od:
> print(n, cardi); # equal
                                756756, 756756
 
> time()-st;
                                    24.098
 
>
> st:=time():
> initbagperm(symb, R_,P_,Q_,D_):
> n := 1: print(n, [seq(R_[i], i = 1..m)]);
               1, [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]
 
> while nextbagperm_typed(R_,P_,Q_,D_) <= m and n < cardi + 2 do
>   n := n+1;
>   #print(n, [seq(R_[i], i = 1..m)]);
> od:
> print(n, cardi); # equal
                                756756, 756756
 
> time()-st;
                                    173.600
 
>
> st:=time():
> initbagperm(symb, R_,P_,Q_,D_):
> n := 1: print(n, [seq(R_[i], i = 1..m)]);
               1, [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]
 
> while compiled_nextbagperm_typed(R_,P_,Q_,D_) <= m and n < cardi + 2 do
>   n := n+1;
>   #print(n, [seq(R_[i], i = 1..m)]);
> od:
> print(n, cardi); # equal
                                756756, 756756
 
> time()-st;
                                     5.239

As one can see, I had a little difficulty with the sizes in the type-specification of the Array arguments to the nextbagperm procedure. If I did not hard code the size then Compile complained that the lower index started at 0 instead of 1. It may be that the code would need rewriting to be "1-based" instead of "0-based" for Array referencing, so that the Array size need not be supplied in the parameter type specification. I'd welcome any news that there is another way.

acer

One would want to double-check the actual results, to make sure that each version of the code below produced the same thing.

Here is a run of three versions: the original nextbagperm, a "typed" nextbagperm, and a Maple-Compiled nextbagperm. The second is about seven times slower than the first. The third is about five times faster than the first.

    |\^/|     Maple 12 (X86 64 LINUX)
._|\|   |/|_. Copyright (c) Maplesoft, a division of Waterloo Maple Inc. 2008
 \  MAPLE  /  All rights reserved. Maple is a trademark of
 <____ ____>  Waterloo Maple Inc.
      |       Type ? for help.
> initbagperm := proc (rank)
> global  R_, P_, Q_, D_;
> local m, j, r, r_1, r_m;
> m := nops(rank); r := sort(rank);
> if m <= 0 then print(`bagperm: length <= 0`)
> else r_1, r_m := r[1], r[m];
> R_ := Array(0..m+3, [r_1-1, seq(r[j], j = 1..m), r_1-1, r_m+1, r_m+2],datatype=integer[4]);
> P_ := Array(0..m+3, [0, seq(j, j = 1..m), 0, m+1, m+2],datatype=integer[4]); # permed identities
> Q_ := Array(0..m+3, [0, seq(j, j = 1..m), m+2, m+3, 0],datatype=integer[4]); # inverse locations
> D_ := Array(0..m+3, [0, seq(+1, j = 1..m), 0, +1, +1],datatype=integer[4]); # permed drifts
> fi; NULL end:
>
> nextbagperm := proc (R_, P_, Q_, D_)
> local i, j, k, l, d, e, p;
# locate earliest unblocked element at j, starting at blocked element 0
> j, i, d := 0, 0, 0;
> while R_[j] >= R_[i] do
> D_[j] := -d; # blocked at j; reverse drift d pre-emptively
> j := Q_[P_[j]+1]; d := D_[j]; i := j+d; # next element at j, neighbour at i
> if R_[j-1] <> R_[j] then l := j # save left end of run in l
> elif d < 0 then i := l-1 fi od; # restore left end at head of run
# shift run of equal rank from i-d,i-2d,...,l to i,i-d,...,l+d
> k := i; if d < 0 then l := j fi;
> e := D_[i]; p := P_[i]; # save neighbour drift e and identifier p
> while k <> l do
> P_[k] := P_[k-d]; Q_[P_[k]] := k;
> D_[k] := -1; k := k-d od; # reset drifts of run tail elements
> R_[l], R_[i] := R_[i], R_[l]; # transpose user ranks
> D_[l], D_[i] := e, d; # restore drifts of head and neighbour
> P_[l], Q_[p] := p, l; # wrap neighbour around to other end
> j end:
>
> nextbagperm_typed := proc (R_::Array(0..18,datatype=integer[4]),
>                      P_::Array(0..18,datatype=integer[4]),
>                      Q_::Array(0..18,datatype=integer[4]),
>                      D_::Array(0..18,datatype=integer[4]))
> local i :: integer, j :: integer, k :: integer, l :: integer,
>       d :: integer, e :: integer, p :: integer;
# locate earliest unblocked element at j, starting at blocked element 0
> j, i, d := 0, 0, 0;
> while R_[j] >= R_[i] do
> D_[j] := -d; # blocked at j; reverse drift d pre-emptively
> j := Q_[P_[j]+1]; d := D_[j]; i := j+d; # next element at j, neighbour at i
> if R_[j-1] <> R_[j] then l := j # save left end of run in l
> elif d < 0 then i := l-1 fi od; # restore left end at head of run
# shift run of equal rank from i-d,i-2d,...,l to i,i-d,...,l+d
> k := i; if d < 0 then l := j fi;
> e := D_[i]; p := P_[i]; # save neighbour drift e and identifier p
> while k <> l do
> P_[k] := P_[k-d]; Q_[P_[k]] := k;
> D_[k] := -1; k := k-d od; # reset drifts of run tail elements
> R_[l], R_[i] := R_[i], R_[l]; # transpose user ranks
> D_[l], D_[i] := e, d; # restore drifts of head and neighbour
> P_[l], Q_[p] := p, l; # wrap neighbour around to other end
> j end:
>
> compiled_nextbagperm_typed := Compiler:-Compile(nextbagperm_typed):
>
> parts := [5, 5, 5]; # chosen partition of set
                              parts := [5, 5, 5]
 
> n := nops(parts): m := add(parts[i], i = 1..n): # length and weight
> symb := [seq(seq(i, j = 1..parts[i]), i = 1..n)]:
> cardi := combinat[multinomial](m, op(parts)): # number of bag-perms
>
> kernelopts(printbytes=false);
                                     true
 
>
> st:=time():
> initbagperm(symb, R_,P_,Q_,D_):
> n := 1: print(n, [seq(R_[i], i = 1..m)]):
               1, [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]
 
> while nextbagperm(R_,P_,Q_,D_) <= m and n < cardi + 2 do
>   n := n+1;
>   #print(n, [seq(R_[i], i = 1..m)]);
> od:
> print(n, cardi); # equal
                                756756, 756756
 
> time()-st;
                                    24.098
 
>
> st:=time():
> initbagperm(symb, R_,P_,Q_,D_):
> n := 1: print(n, [seq(R_[i], i = 1..m)]);
               1, [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]
 
> while nextbagperm_typed(R_,P_,Q_,D_) <= m and n < cardi + 2 do
>   n := n+1;
>   #print(n, [seq(R_[i], i = 1..m)]);
> od:
> print(n, cardi); # equal
                                756756, 756756
 
> time()-st;
                                    173.600
 
>
> st:=time():
> initbagperm(symb, R_,P_,Q_,D_):
> n := 1: print(n, [seq(R_[i], i = 1..m)]);
               1, [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]
 
> while compiled_nextbagperm_typed(R_,P_,Q_,D_) <= m and n < cardi + 2 do
>   n := n+1;
>   #print(n, [seq(R_[i], i = 1..m)]);
> od:
> print(n, cardi); # equal
                                756756, 756756
 
> time()-st;
                                     5.239

As one can see, I had a little difficulty with the sizes in the type-specification of the Array arguments to the nextbagperm procedure. If I did not hard code the size then Compile complained that the lower index started at 0 instead of 1. It may be that the code would need rewriting to be "1-based" instead of "0-based" for Array referencing, so that the Array size need not be supplied in the parameter type specification. I'd welcome any news that there is another way.

acer

This order of this thread is a little mixed up. But this comment above may help.

acer

This order of this thread is a little mixed up. But this comment above may help.

acer

What is the "compiler" that gets mentioned on that page? Maple uses an interpreter, and doesn't (normally) compile code. Since the usual (not evalhf) Maple interpreter doesn't compile (not even just in time), it doesn't seem surprising to me that adding type-checks incurs extra runtime cost. It seems like a misunderstanding about how Maple works. That's not any disparagement -- Fred Lunnon did not create Maple in the way that Knuth wrote TeX.

Maple did get a Compiler routine, a few years ago. But Compiler:-Compile doesn't know how to handle that code, as it stands. (The Compiler knows about Arrays, but not arrays. And it might be more feasible to have the procedure accept the Arrays as arguments, since the Compiler doesn't know how to handle indeterminate index ranges like 0..m+3.)

With a little work, an edited version of the procedure (possibly running inside a wrapping procedure that sets up the Arrays) might be done. I would expect that to get a speed-up of something like a factor of 10-25 or so, for the sub-parts that are "Compilable". One would have to hit it explicitly with Compiler:-Compile.

acer

If I changed elements like `-p/2` to `- p/2`, with a space after the minus sign, then it appeared better in the exported .eps file. The symbol showed as minus rather than plusminus, and the extra whitespace didn't seem too glaring.

But then I tried something else. There is also a programmatic way to export the plot. before the display call, I added this command,

plotsetup(ps,plotoutput=`foo.eps`,plotoptions=`portrait,noborder`);

That command will make plots get written directly to the file. The plot won't also appear visually. Using the exporter, I found that the original syntax you used of `-p/2` would come out with the correct minus sign in the .eps file.

I used ghostview to preview the .eps file, rather than embedding it into latex.

Is the "90 degree rotation" issue just one of portrait versus landscape, for Postscript?

It's fun, no, that Maple has (at least) three distinct Postscript converters? (Ie, the menu driven one in Standard, the menu driven one in Classic, and that programmatic command available in each interface.)

The command plotsetup(default) will reset the plot device to its original default setting (ie, visual display of plots).

acer

First 511 512 513 514 515 516 517 Last Page 513 of 591