acer

32822 Reputation

29 Badges

20 years, 134 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are replies submitted by acer

Perhaps you could show an example in a comment, of what Maple wouldn't run through when some of the names were not assigned numeric values, so we could take a crack at it. It may be possible to work around that in another way. (Maybe it would be possible to call `solve` and specify which names to solve for, or use `eliminate`, or fsolve, or convert to rationals, etc.)

acer

Perhaps you could show an example in a comment, of what Maple wouldn't run through when some of the names were not assigned numeric values, so we could take a crack at it. It may be possible to work around that in another way. (Maybe it would be possible to call `solve` and specify which names to solve for, or use `eliminate`, or fsolve, or convert to rationals, etc.)

acer

These are just a few thoughts.

Right now, that CompileTools:-Copy routine places the shared libary (external) file into a location that is not platform specific. But it could, instead, put it into a platform specfic directory such as,

  cat("bin.",StringTools:-CharacterMap(" ","_",kernelopts(system)));

Alongside that, the new version of the user-defined Maple routine (here,`sqr`) could be different. Instead of having the external shared library location be hard coded inside a permanent, new version of `sqr`, perhaps the new `sqr` could be a routine which redefines itself (without being a protected member of any module, though). That way, the first time `sqr` gets called in every fresh session it could determine the running platform and overwrite itself with an explicit call_external that used the right binary. And if no appropriate external library was found for that platform, an error could be raised.

