acer

32490 Reputation

29 Badges

20 years, 8 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are replies submitted by acer

The relative performance with increased problem "size" here can depend on on which gets larger: the number of items in the inner lists, or the number of inner lists, or both. I deliberately repeat one of the computations in each run below, to test whether the order of execution is affecting it's timing.

For example,

restart;
A := [seq([seq(i*j,j=1..1000000)],i=1..3)]:

ans1 := CodeTools:-Usage( op(map(op~,[1,2],A)) ):
memory used=1.70KiB, alloc change=0 bytes, cpu time=7.00ms, real time=7.00ms, gc time=0ns
ans2 := CodeTools:-Usage( op([1..2],ListTools:-Transpose(A)) ):
memory used=53.42MiB, alloc change=371.64MiB, cpu time=2.90s, real time=1.28s, gc time=2.48s
ans3 := CodeTools:-Usage( op(map(op~,[1,2],A)) ):
memory used=1.73KiB, alloc change=0 bytes, cpu time=8.00ms, real time=7.00ms, gc time=0ns

ans1-ans2, ans1-ans3;
                                    0, 0

restart;
A := [seq([seq(i*j,j=1..1700)],i=1..1700)]:

ans1 := CodeTools:-Usage( op(map(op~,[1,2],A)) ):
memory used=187.17KiB, alloc change=32.00KiB, cpu time=8.00ms, real time=8.00ms, gc time=0ns
ans2 := CodeTools:-Usage( op([1..2],ListTools:-Transpose(A)) ):
memory used=22.11MiB, alloc change=260.31MiB, cpu time=56.00ms, real time=56.00ms, gc time=20.00ms
ans3 := CodeTools:-Usage( op(map(op~,[1,2],A)) ):
memory used=187.34KiB, alloc change=0 bytes, cpu time=8.00ms, real time=7.00ms, gc time=0ns

ans1-ans2, ans1-ans3;
                                    0, 0

restart;
A := [seq([seq(i*j,j=1..3)],i=1..1000000)]:
ans1 := CodeTools:-Usage( op(map(op~,[1,2],A)) ):
memory used=106.82MiB, alloc change=47.27MiB, cpu time=2.08s, real time=919.00ms, gc time=1.58s
ans2 := CodeTools:-Usage( op([1..2],ListTools:-Transpose(A)) ):
memory used=22.89MiB, alloc change=22.90MiB, cpu time=40.00ms, real time=42.00ms, gc time=0ns
ans3 := CodeTools:-Usage( op(map(op~,[1,2],A)) ):
memory used=106.82MiB, alloc change=-7.63MiB, cpu time=1.72s, real time=815.00ms, gc time=1.23s

ans1-ans2, ans1-ans3;
                                    0, 0

@Annonymouse Thanks for that. Here is a worksheet in which your optimal target expression is named `OP`. It is better using several metrics, including `length`, `LeafCount`, codegen[cost], and the `simplify/size/size` internal procedure that the simplify(...,size) command uses.

simp4.mw

As I briefly mentioned above, the ability to temporarily add/subtract some either special terms (or some subset of the addends of a sum) can be a tricky topic, I suspect. The potential cost in the presence of a sum of many addends (in general, not here) looks like it might be daunting. As you say, there may be hints that can be leverage, including the presence of denominators common amongst some addends. Thanks for this example -- I'm going to consider all this in one partial approach of a compactifier I'm working on.

 @vv What I was trying to convey by showing that approach with `collect` was just that it produced a smaller result for the given example. I wasn't trying to imply that it would always do better, naturally. Indeed even for the given example it matters which name is collected. A similar question arises: should simplify(...,size) attempt collection wrt single names, all single names, combinations of all subsets on names present, etc, and if so how could that be effectively cut off for practicality?

@Carl Love I'm not sure whether Carl has overlooked one aspect of this task, or has left it as part of the homework exercise...

In order to utilize the procedure that Carl has written the first argument must be equal to the remaining expression when one instance of x in the original expression is isolated. First, let's do it by isolating for the two individual instances of x in exp(x)-x-5 .

For example,

evalf( [solve( exp(x)-x-5, x )] );
                  [-4.993216189, 1.936847407]

PointFixe(exp(x)-5, -2, 1e-8, 100);
                          -4.993216188

PointFixe(ln(x+5), 2, 1e-8, 100);
                          1.936847409

I have changed Carl's routine a little, to return FAIL rather than raise an error. In the attached sheet I show a crude way to generate the various "isolations" for separate occurences of `x` (in this case, two of them).

Download pointfixe.mw

@Thomas Richard 

restart:

A := [[1,2],[3,4],[5,6]]: 

op([1..2],ListTools:-Transpose(A));
                                         [1, 3, 5], [2, 4, 6]

seq(map(`?[]`,A,[i]),i=1..2);
                                         [1, 3, 5], [2, 4, 6]

B := [[1,2,3,4],[5,6,7,8],[9,10,11,12]]:

op([1..2],ListTools:-Transpose(B));
                                         [1, 5, 9], [2, 6, 10]

seq(map(`?[]`,B,[i]),i=1..2);
                                         [1, 5, 9], [2, 6, 10]

