Joe Riel

9660 Reputation

23 Badges

20 years, 9 days

MaplePrimes Activity


These are replies submitted by Joe Riel

@PatrickT Maple lists are not limited to 100 elements.  Rather, the following operation raises an error with a list of more than 100 elements:

L := [seq(1..101)]:
L[1] := 0;
 Error, assigning to a long list, please use Arrays

The error message is confusing. What is happening here is that the assignment 

L[1] := 0;

is 'sort-of' modifying the first element of the list L.  However, it cannot actually do that, regardless the length of the list. Maple lists (and sets, and most data structures with the exceptions of tables and rtables) are immutable. Once created, they cannot be modified. At one time the above operation was not allowed in Maple (regardless the size of the list). A later release changed this so that if the list is small enough (100 elements or less), Maple would permit the operation. It still does not actually change the original list.  Rather it creates a new list with a different first element (now 0) and assigns it to L. The reason for the abitrary limit is that creating an entirely new list is inefficient. Without the warning a user might wonder why his bubble-sort routine is running in O(n^4) time. If you really want to be changing elements in a structure, then you should be using a mutable data structure (probably an rtable, i.e., Array).

That long-winded explanation does not directly answer the more pressing question as to why an Array was used and then later converted to a list---so here's another.  First the easy part.  The reason for converting to a list was simply because you  had originally requested a list as output. If an Array will suffice---and it seems as though it might---then that conversion can be eliminated.  

The reason for using an Array rather than a list to record the times is also due to the immutability of lists.  The typical way to create a list in such an application (a loop) is to create an entirely new list each time an element needs to be appended.  That generates a lot of unused data (the old lists) that must later be garbage collected. In a loop, that process is O(n^2) in time and space, meaning the processing time and memory usage is proportional to the square of the number of elements in the final list, assuming a new element is added one at a time.  For small n that inefficiency is insignificant in the scheme of things, however, for large n it can dominant a computation.  For older Maples, the usual way to avoid this in a loop is to use a table.  With newer Maples one can use a dynamically resizable Array.  Here I chose to use a dynamically resizable Array to illustrate its use.  The trick is to assign a new element using parentheses where you would normally use square brackets.

@PatrickT dsolve does not provide a way to store values during the integration.  A way around this is to halt the integration, store the values, reinitialize the integrator, and continue.  Thus

Sol := dsolve( [ diff(y(t),t) = -y(t), y(0) = 1, p(0) = 1/10, s(0) = 0 ]
               , 'type' = numeric
               , 'discrete_variables' = [ p(t)::float, s(t)::float ]
               , 'events' = [ [ y(t) = p(t), [ p(t) = p(t)/10, s(t) = t, 'halt' ] ]  ]
             ) :

cnt := 0:
A := Array(1..0):
Tf := 20:
_Env_in_maplet := true:  # incantation to suppress integrator warnings
do
    result := Sol(Tf);
    timefired := eval(t, result);
    if timefired >= Tf then
        break;
    else
        cnt := cnt+1;
        A(cnt) := timefired; # append timefired to Array, dynamically resizing it.
        # reinitialize the integrator with the last result
        Sol("initial" = map(rhs, result));
    end if;
end do:

convert(A, list);
[2.30258463685735, 4.60516821203946, 6.90774379194420, 9.21026168095786,
    11.5122537013767, 13.8094352885412, 16.1002798481035, 18.3911300766884]


@PatrickT dsolve does not provide a way to store values during the integration.  A way around this is to halt the integration, store the values, reinitialize the integrator, and continue.  Thus

Sol := dsolve( [ diff(y(t),t) = -y(t), y(0) = 1, p(0) = 1/10, s(0) = 0 ]
               , 'type' = numeric
               , 'discrete_variables' = [ p(t)::float, s(t)::float ]
               , 'events' = [ [ y(t) = p(t), [ p(t) = p(t)/10, s(t) = t, 'halt' ] ]  ]
             ) :

cnt := 0:
A := Array(1..0):
Tf := 20:
_Env_in_maplet := true:  # incantation to suppress integrator warnings
do
    result := Sol(Tf);
    timefired := eval(t, result);
    if timefired >= Tf then
        break;
    else
        cnt := cnt+1;
        A(cnt) := timefired; # append timefired to Array, dynamically resizing it.
        # reinitialize the integrator with the last result
        Sol("initial" = map(rhs, result));
    end if;
end do:

convert(A, list);
[2.30258463685735, 4.60516821203946, 6.90774379194420, 9.21026168095786,
    11.5122537013767, 13.8094352885412, 16.1002798481035, 18.3911300766884]


@PatrickT The NULL does nothing; when Maple evaluates the set it goes away.  It is an idiosyncracy of mine.  I use an external editor (emacs) that autoindents; I also prefer to to lead continued lines with a comma (less likely to mistake them for a newline).  Using the NULL allows all the non-NULL elements of the set to appear syntactically the same---that makes it slightly easier to later move them around and comment them out.

@PatrickT The NULL does nothing; when Maple evaluates the set it goes away.  It is an idiosyncracy of mine.  I use an external editor (emacs) that autoindents; I also prefer to to lead continued lines with a comma (less likely to mistake them for a newline).  Using the NULL allows all the non-NULL elements of the set to appear syntactically the same---that makes it slightly easier to later move them around and comment them out.

@epostma Nice extension.  Saving the event-time explicitly is a useful technique.

@epostma Nice extension.  Saving the event-time explicitly is a useful technique.

In what sense is the debugger disabled?

 

I agree that there should be a better way to do this.  I've submitted an SCR to that effect.

That is a neat application. 

Given the axial symmetry in the first construction, I'd be tempted to create a single pattern (through the line of symmetry) and use it to simultaneously cut out a bunch of identical axial slices.  Not sure the best way to combine them---maybe sew them together along the line of symmetry (like a book) and then fan the whole thing open.

Not sure why this old post suddenly reappeared, however, it is interesting. I wouldn't call algorithm sp7 a usual implementation of the sieve of Erasthones, nor a particularly efficient one in Maple.  Better would be

sp8 := proc( n :: posint )
local S,P,i,j,cnt;
S := Array(2..n);
cnt := 0;
for i from 2 to n do
if S[i] = 1 then
next;
else
cnt := cnt+1;
P[cnt] := i;
for j from 2*i to n by i do
S[j] := 1;
end do;
end if;
end do;
seq(P[cnt],cnt=1..cnt);
end proc:
macro(CU=CodeTools:-Usage):
CU(sp8(2^16)):
memory used=16.02MiB, alloc change=15.87MiB, cpu time=203.00ms, real time=205.00ms

I see there is no need to allocate a new table, just reuse S. The memory saving is negligible, but it simplifies compilation.

sp8b := proc( n :: posint )
local S,i,j,cnt;
S := Array(1..n);
cnt := 0;
for i from 2 to n do
if S[i] = 0 then
cnt := cnt+1;
S[cnt] := i;
for j from 2*i to n by i do
S[j] := 1;
end do;
end if;
end do;
seq(S[cnt],cnt=1..cnt);
end proc:

While not the most efficient, you can do

 map((`+`@op@abs~)/nops,DD);
                                   [2, 2, 1]

While not the most efficient, you can do

 map((`+`@op@abs~)/nops,DD);
                                   [2, 2, 1]

An example would be helpful

Did you attempt to attach a model to that post?  I don't see it.

First 74 75 76 77 78 79 80 Last Page 76 of 195