Joe Riel

9530 Reputation

23 Badges

20 years, 24 days

MaplePrimes Activity


These are answers submitted by Joe Riel

You might have avoided this issue, or more easily discovered the cause, by using numelems rather than nops. They give the same result when the argument is a list, but numelems raises an error if its input is an unevaluated function call, which was your situation:

L(1):=[1,2,3]:
L(2):=[A,B,C]:
sum(numelems(L(i)),i=1..2);
Error, invalid input: numelems expects its 1st argument, t, to be of type indexable, but received L(i)

add(numelems(L(i)),i=1..2); 6

When writing Maple code it is good practice to use numelems when the argument is a list or other indexable element. The lower level nops returns a value for practically any Maple expression, as such it can mask subtle errors.

Consider using Iterator:-Permute. It will use a minimal amount of memory. As Markiyan points out, there is little reason to generate the entire permutation at once.

P := Iterator:-Permute(11):
# loop through the entire permutation.
CodeTools:-Usage(proc() local p; for p in P do end do; end proc());
memory used=1.49GiB, alloc change=0 bytes, cpu time=65.34s, real time=65.54s, gc time=876.06ms

Here's the non-robust foolish way to do this by directly changing the Maple dag type of the sublists. The idea is that the internal structure for a two-element list of integers is essentially the same as that for a fraction, so we merely have to change the dag type. For this particular example we can do so with a string substitutution in the m-format. I've added an element to the list to show what happens when the integers are not relatively prime.

A := [[2,3], [4,5], [6,7], [3,3]]:
sscanf(StringTools:-SubstituteAll(sprintf("%m",A),"7$","#"),"%m")[1];
              [2/3, 4/5, 6/7, 3/3]

Note that the last element is not in standard form.

If you happen to assign, say in your initialization file, the handy procedure

crossmul := proc(eq :: equation)
local L,R; 
    (L,R) := op(eq);
    numer(L)*denom(R) = numer(R)*denom(L);
end proc:

then you can use it with isolate

eq:= a*x+b*y=c*x+d*y:
crossmul(isolate(eq,x));
               (a-c)*x = -y*(b-d)

Not recommended as it generates a needless intermediate form.

 `/`~(ListTools:-Transpose(A)[]);
                              [2/3, 4/5, 6/7]

Make mass a Vector, not a Matrix.

  mass := Vector([...]);

Change distancevector to return a Vector, not a list:

  distancevector := (i,j) -> Vector([ ... ]):

Finally, change the k in the assignment to ode to q:

  ode := seq(seq((D(D(x[i, q])))(t) = force(i)[q], q = 1 .. 3), i = 0 .. N-1)

With that, dsolve returns a procedure and odeplot returns a plot of the trajectory.

The Do procedure is used to access and assign the value of the component. Use something like

for i to Do(%id) do
   for j from x to y do
      block[i][j] := 1-block[i][j];
   end do;
   ...
   Do(%id = whatever);
end do;

A more mathematical approach is

q := 01100101:
ListTools:-Reverse([seq(irem(q,10,'q'), i=1..length(q))]);
                                    [1, 1, 0, 0, 1, 0, 1]

Be aware that that reassigns q.

Simpler is

q := 01100101:
ListTools:-Reverse(convert(q,'base',10));
                                    [1, 1, 0, 0, 1, 0, 1]

The loop is squaring and adding 1. By the 10th iteration the integer has 91 digits. Memory usage will quickly get out of hand. 

Consider using Threads:-Task for the real problem.

Note, too, that, after correcting the errors that Doug pointed out, the assignment is to a table and not a Matrix because you never assigned a to be a Matrix.  You can do that with

  a := Matrix(4): # only one dimension is necessary for a square matrix

Do so before the loop. Or use the initializer method that Kitonum demonstrated; when usable it is convenient. Here is the corrected version.

a := Matrix(4):
for i to 4 do
   for j to 4 do
       a[i,j] := 2*psi[i]*psi[j];
   end do;
end do:

Using the the AllPairsDistance procedure in GraphTheory almost works here; the problem is that your b node doesn't really fit with the scheme because it is equivalent to a node with a branch to itself and Maple's undirected graphs do not allow that. The following procedure uses MultiSet to store the nodes with self-loops, then, after computing the Matrix, assigns 1 on the diagonal to the nodes with self loops. Note the hackish use of assign to return NULL. The resulting Matrix, which contains the minimum distance between any two vertices, along with the list of vertices whose position in the list corresponds to the indices of the Matrix, can be used to easily construct the desired result