When the length of the inner lists gets large the mapped `?[]` approach becomes relatively faster, and the additional memory allocation becomes relatively smaller (because the transposition creates something effectively as large as the original).

[edited] Oh, it seems like the performance of the following is quite a bit better, for large inner lists. Thanks, Kitonum!

op(map(op~,[1,2],A));
                                          [1, 3, 5], [2, 4, 6]

op(map(op~,[1,2],B));
                                          [1, 5, 9], [2, 6, 10]

@vv Yes, it's an interesting topic. Leaving aside the complications of trying to introduce terms so as to get fortuitous factorization (which seems like it may be a deep rabbit hole), it can be an involved subject using just the tools available.

F3 := expand(E3):

length( simplify(F3,size) );
                                                  6938

CG:=u->codegen[optimize](subs(__dum=u,proc() __dum; end proc),tryhard)():

length( CG( collect( F3, y, u->simplify(u,size) ) ) );
                                                  2580

length( simplify( (CG@@2)( collect( simplify(F3,size), y, u->simplify(u,size) ) ),size ) );
                                                  2441

This page indicates that OSX versions 10.12 is not an officially supported platform for Maple 2016.

It would be useful if this roadmap page could be updated with the intended support for Maple 2017.

acer

@AmusingYeti I do not recall seeing full details from you as to how your lengthy expressions come about. Please keep in mind that a common mistake is to use floating-point vallues too early. Sight unseen, there is a chance that some earlier aspect of your computations which produced these lengthy integrands might be better handled with exact (or possibly even symbolic) values.

Since the integrand is somewhat expensive to compute, and since the numeric triple-integration does many functional evaluations of the integrand, it is beneficial here to compile the integrand (after making a procedure from it).

There is a little extra overhead due to the external cuhre function having to call back to Maple to access the compiled integrand procedure. But for this example the speed advantage of the compiled version over the (otherwise, here) evalhf evaluations of the integrand wins out.

This compiled version takes 2.25 sec on my 64bit Linux Maple 2016.1 using the well-optimized expr1, while the previous well-optimized version takes 8.6 sec. The first method in my original Answer above takes 21.1 sec.

Maple_numeric_speed_compiled.mw

Of course this approach requires that the Compiler:-Compile command is functioning.

Even when using Maple 2016.1 the speed will depend on your machine and the OS. I tried this on a moderately quick Windows 7 machine using 64bit Maple 2016.1 and the well-optimized version shown previously took about 22 sec while the compiled version tool about 6.3 sec and the first I posted took about 55 sec.

The upshot is that the speed of the individual evaluations of the integral is key here. Compactification of the integrand helps, and so to may compilation (if possible, like here).

@vv 

The manually written procedure you gave has the virtue that it declares y as a local. With the unapply method I gave there would be a problem if global y were assigned, say, a numeric value. So I think that it's good that you showed it, and wrote the useful explanation.

As a side note, perhaps it would be convenient if parameter-processing were to offer a terse syntax for handling required arguments in such a way.

Eg (making this up, this is not valid syntax ladies and gentlemen),

g := (a::query(numeric)) -> a^3;

or 

g := proc(a::query(numeric))
       a^3;
     end proc:

where such a procedure would return unevaluated if the required argument did not satisfy its queried type.

@Markiyan Hirnyk The final number you show is negative, but you said you wanted the solution in RealRange(Open(0),4).

solve( {n>1, n<=4, (1/n-1)*ln(t)+(n-1/n-1)*ln(1-t)=ln(t)/n-ln(t)}, n); 

                                                            1/2
                                                           5
                                                      {n = ---- + 1/2}
                                                            2

@Markiyan Hirnyk No, the 1 was not out of thin air -- I thought about what a trivial case of that might be, akin to solving an identity.

Anyway, your comment about the RHS was silly and wrong. The RHS of ff is GAMMA(n-1)/GAMMA(1/n) and not just GAMMA(n-1), and that does in fact evaluate to exact 1 when n=(1/2)*sqrt(5)+1/2).

Clearly you do sometimes say something even when you have nothing to say.

@Markiyan Hirnyk  That's not the RHS. 

I would like to find a way to obtain a version of your expression in Maple 2016.1 which integrates numerically this fast. Likely it's size would be comparable. I have not yet found the magic simplification incantation which can easily be applied programmatically.

Maple_numeric_speed_special.mw

The timings are different, but not very different in a relative sense.

Could you state your target (relative) accuracy? Is it 1e-5, or finer, or would you be satisfied with even say, epsilon=1e-3 or 1e-4 (in which case probabilistic methods like CubaCuhre might be faster).

I'm not sure why you say that the evalf(Int(...)) syntax has changed in Maple 2016. I don't yet see any problem with that. Where there is some problem, however, is with the simplify(expr1,LaguerreL) and simplify(expr1,sqrt) in Maple 2016.1. I can try and figure out what's up with that, and how to better proceed. I notice that your were assigning results from both of those to expr1, so only one of them was being used anyway. Was that intentional, or a mistake?

First 295 296 297 298 299 300 301 Last Page 297 of 595