If the .mla archive containing the CompileTools package were placed in a special location, then its location would be automatically added to libname. One can discover the following special locations by experiment. (One might have to replace some forward-slashes with kernelopts(dirsep), I didn't check.)

  cat(kernelopts(homedir),kernelopts(dirsep),
"maple/toolbox/lib");

cat(kernelopts(homedir),"/maple/toolbox/",
StringTools:-Split(StringTools:-Split(kernelopts(version),".")[1]," ")[2],
"/lib");

The way it is all set up in the original post, the new `sqr` routine gets savelib'd to a .mla archive with no special location. That seems like good behaviour which could be retained even if `sqr` were self-defining. One should have to explicitly, deliberately add that location to libname, in order to have the precompiled functions assigned to the user-level names like `sqr` be defined in any new session. Otherwise they'd often get in the way.

If the CompileTools ,mla archive were actually going to be stored in a special location (eg. .../toolbox/CompileTools/) then that folder might be also be a convenient place for any platform specific bin.XXX subfolders.

acer

@Joe Riel Hi Joe, might your response about saving a compiled procedure be a good candidate for Branch to New Post?

@Joe Riel Hi Joe, might your response about saving a compiled procedure be a good candidate for Branch to New Post?

@Joe Riel Joe, I'd label applying the subsindets version onto such examples as user error, not a code bug. It's just obviously the wrong tool for the job, isn't it?

I'd accept the idea, that the discussion heretofore was about examples where the intended deepest entries were numeric, say. I think that it's reasonable to suppose that this is about code for some known situation, if not that particular one.

Look at the first suggestion, map(op,L). That was clearly only intended for the known case that L was a list (or maybe a set), as it doesn't do much good when applied to all kinds of piecewise or other structure instead.

And isn't that what happens so often in practice? One writes code in which a given, inner situation is known. There's no need to take the performance hit to check the deep typing of list L. But for L of a given type (which one's own known code might well have produced its very self) some faster method may apply.

Isn't coding like that one possible ideal, in the absence of an optimizing symbolic compiler?

That's why I think that the subsindets version is notable. For a known and commonly occuring class, it is quite a bit faster.

acer

@Joe Riel Joe, I'd label applying the subsindets version onto such examples as user error, not a code bug. It's just obviously the wrong tool for the job, isn't it?

I'd accept the idea, that the discussion heretofore was about examples where the intended deepest entries were numeric, say. I think that it's reasonable to suppose that this is about code for some known situation, if not that particular one.

Look at the first suggestion, map(op,L). That was clearly only intended for the known case that L was a list (or maybe a set), as it doesn't do much good when applied to all kinds of piecewise or other structure instead.

And isn't that what happens so often in practice? One writes code in which a given, inner situation is known. There's no need to take the performance hit to check the deep typing of list L. But for L of a given type (which one's own known code might well have produced its very self) some faster method may apply.

Isn't coding like that one possible ideal, in the absence of an optimizing symbolic compiler?

That's why I think that the subsindets version is notable. For a known and commonly occuring class, it is quite a bit faster.

acer

What exactly is meant, when you write that you cannot simplify the piecewise under assumptions, "...because that value of q[S] is still dependent of another variable"? Why can't that other variable be included in the assumption(s), and the assumption(s) be whatever is need to trigger a given conditional (but no conditional earlier in the piecewise)?

acer

What exactly is meant, when you write that you cannot simplify the piecewise under assumptions, "...because that value of q[S] is still dependent of another variable"? Why can't that other variable be included in the assumption(s), and the assumption(s) be whatever is need to trigger a given conditional (but no conditional earlier in the piecewise)?

acer

@Alejandro Jakubi That's really helpful, Alejandro. Thanks.

@jakubi 

Without preserved nesting and order of all the comments to a post, a lot or real value is lost.

I'd like to hear that it's going to be corrected, as an automatic sweep throught the new site. It's even more important than the related issue of whether the formatting of earlier posts will be fixed (all crammed into one run-on paragraph).

And the same is true for Questions: Just because more highly up-voted Answers rise to the top should (ideally) not mean that the comments nested underneath them get their order and placement mangled.

Which reminds me: the mechanism for submitting nested comments is erratic. I always click the link for a previous comment or Answer on which I want to reply further. And the system certainly knows something of what I want, because it inserts a @name for the author to which I'm responding further. But only sometimes does my comment get nested (indented, or whatever you want to call it). It's frustrating, and I believe that I'm being careful enough to be attempting it properly. (Also, for comments on Posts -- not Questions or Answers -- why doesn't the "Parent" drop-down choice appear?)

acer

There are effective differences between these,

flat := a->`if`(type(a,list), op(map(procname,a)), a):

flat2 := x -> [subsindets(x,list,t->op(t))]:

In cases of extreme nesting there could be tie-in with stacklimit, for the recursive call. And indeed the recursive method fails after hitting the recursion limit. For very deep nesting the subsindets may succeed, but only so slowly as to be useless.

> Z:=(`[]`@@17229)(7,8):

> st:=time(): ans1:=[flat(Z)]: time()-st; # very fast
                                    0.219

> Z:=(`[]`@@17230)(7,8):

> st:=time(): ans1:=[flat(Z)]: time()-st;
Error, (in flat) too many levels of recursion
                                    0.172

In case you are wondering about ListTools:-Flatten and deeply nested lists,

> st:=time(): ans1:=ListTools:-Flatten((`[]`@@59059)(7)): time()-st;
                                    1.904

> st:=time(): ans1:=ListTools:-Flatten((`[]`@@59060)(7)): time()-st;
Error, (in ListTools:-Flatten) too many levels of recursion
                                    1.528

I'm leaving out half the story, throughout, which is memory allocation increases by different methods.

For a simple list of many lists of lists (ie. shallow nesting with many children, and IMO likely the more common case), the comparative performance situation can look quite different

> Z:=[seq([[7,8]],i=1..100000)]:

> st:=time(): ans1:=[flat(Z)]: time()-st;
                                    2.527

> st:=time(): ans2:=flat2(Z): time()-st;
                                    0.187

> st:=time(): ans3:=ListTools:-Flatten(Z): time()-st;
                                    2.293

This was all in Maple 13.01 on Windows XP.

acer

There are effective differences between these,

flat := a->`if`(type(a,list), op(map(procname,a)), a):

flat2 := x -> [subsindets(x,list,t->op(t))]:

In cases of extreme nesting there could be tie-in with stacklimit, for the recursive call. And indeed the recursive method fails after hitting the recursion limit. For very deep nesting the subsindets may succeed, but only so slowly as to be useless.

> Z:=(`[]`@@17229)(7,8):

> st:=time(): ans1:=[flat(Z)]: time()-st; # very fast
                                    0.219

> Z:=(`[]`@@17230)(7,8):

> st:=time(): ans1:=[flat(Z)]: time()-st;
Error, (in flat) too many levels of recursion
                                    0.172

In case you are wondering about ListTools:-Flatten and deeply nested lists,

> st:=time(): ans1:=ListTools:-Flatten((`[]`@@59059)(7)): time()-st;
                                    1.904

> st:=time(): ans1:=ListTools:-Flatten((`[]`@@59060)(7)): time()-st;
Error, (in ListTools:-Flatten) too many levels of recursion
                                    1.528

I'm leaving out half the story, throughout, which is memory allocation increases by different methods.

For a simple list of many lists of lists (ie. shallow nesting with many children, and IMO likely the more common case), the comparative performance situation can look quite different

> Z:=[seq([[7,8]],i=1..100000)]:

> st:=time(): ans1:=[flat(Z)]: time()-st;
                                    2.527

> st:=time(): ans2:=flat2(Z): time()-st;
                                    0.187

> st:=time(): ans3:=ListTools:-Flatten(Z): time()-st;
                                    2.293

This was all in Maple 13.01 on Windows XP.

acer

By coincidence, now that the Mapleprimes Search facility has improved, I was thinking about sieving this site and collating all the requests for abstract linear algebra. Maybe that would help in the decision making.

The question comes up (with slightly differing functionality aspects, naturally) pretty regularly.

I have made some very modest efforts into this area. But they are very rough (in a backlog of unfinished prototype side-projects). So I doubt they would be of use to anyone, as is.

Part of the problem is knowing where to start. Collating the particular functionality requests seems like one reasonable place to begin. It's tempting to ask, "Ok, how do I lay down a comprehensive set of requirements, up front?" But if the horizon is too vast, that can be an impediment to making any headway. I asked a colleague, expert in programming, what one can do in extreme situations. The answer was that one way is to collect a smaller, manageable set of individual tasks, and see what would be required to solve them individually.

The technical question, of how to represent an abstract Matrix, is interesting. In the past, I've briefly looked at attributes on names, `is` and assumptions, and even modules or records. It's quicker to get going simply with attributes on names, but these days I'm leaning more toward modules or similar (despite their rather heavy nature).

On a forwards thinking note, I saw this the other day. Wouldn't it be nice to be able to do the same in Maple. (This looks like an impressive use of it.)

acer

If you expect to use a `simple' piece of code many times, inside some other procedures, then you might not want to take the performance hit of extra function calls just to get that simple code to run inside some parent procedure.

Maple function calls can be (relatively) expensive, so wrapping just a tiny code fragment inside a proc can have a measurable cost. For such reasons, the `option inline` exists for procedures. Compare the body of computational routine `f` below, when `Centroid` does or does not have option inline.

The idea is that `f` might do a long computation which calls `Centroid`many times. You can ignore the T stuff, and focus on the last part of the body of `f`, where the centroid computation takes place.

Notice in the printed 2D output below how the body of the second version of `f` has the centroid code inlined into it, avoiding the overhead cost of the function call to `Centroid`.

> Centroid:=proc(L) `+`(op(L))/nops(L) end proc:

> f:=proc()
  local T;
  T := [[1,2,3],[4,5,6],[8,9,10]];
  Centroid(T);
end proc;

   f := proc () local T; T := [[1, 2, 3], [4, 5, 6], [8, 9, 10]]; Centroid(T) end proc

> f(); # it works
                          [13  16  19]
                          [--, --, --]
                          [3   3   3 ]

> Centroid:=proc(L) option inline; `+`(op(L))/nops(L) end proc:

> f:=proc()
  local T;
  T := [[1,2,3],[4,5,6],[8,9,10]];
  Centroid(T);
end proc;

   f := proc() local T; T := [[1, 2, 3], [4, 5, 6], [8, 9, 10]]; (`+`(op(T)))/nops(T) end proc

> f(); # it still works
                          [13  16  19]
                          [--, --, --]
                          [3   3   3 ]

BTW, you seem to be suggesting that Maple should have a routine to compute centroids of lists. That notion has, built right into it, the idea that a list represents a point in space. That may be convenient sometimes, but a Vector (usual, or VectorCalculus) might be more useful. I'd agree that the `geometry` package's objects are too unwieldy.

The original versions posted here simply print the result, and return NULL. If that's really what one wants, inside some larger working procedure say, then why not use userinfo?

While I was composing the minor variant, using `+` and `op`, Joe posted the same.

note to admin: I realize now that I should have made this a branch post. Can that be done, after the fact? Thnx.

acer

First 464 465 466 467 468 469 470 Last Page 466 of 601