Distance := proc(neighbors :: seq(name=set(name)))
local G,M,S,T,V,eq,i;
uses GT = GraphTheory;
    S := MultiSet();
    G := GT:-Graph({seq(proc(eq)
                        local x, i := lhs(eq);
                            seq(`if`(i=j
                                     , assign('x',Insert(S,i))
                                     , {i,j}
                                    ), j = rhs(eq))
                        end proc(eq)
                        , eq = neighbors)});
    M := GT:-AllPairsDistance(G);
    V := GT:-Vertices(G);
    T := table([seq(V[i]=i, i=1..numelems(V))]);
    for i in S do
        i := T[i];
        M[i,i] := 1;
    end do;
    M,eval(V);
end proc:
(dist,verts) := Distance(a = {b, c, d}, b = {a, b, e}, c = {a, d, f});

Here's a rewrite that may be easier to comprehend.

Distance := proc(neighbors :: seq(name=set(name)))
local G,M,S,T,V,eq,i,j;
uses GT = GraphTheory;
    S := MultiSet();
    V := convert(indets([neighbors]),'list');
    G := GT:-Graph(V);
    for eq in neighbors do
        i := lhs(eq);
        for j in rhs(eq) do
            if i=j then
                Insert(S,i);
            else
                GT:-AddEdge(G, {i,j});
            end if;
        end do;
    end do;
    M := GT:-AllPairsDistance(G);
    T := table([seq(V[i]=i, i=1..numelems(V))]);
    for i in S do
        i := T[i];
        M[i,i] := 1;
    end do;
    (M,V);
end proc:
(dist,verts) := Distance(a = {b, c, d}, b = {a, b, e}, c = {a, d, f});
                    [0    1    1    1    2    2]
                    [                          ]
                    [1    1    2    2    1    3]
                    [                          ]
                    [1    2    0    1    3    1]
     dist, verts := [                          ], [a, b, c, d, e, f]
                    [1    2    1    0    3    2]
                    [                          ]
                    [2    1    3    3    0    4]
                    [                          ]
                    [2    3    1    2    4    0]

I don't get any syntactic error. What input are you using, and what result do you expect?  

Rather than doing with(LinearAlgebra), consider using

 

Karmarkar := proc(A,c)
uses LinearAlgebra;
   ...
end proc;

Actually, I prefer uses LA = LinearAlgebra and then prefixing the LinearAlgebra calls with LA:-.

A way to combine the operations (I assume you plan to replace the inert functions of t with variables) is to use subsindets:

subsindets(eq, function(identical(t)), f -> cat(op(0,f),'_'));

Probably you will need to make that more robust, frequently one is interested in converting only unknown functions of t, that is, sin(t) should remain as is.  That can be accomplished by modifying the type expression used to match the functions of t. For example, use

And(function(identical(t)), Not(known))

where Not(known) means the function is not known to Maple.

 

Map, over the list, a procedure that extracts the name of the function and catenates an underscore to it. The function name is extracted via the op procedure, e.g. op(0,f(a,b,c)) evaluates to f. Thus 

map(f->cat(op(0,f),_),T);

Note that this fails if the name of a function is indexed, e.g. f[2](a). No error is generated but the catenation doesn't evaluate to a symbol. Presumably that isn't an issue here.  One way to handle that case is to first convert the indexed name to a symbol, then catenate the underscore.  So a more robust version is

map(f->cat(convert(op(0,f),'symbol'),_),T);

However, if you are actually dealing with indexed names you might want a different result. Another way to do the conversion, and combine it with the catenation, is to use nprintf, which generates a name (symbol). Thus

map(f -> nprintf("%a_", op(0,f)),T);

 

The curly braces designate a set, not a list. An easy way to flatten a set is

s := {a,b,c, {d, e, {f, g}}}:
{subsindets(s, set, op)};
                      {a,b,c,d,e,f,g}

The same could be done for nested lists (which use square brackets rather than curly brackets). 

Followup:

ListTools:-Flatten works for nested lists, but not sets.  

First 24 25 26 27 28 29 30 Last Page 26 of 114