Carl Love

Carl Love

28035 Reputation

25 Badges

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

MaplePrimes Activity


These are replies submitted by Carl Love

@Mac Dude  @Earl

I appreciate the interest in my Answer, but retrofits of my code to earlier versions of Maple are not needed or wanted. The OP uses Maple 2019, and I knew that from the start. The power of the syntax innovations of Maple 2018 and Maple 2019 is so far beyond earlier versions that it's painful for me to retrofit. I guess that I should start code with the warning "This code requires Maple 2019 and Maple Input (aka 1-D input)."

Here is the cache-based application that I was talking about. It generates an evaluator procedure for an input recurrence relation. The evaluator uses a cache as a circular buffer. It's mind-blowing to me that this type of meta-programming with sophisticated memory management can be accomplished in Maple in only 18 lines of code. 

Several commands from the Cache package (as mentioned by Acer) are used: 

  1. AddPermanent is used to set the initial values.
  2. Resize is used to limit the size of the circular part of the cache to the order of the recurrence.
  3. TemporaryIndices is used to decide whether a short cut can be taken for particular evaluations.

Since the returned evaluator is a procedure local to the main procedure, it and its cache get garbage collected once there are no external pointers to it (such as when the ad hoc name that it's assigned to gets used for something else).

restart
:

(*--->.............................................................
! MakeProc:                                                       !
!     Fast cache-based evaluation of recurrence relations of      !
!     fixed-but-arbitrary order (similar to rsolve(..., makeproc))!
!                                                                 !
! Parameters:                                                     !
!     F :: name=procedure                                         !
!        The recurrence formula, given as name=procedure where    !
!        the procedure uses the name recursively,                 !
!        e.g., Fibo = (n-> Fibo(n-1)+Fibo(n-2))                   !
!     n0 :: integer                                               !
!        The smallest value of the independent variable for which !
!        an initial value is given                                !
!     iv :: list                                                  !
!        The initial values. The number of them must equal the    !
!        order. They do NOT need to be numeric.                   !
.............................................................<---*)
MakeProc:= proc(F::name=procedure, n0::integer, iv::list)
option `Author: Carl Love <carl.j.love@gmail.com> 18-Jan-2020`;
uses C= Cache;
local k:= nops(iv), R;
    R:= subs(
        _n1= n0+k,
        _F= subs(lhs(F)= _R, eval(rhs(F)))(_i),
        _R= :-thisproc,
        proc(n::And(integer, satisfies(n-> n >= n0)))
        option cache;
        local _i, j, m:= max(_n1, op~([C:-TemporaryIndices(R)])[]);
            for _i from `if`(n > m, m, _n1) to n do R(_i):= _F od
        end proc
    );
    R(n0):= iv[1]; #Force creation of cache.
    C:-Resize(k, R);
    C:-AddPermanent~(R, `[]`~([$n0..n0+k-1]), iv);
    eval(R)
end proc
:

First, I verify that the above works by generating a very large fibonaci number and comparing it to the known value.

F:= MakeProc(Fib= (n-> Fib(n-1)+Fib(n-2)), 0, [0,1]):

f1:= CodeTools:-Usage(F(9999)):

memory used=5.17MiB, alloc change=32.00MiB, cpu time=31.00ms, real time=26.00ms, gc time=0ns

f2:= combinat:-fibonacci(9999):

ilog10(f1); f1-f2; #Verify size and equality.

2089

0

Fibonaci numbers are too easy though because there's a fast matrix-based algorithm for linear homogenous constant-coefficient recurrences. Here's a nonlinear Fibonaci-like recurrence:

rec:= f(n) = f(n-1) + f(n-2) + igcd(f(n-1), f(n-2)),
    [f(1)=1, f(2)=1]:

F1:= rsolve({rec[1], rec[2][]}, f(n), makeproc):

F2:= MakeProc(G= (n-> G(n-1)+G(n-2)+igcd(G(n-1),G(n-2))), 1, [1,1])

proc (n::(And(integer, satisfies(proc (n) options operator, arrow; n0 <= n end proc)))) local _i, j, m; option cache; table( [( temporary::(1) ) = 1, ( permanent::(2) ) = 1, ( permanent::(1) ) = 1 ] ) m := max(3, `~`[op]([Cache:-TemporaryIndices(R)])[]); for _i from `if`(m < n, m, 3) to n do R(_i) := thisproc(_i-1)+thisproc(_i-2)+igcd(thisproc(_i-1), thisproc(_i-2)) end do end proc

gc():
f1:= CodeTools:-Usage((()-> local r:= F1(99999): (r, gc()))()):

memory used=2.33GiB, alloc change=27.49MiB, cpu time=4.75s, real time=4.02s, gc time=2.98s

gc():
f2:= CodeTools:-Usage((()-> local r:= F2(99999): (r, gc()))()):

memory used=2.33GiB, alloc change=32.00MiB, cpu time=4.47s, real time=3.50s, gc time=3.06s

ilog10(f2), f2-f1; #Verify size and equality.

23855, 0

The cache technique excels for "deep" recursions--those that go back many terms.

rec:= f(n) = irem(n,5)+f(n-1)+f(n-69)/n, [seq(f(k)=k, k= 1..69)]:

F1:= rsolve({rec[1], rec[2][]}, f(n), makeproc):

F2:= MakeProc(G= (n-> irem(n,5)+G(n-1)+G(n-69)/n), 1, [$1..69]):

gc():
f1:= CodeTools:-Usage((()-> local r:= F1(9999): (r, gc()))()):

memory used=1.04GiB, alloc change=0 bytes, cpu time=21.20s, real time=21.08s, gc time=1.19s

gc():
f2:= CodeTools:-Usage((()-> local r:= F2(9999): (r, gc()))()):

memory used=0.52GiB, alloc change=0 bytes, cpu time=10.74s, real time=10.68s, gc time=718.75ms

f1-f2;

0

ilog10(denom(f2));

22683

 


 

Download RecMakeProc.mw

@Agha So far, I've looked in three statistics textbooks, the Wikipedia article "Quartile", and a journal article referenced in that Wikipedia article. So far, I have found ZERO evidence to support your claim of the universality of the method that leads to 2.5. Instead, I find statements like "there is no universal agreement on selecting the quartile values" (Wikipedia) and "there are a large number of different definitions used for sample quantiles in statistical computer packages" (very first sentence of referenced article 3).

@acer 

And although Collect is not coded to call Tally, it's effectively true that

ListTools:-Collect:= [op]~@Statistics:-Tally

Indeed, if I may indulge in a little "code golfing", in Maple 2019 Collect can be replaced by this:

Collect:= (L::list)-> 
    local t, T:= table(sparse);
    ([op]~@op@table)(L=~ `+=`~(subs(t= T, `?[]`~(t,`[]`~(L)))))
:

which doesn't use any library code, only built-in code. That goes to show the awesome power of the updating assignment operators, such as += above, which were introduced in Maple 2019.

@barxque What is the file size, in bytes, of the worksheet? Save it before you check.

@Melda Here is what I mean, in a Maple worksheet:

Download SimpleDsolve.mw

For reasons that I don't know, the above won't display inline on this site, but you can download it to see.

Or, just enter these commands into Maple:

ode_sys:= diff(y(x),x$2)-y(x)=0, y(0)=0, y(1)=1;
dsolve({ode_sys});
convert(normal(%), sinh);

 

 

What is the subexpression int(U(x,z), x, z) supposed to mean? What are the limits of integration? Numerical integration without limits is not "a thing". And what is a?

@Stretto What part of 

  • This is just an info-gathering experiment; I'm not claiming that this [restart] will or won't solve your blank-line problem!

don't you understand?

You wrote:

  • It doesn't matter about restart: I always put it at the top so I can easily clear stuff if need be but it is ultimately irrelevant to the problem.

How could you possibly know whether the information that I get by you simply answering my diagnostic questions about what happens when you do restart is relevant or not? 
 

Now, go to menu Tools => Options => Display. The 4th checkbox from the bottom is "Always insert new execution group after executing". Is that box checked? If it is checked, uncheck it, and see how that affects your blank-line problem. Also, tell me the result that you get from the commands

interface(echo); interface(prompt);

@Agha So why haven't you responded to my Answer, which gets you the 2.5 that you want? 

@Stretto You wrote:

  • I was using this
        global _Hist
        _Hist := [N, op(_Hist[1..-2])];

I'm impressed. Yesterday I wrote a caching application that does just that. It's a tiny bit more efficient (for a small cache) than those list operations and much more efficient for a large cache, and, of course, more robust than using globals. It's on another computer. I'll post it in a few hours, after my wife wakes up (the computer is on the bed).

I know that you're a fan of terse syntax, as am I. So, the code op(_Hist[1..-2]) can replaced by _Hist[..-2][]

  • What you say about option remember, system; Generally how often? Every time memory or numbers , change?

Yes, every time that you see those numbers change, there has been a garbage collection (gc()).

  • They change all the time when I do any computation, this may be a bit excessive if it is constantly collecting.

The frequency is based on the amount of garbage waiting to be collected; it isn't time based. So, you must be generating a lot. The algorithm is AFAIK highly optimized, and it helps that it runs in parallel threads (generally 4 threads--but you can set it). Go to ?kernelopts and read about the eight gc options (but gcfreq does nothing at all in Maple 2019). 

@Kitonum See help page ?QuaNtile (not ?QuaRtile). It documents the eight interpolation method options that can be used with either command.

@Stretto The reason that I asked about restart is because your maple.ini is executed whenever you do a restart, as well as when you start a new worksheet or open an old one. So, is there any difference in your blank line situation between using restart: and restart; ?

I suppose that you already know to suppress the output inside the maple.ini with colons. But colons don't suppress explicit output statements print, printf, lprint, userinfo, etc.

@Ali2020 All these seemingly weird syntax innovations work in Maple 2019 if you use the input style Maple Input (also commonly called 1-D input). This is the style where the input characters are in a monospaced reddish-brown upright bold font (as shown in my code box).

Short        Equivalent longer 
syntax      syntax                           When added (approx.)
----------------------------------------------------------------------------------------------
y::odd                 type(y, odd)     has been valid for decades
s+= x                   s:= s+x           new to Maple 2019
--y                        y:= y-1            new to Maple 2019
x*= 2                    x:= x*2           new to Maple 2019
y/= 2                     y:= y/2           new to Maple 2019
(x,y):= (1,2)          x:= 1; y:= 2;    has been valid for 15 years or so

But there's one feature that I used that has no current equivalent in 2D Input, and it's a profound, game-changing improvement to Maple coding that saves much coding time and much computation time. That is, a looping command (such as while) can be used as an expression rather than as a statement. When this is done, the expression returned is the sequence of the evaluated final expressions in the loop. This allows for the efficient creation of sequences that cannot be created with seq.

I've spent many coding hours over the years converting inefficient loops (inefficient because of the immutable-container issue described in the Answer) into more-efficient forms, such as seq. That's no longer necessary! Hoorah for Maple!
 

Since the singularity of sec (or tan) at Pi/2 is not integrable, you have a problem with this particular example. However, if the integration is possible, then summing an arbitrary number of them is quite easy, and I'll show it in an Answer.

I edited the title of your Question. Please don't try to fit your entire Question into the title box!

@mmcdara I don't see any theoretical difficulty for a CAS to correctly handle the arithmetic of infinity. For Maple, for the bugs that you showed, it'd be a matter of suppressing some automatic simplification. Many such things have been improved with automatic simplification over the years. For example, times a Matrix returns a zero Matrix rather than plain 0. So, I wouldn't be surprised if there was already a CAS where one did not need to be very careful regarding infinity.

However, note that automatic simplification is an essential part of Maple's efficiency. It's quicker to process expressions if the rule is simply "explicit A - A = 0, always".

First 224 225 226 227 228 229 230 Last Page 226 of 708