Carl Love

Carl Love

28025 Reputation

25 Badges

12 years, 313 days
Himself
Wayland, Massachusetts, United States
My name was formerly Carl Devore.

MaplePrimes Activity


These are replies submitted by Carl Love

Another significant difference between sets and lists is that membership checks in large sets are faster than those in long lists because it makes use of the fact that the set entries are stored sorted. In addition to the differences mentioned by Acer, I think that this is the only other significant difference.

@emendes I had similar weird errors the 1st (and only the 1st after each restart) time that I tried to run it on each of my two computers: one error coming from Iterator about a random-seeming particular iterate, and one about some randomly-generated file name not existing. Funny thing, though: Both of my computers are Windows 10!! So, please just try again. I have a vague suspicion that the issue is related to Iterator compiling its results (perhaps in separate threads).

The box that contains the module code is called a code edit region. You can use the Insert menu to insert one anywhere in a worksheet. To "load" the code in the region, right click on it and select "Execute Code" from the context menu that pops up. If the code has errors, you'll be notified, but you may need a magnifying glass to locate them precisely: Their approximate locations in the code are marked by red squiggles the same size as the red fibers in US currency.

@Kitonum Here is some cleaner and faster code that does the same thing. My only goal was to make it cleaner; the faster came as an unexpected bonus.

restart:
A:= <1,2,2; 2,1,2; 2,2,3>:
T:= <L[1], -L[2], L[3]; L[1], L[2], L[3]; -L[1], L[2], L[3]>:
NextTriples:= subs(R= convert(T.A, listlist)[], L-> R):

T1:= CodeTools:-Usage(seq((NextTriples~@@n)([[3,4,5]])[], n= 1..10)):
memory used=24.48MiB, alloc change=46.01MiB, cpu time=187.00ms,
real time=189.00ms, gc time=46.88ms

nops([T1]);
                             88572

#Compare with:
NextTriple:=proc(L)
local i;
[seq(op([[L[i,1]-2*L[i,2]+2*L[i,3], 2*L[i,1]-L[i,2]+2*L[i,3], 2*L[i,1]-2*L[i,2]+3*L[i,3]], [L[i,1]+2*L[i,2]+2*L[i,3], 2*L[i,1]+L[i,2]+2*L[i,3], 2*L[i,1]+2*L[i,2]+3*L[i,3]],
[-L[i,1]+2*L[i,2]+2*L[i,3], -2*L[i,1]+L[i,2]+2*L[i,3], -2*L[i,1]+2*L[i,2]+3*L[i,3]]]), i=1..nops(L))];
end proc:
T2:= CodeTools:-Usage(seq((NextTriple@@n)([[3,4,5]])[], n= 1..10)):
memory used=37.53MiB, alloc change=-6.01MiB, cpu time=485.00ms, 
real time=495.00ms, gc time=140.62ms

evalb([T1]=[T2]);
                              true

 

@emendes Garbage collection (gc) happens automatically. Every time that you see either number (memory or time) change in the status bar (bottom right of your worksheet window), there has been a gc. With the code that we're working on, you'll notice that that happens about once per second. There's no danger in doing your own gc, but it's unlikely that you'll improve upon the efficiency of the automatic ones, and there's a good chance that you'll decrease the efficiency. That's why it's discouraged.

@JAMET 

There are many ways to do it. The way that I would recommend would depend largely on two conditions:

  1. Do you want to use a very large n, say, n > 1000?
  2. Do you want to return the entire sequence of iterates, or just its final entry?

The commands foldl and foldr can be used to compose a binary operator with itself. If the operator is associative (as the present case is), these commands give the same result. For example,

foldr(`&*`, [3,4,5] $ 9)

The procedure that you were trying to write could be written like this:

Tri:= proc(Y::And(list(algebraic), 3 &under nops), n::posint)
local r:= Y;
    to n-1 do r:= Y &* r od;
    r
end proc:

You shouldn't declare a variable global just because you use it in a procedure. That's only needed if you make an assignment to it.

@emendes If your attempt to use Grid is pursuant to the same problem that we're working on in the other thread, then don't bother. I just finished parallelizing our OrbitPartition with Threads, which is much more memory efficient than Grid (if you can satisfy its rather strict requirements).

@Carl Love I pared my code down to a single regular-expression substitution:

showstat_no_nums:= p->
    `debugger/printf`(
        "%s",  
        StringTools:-RegSubs(
            "\n[ 1-9][^\n][^\n][^\n]"= "\n ", 
            debugopts('procpretty'= p)
        )
    )
:

 

@emendes 

Sorry for the delay in answering. It was because both of your questions require lengthy and technical answers.
 

Re: "Memory used" as reported by CodeTools:-Usage: This number is reported with a dimension of information (bytes or multiples thereof). This is incorrect! What this number actually represents is Int(M(t), t= time program runs) where M(t) is the amount of memory "being actively used" at time t. Thus the correct dimensions are information*time (e.g., GiB-s (gibibyte-seconds)). It is sad and somewhat shocking that no-one at MapleSoft has noticed and corrected this. (The same dimension error is incorrectly documented for kernelopts(bytesused).) Many systems and computer scientists avoid the confusion about this issue by naming this measurement "memory integral" rather than "memory used" and by using the correct dimensions.

I don't know the precise definition of "being actively used"; I am trying to figure that out from experimentation. There is also the issue of how time is measured. Is it real time? cpu time? something else? This is a bit easier to determine by experiment, and my best guess so far is that it's pretty close to kernelopts(cputime) - kernelopts(gctotaltime).

You're justifiably worried about running out of memory when doing the larger tuples. The number that you need to watch is not reported by CodeTools:-Usage. It does however appear on the worksheet status line (the bottom right), along with cputime.

Note that memory is nearly constantly being recycled by garbage collection, so the same chunk of memory may be "used" many times during a program run. Each such re-use adds to the incorrectly named "memory used".
 

Re: option remember and option cache: Both of these are attempts to save the cputime needed to re-call a procedure with arguments that it's already seen at the expense of the memory needed to store those results. The process is technically called memoization in computer science literature.

Consider the subprocedure of OrbitPartition. It may be called millions of times during an execution of the program, but it only has exactly 13 possible pairs of arguments. Thus the memory needed to store the pre-computed results is trivial. Using option remember means any previously computed results will be remembered for as long as the procedure is in the visible scope.

Now consider the procedure ClassifyI in the setup code. It also may be called millions or times, but with millions of different arguments. But it's called twice in succession with the same argument---once in AllowedRep and once in DisallowedOrbit. By using option cache, a scrolling cache of the most recently used results is maintained. You can specify the maximum number of entries in this cache in the option. In this case, option cache(1) would work. The only reason that I didn't put a number is that a default-size cache might supply some useful debugging information if that were needed. The cache or remember table of a procedure P (it can't have both, but it may have neither) can be directly inspected via op(4, eval(P)).
 

Re: Making it a module: Do you want the setup specifications inside (local to) the module?

@JAMET Sorry about that. I had just noticed that myself, and I uploaded a new worksheet a few minutes ago. Try it again.

I have often had trouble with Grid:-Seq when the chunks were too small. I'd recommend that each chunk take at least 2 seconds to process. Your 500 seems both rather arbitrary and way too small.

I don't think that it can be done unless you know the positions of the vertices. If you do know (for example, if you can measure them from an existing picture), then you can use SetVertxPositions. I doubt that there is any algorithm to do it without knowing those vertex positions.

To give you an idea of the problems with constructing an algorithm, consider the triangle inequality.

@mmcdara The output of showstat is equivalent to the output of printf; so, yes, it's "side-effect" output rather than "return value" output. That's why I went one step back through the showstat code to get the output from debugopts(procpretty= ...). This is identical to the standard showstat output, but in string (actually name) form.

@Pascal4QM Thanks. As you can probably tell, I worked it out by deconstructing showstat itself.

@acer You can use a line-width specifier in the format code such as "%40P". Then, the lines will be sensibly broken and indented with a maximum length of 40. It's quite impressive how nicely it's done.

@dharr 

dsolve(..., numeric) does try to solve ODEs for their highest derivatives before proceeding. But if there are multiple solutions, even trivial ones, it refuses to arbitrarily select one.

There are other issues that may hamper the attempt that are relatively easy to address "by hand". For example, in the case at hand, I needed to differentiate one of the equations. That often necessitates additional initial\boundary conditions, but it didn't in this case.

First 199 200 201 202 203 204 205 Last Page 201 of 708