Joe Riel

9660 Reputation

23 Badges

20 years, 3 days

MaplePrimes Activity


These are replies submitted by Joe Riel

No, it took about 3 seconds. I multiplied the time from 1 to 10^7 by 90 to compute the time it should take (assuming linearity) to go from 10^8 to 10^9.
I apologize for the plug, but if you use emacs you could use my maplev-mode, which provides a reasonably nice interface to the tty help system. It font locks (colors) the various section headers, has a history mechanism, and also permits clicking on words/links to open another help page. I've considered embellishing the history mechanism so it returns to the same point on the page, but haven't got around to it (thanks for the encouragement). Naturally you can scroll up and down and use Emacs builtin search facility.
I'm curious as to how you ascertained the relative speed of these techniques---they do not agree with either my intuition or my timing. Actually, I've only looked at the first problem. Following is the code I used to time the four techniques, and a fifth method, which is far and away the fastest of the lot. While method 1 (incrementally building up a list) is certainly a loser, I did not expect method four, using assign, to be particularly fast, considering that assign is not a builtin. It wasn't in my timings. Here they are
num1 := proc(L)
local M,i;
    M := [];
    for i from 1 to nops(L) do
        M := [op(M), L[i]=i];
    end do;
    M
end proc:

num2 := proc(L)
local M,i;
    M := table():
    for i to nops(L) do
        M[i] := L[i]=i;
    end do:
    [seq(M[i], i=1..nops(L))];
end proc:

num3 := proc(L)
local M,i,j;
    M := table():
    j := 1:
    for i in L do
        M[j] := i=j;
        j := j+1;
    end do:
    [seq(M[i], i=1..nops(L))];
end proc:

num4 := proc(L)
local i,j;
    j := 1;
    [seq(i=`+`(j, assign('j', j+1)), i=L)];
end proc:

num5 := proc(L)
local i;
    [seq](L[i]=i,i=1..nops(L)):
end proc:

Time := proc(num,L,N)
local st;
    st := time();
    to N do
        num(L);
    end do;
    printf("%A = %A\n", num, time() -st)
end proc:

L := [$1..100000]:
N := 1:
#Time(num1, L, N);
Time(num2, L, N);
Time(num3, L, N);
Time(num4, L, N);
Time(num5, L, N);
num2 = .930
num3 = 1.210
num4 = 2.360
num5 = .260
As Roman suggests, you can use a list as the data structure to store the digits. However, entering them as lists might be painful, lots of additional typing required. Simpler for entry, after which you'd convert to a list format, would be strings, decimals, or names. Strings would probably be the best choice, they are robust and readily converted to lists of integers using StringTools:-Explode and parse:
upn := "0123456789":
map(parse, StringTools:-Explode(upn));
               [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Thanks for the suggestion. The procedure expand, however, is rather aggressive. To limit it, I could use frontend(expand,[a]), instead, at the start. That handles the particular example you gave while avoiding expanding, say, sin(a+b). I'll have to think about this.
This is an interesting technique. To see a benefit, I presume, the multiplication by the matrix must be done repeatedly for different vectors, otherwise the start-up cost is prohibitive. An obvious application is Matrix-Matrix multiplication. I put together a small procedure to test this:
MatrixMultiply := proc(A,B)
local m,n,p,X,Ax,i,j,x,col;
uses LinearAlgebra:-LA_Main;
    m := op([1,1],A);
    (n,p) := op(1,B);
    X := rtable( 1..n
                 , i -> x[i]
                 , 'subtype' = 'Vector'['column']
               );
    Ax := convert(MatrixVectorMultiply(A, X, 'outputoptions' = [])
                  , list);
    for j to p do
        for i to m do
            x[i] := B[i,j];
        end do;
        col[j] := eval(Ax);
        x := 'x';
    end do;
    rtable( 1..m, 1..p
            , ListTools:-Transpose([seq](col[j],j=1..p))
            , 'subtype' = 'Matrix'
          );
end proc:
Timing Here is a direct comparison with Matrix multiplication using the LA:-Main subpackage (to avoid the minor overhead of type checking, etc):
with(LinearAlgebra):
(m,n,p) := (100,100,1000);
B := RandomMatrix(n,p):
A := RandomMatrix(m,n,density=1):
time(MatrixMultiply(A,B));
time(LinearAlgebra:-LA_Main:-MatrixMatrixMultiply(A,B,'inplace'=false,'outputoptions'=[]));
A := RandomMatrix(m,n,density=1/10):
time(MatrixMultiply(A,B));
time(LinearAlgebra:-LA_Main:-MatrixMatrixMultiply(A,B,'inplace'=false,'outputoptions'=[]));
A := RandomMatrix(m,n,density=1/100):
time(MatrixMultiply(A,B));
time(LinearAlgebra:-LA_Main:-MatrixMatrixMultiply(A,B,'inplace'=false,'outputoptions'=[]));
The times were
density     MatrixMultiply   LA_Main
------------------------------------
   1            5.340         4.269 
  1/10          0.910         3.949
  1/100         0.450         3.840
For dense Matrices there is a minor penalty to this technique. For sparse Matrices there can be a considerable time saving. Follow up I corrected a bug in the code. A for-loop over an rtable, in the previous version, for v in B[1..-1,j] is not guaranteed to loop sequentially through the elements. It gets all the elements, but not necessarily in order of increasing index. If the selected element were not equal to B[i,j], then an incorrect result would be returned. There was no clear change in the execution time.
You have an accents palette? In my Standard Maple GUI (for Linux) there are 19 palettes, but none labeled Accents. They are Symbol Recognition Expression Units(SI) Units(FPS) Common Symbols Matrix Greek Arrows Fenced Relational Relational Round Negated Large Operators Operators Open Face Fraktur Script Miscellaneous Layout
You have an accents palette? In my Standard Maple GUI (for Linux) there are 19 palettes, but none labeled Accents. They are Symbol Recognition Expression Units(SI) Units(FPS) Common Symbols Matrix Greek Arrows Fenced Relational Relational Round Negated Large Operators Operators Open Face Fraktur Script Miscellaneous Layout
Do you know how to represent linear equations as matrix equations? For example, the linear equations,
a11*x1 + a12*x2 = b1
a21*x1 + a22*x2 = b2
where the a's and b's are constant, the x's are the indeterminates, is equivalent to the Matrix equation (in Maple),
A := <<a11|a12>,<a21|a22>>:
B := <b1,b2>:
X := <x1,x2>:
A . X = B;
You can use LinearAlgebra[LinearSolve] to solve that equation:
LinearAlgebra:-LinearSolve(A,B);
You could also solve it by converting to a set of expression implicitly assumed to be zero and passing to solve:
eqs ::= convert(A . X - B, set);
solve(eqs, [x1,x2] );
Another approach is to use the Optimization package. This may be overkill for this problem. Normally you'd want to restrict the domain, but it isn't necessary here:
Optimization:-Minimize(y);
       [-0.217233628211221663, [x = 4.49340945743559940]]
Another approach is to use the Optimization package. This may be overkill for this problem. Normally you'd want to restrict the domain, but it isn't necessary here:
Optimization:-Minimize(y);
       [-0.217233628211221663, [x = 4.49340945743559940]]
Another approach, less flexible than Doug's solution but simpler for the particular problem at hand, is to use ListTools:-Transpose:
ListTools:-Transpose([ [1,2,3], [2,3,4], [3,3,3] ]);
          [[1, 2, 3], [2, 3, 3], [3, 4, 3]]
This can be easily extended to create a version of zip that handles any number of lists:
zipall := proc(f)
uses ListTools;
    map( lst -> f(lst[])
         , Transpose([args[2..-1]]));
end proc;
Another approach, less flexible than Doug's solution but simpler for the particular problem at hand, is to use ListTools:-Transpose:
ListTools:-Transpose([ [1,2,3], [2,3,4], [3,3,3] ]);
          [[1, 2, 3], [2, 3, 3], [3, 4, 3]]
This can be easily extended to create a version of zip that handles any number of lists:
zipall := proc(f)
uses ListTools;
    map( lst -> f(lst[])
         , Transpose([args[2..-1]]));
end proc;
While using attributes is quicker than scanning the full array for sparse matrices, it is slower with dense matrices. Here's a procedure that is fast in both cases:
maxindex3 := proc(A::rtable)
local val,maxval,eq,index;
    maxval := -infinity;
    for eq in op(2,A) do
        val := abs(rhs(eq));
        if val > maxval then
            maxval := val;
            index := lhs(eq);
        end if;
    end do;
    index;
end proc;
I haven't yet compared it to the rtable_scanblock approach. There is a bug in this procedure, which also shows up in Roman's. I'll leave it as an exercise.
While using attributes is quicker than scanning the full array for sparse matrices, it is slower with dense matrices. Here's a procedure that is fast in both cases:
maxindex3 := proc(A::rtable)
local val,maxval,eq,index;
    maxval := -infinity;
    for eq in op(2,A) do
        val := abs(rhs(eq));
        if val > maxval then
            maxval := val;
            index := lhs(eq);
        end if;
    end do;
    index;
end proc;
I haven't yet compared it to the rtable_scanblock approach. There is a bug in this procedure, which also shows up in Roman's. I'll leave it as an exercise.
First 182 183 184 185 186 187 188 Last Page 184 of 195