Carl Love

Carl Love

28050 Reputation

25 Badges

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

MaplePrimes Activity


These are replies submitted by Carl Love

@emendes For Maple 14, use this (which I just posted in response to vv):

IndicesOfMatches:= proc(L::list)
local T, k;
     for  k to nops(L) do T[L[k]][k]:= () end do;
     [indices]~([entries(T, nolist)], nolist)
end proc:

This is essentially what you would get if you carefully deconstructed ListTools:-Classify specifically for this application. Once again, if you require the lists to be in a certain order, it's a simple modification.

If you're using Maple's 2d-input, I would strongly encourage you not to. But if you insist, then you may need to change () to NULL in the above.

@vv Whether or not your code is faster depends on the average length of the subsets. In the comparison that I made with Tom's code, that average was ~10. Watch what happens if I make that average ~10000:

R:= rand(1..9):
L:= ['R()' $ 99999]:
r1:= CodeTools:-Usage(
     {entries(((x-> x[2])~)~(ListTools:-Classify(x-> x[1], `[]`~(L, [$1..nops(L)]))), nolist)}
):

memory used=31.10MiB, alloc change=0 bytes, cpu time=422.00ms, real time=426.00ms, gc time=93.75ms

ff:=proc(a)
local aa,sa:=convert(a,set),T,u;
aa:=zip(`[]`,a,[$1..nops(a)]);
for u in sa do T[u]:=NULL od;
for u in aa do T[u[1]]:=T[u[1]],u[2] od;
[seq([T[u]],u=sa)];
end:

r3:= CodeTools:-Usage(ff(L)):

memory used=4.16GiB, alloc change=0 bytes, cpu time=16.61s, real time=11.99s, gc time=13.14s

evalb(r1 = {(_-> {_[]})~(r3)[]});
     true

Your code can be improved by not using iterative appending on the subsets (your table entries). Rather, each of those entries should itself be a table. Thus:

f4:= proc(a)
local T, u;
     for  u in `[]`~(a, [$1..nops(a)]) do T[u[1]][u[2]]:= () od;
     {indices}~({entries(T, nolist)}, nolist)
end proc:

r4:= CodeTools:-Usage(f4(L)):
memory used=22.67MiB, alloc change=0 bytes, cpu time=250.00ms, real time=230.00ms, gc time=78.12ms

evalb(r1 = r4);
     true

 

@taro Yes, lprint is the key to analyzing these funky name constructs. It's what I used to figure out the op numbers for my deconstructors. Working in the opposite direction, constructing names, requires nprintf. The syntax is identical to sprintf.

FourCornerScripts:= (Center, UpperLeft, LowerLeft, UpperRight, LowerRight)->
    nprintf(
        cat("#mscripts(mi(\"%a\"),", "none(),"$4, "mn(\"%a\"),mn(\"%a\"))"),
        Center, LowerLeft, UpperLeft
    )[LowerRight]^UpperRight
:
FourCornerScripts(B, 1, 2, 3, 4);

@ x-> x[1] extracts the first element of a pair [a,b]; x-> x[2] extracts the second element. It should be trivial for you to explode my code step-by-step. Nonetheless, here I have done it for you:

a:=[[x+y+z],[2*x+y+z],[x-y+z],[2*x+y+z]];

[[x+y+z], [2*x+y+z], [x-y+z], [2*x+y+z]]

nops(a);

4

$1..%;

1, 2, 3, 4

[%];

[1, 2, 3, 4]

#`[]` is equivalent to ()-> [args], but is faster because it's builtin.
zip(`[]`, a, %);

[[[x+y+z], 1], [[2*x+y+z], 2], [[x-y+z], 3], [[2*x+y+z], 4]]

map(x-> x[1], %);

[[x+y+z], [2*x+y+z], [x-y+z], [2*x+y+z]]

ListTools:-Classify(x-> x[1], %%);

table( [( [x-y+z] ) = {[[x-y+z], 3]}, ( [2*x+y+z] ) = {[[2*x+y+z], 2], [[2*x+y+z], 4]}, ( [x+y+z] ) = {[[x+y+z], 1]} ] )

map(e-> map(x-> x[2], e), %);

table( [( [x-y+z] ) = {3}, ( [2*x+y+z] ) = {2, 4}, ( [x+y+z] ) = {1} ] )

entries(%);

[{3}], [{2, 4}], [{1}]

entries(%%, nolist);

{3}, {2, 4}, {1}

{%};

{{1}, {3}, {2, 4}}

 

 

Download Classify.mw

@tomleslie I'm not saying that you were claiming that your code was particularly efficient---indeed there's something to be said for its simplicity---but you may be shocked to see just how inefficient it is:

R:= rand(1..999):
L:= ['R()' $ 9999]:
r1:= CodeTools:-Usage(
     {entries(((x-> x[2])~)~(ListTools:-Classify(x-> x[1], `[]`~(L, [$1..nops(L)]))), nolist)}
):
memory used=5.58MiB, alloc change=4.00MiB, cpu time=31.00ms, real time=46.00ms, gc time=0ns

r2:= CodeTools:-Usage(
     {seq({ListTools:-SearchAll(j,L)}, j in L)}
):

memory used=10.47GiB, alloc change=0 bytes, cpu time=89.48s, real time=89.49s, gc time=5.38s

evalb(r1 = r2);
     true

89.48/.031;
     2886.45161290323

The reason for the inefficiency is that your code repeatedly performs linear searches over the same list.

 

@tomleslie I wasn't claiming that you were claiming that any commands were threadsafe. Rather, I was addressing the following comment of yours:

Of course your original calculation should run multithreaded. At the moment I can't figure out why it doesn't....

@tomleslie The commands solve, fsolve, and int---like the vast majority of more-complicated Maple commands---aren't "thread safe". They can't be used with Threads. See ?index,threadsafe.

@taro There's no problem with the accuracy of your use of eval. The problem is with efficiency. Like I said, it forces the recomputation of the symbolic derivative every time that it's used. In other words, every time that you use eval(g(x), x= a), Maple does these steps:

x^2 is converted to 2*x, then a is substituted for x.

Using D, the conversion x^2 to 2*x is done only once, at the time g is defined, and it's only the substitution step that's done for every invocation of g.

Here's an example showing the timing difference for a complicated function:

f:= unapply(randpoly([exp,sin,cos,arctan](x), degree= 23, dense), x):
g:= x-> diff(f(x),x):
gD:= D(f):
time(eval(g(x), x= 2));

     0.218

gc(); time(gD(2));

     0.109

gc(); time(eval(g(x), x= 3));

     0.234

gc(); time(gD(3));

     0.109

By "pre-subscript", do you mean the x in x[1] or x__1? By "pre-superscript", do you mean the x in x^2?

@taro Your use of eval isn't a good way to do this. I almost consider it an accident or a coincidence that it works at all. The biggest problem with it is that it forces the re-computation of the symbolic derivative every time it is used.

It can be done without D by using unapply:

f:= x-> x^2:
g:= unapply(diff(f(x),x), x);
g(2);

Indeed, D is essentially just a combination of unapply and diff.

@alfarunner The back quotes used on the `if` are an essential part of Maple syntax, and they're used in a great many commands other than `if`. My guess is that you're not using the correct quote. The correct one is (on a standard US keyboard) the key on the upper left, the leftmost key in the second row, under ESC.

The piecewise is an appropriate alternative to `if` in this case, but that won't always be true.

You can always substitute ifelse (without quotes) for `if`. This is a purely syntactic substitution that will always work. But there are other situations where the back quotes (also called "name" quotes in Maple) will be needed.

 

@nidojan To show you appreciation for my help, you can click on the Thumb icon and/or the Trophy Cup icon in the upper right corner of my Answer.

Please don't ever---on any forum---delete a legitimate question that already has a legitimate answer. To do so is incredibly disrespectful to the person who took the time to answer.

@vv Only a computer or a person with a very limited imagination and no understanding of recursion would give 31 as the answer. If it's a "puzzle", not just a problem, I think that an answer based on a first-order recursion would always be preferable to one that's not.

@emendes No problem. Let's name the procedure P.

P:= proc(f::list, vars::And(list, satisfies(vars-> nops(vars) = nops(f))))
     #...statements...
end proc:

There's no need for the parameter of the satisfies procedure to have the same name as the corresponding parameter of P, so that can be shortened to

P:= proc(f::list, vars::And(list, satisfies(v-> nops(v) = nops(f))))
     #...statements...
end proc:

Here's a third way, completely different:

P:= proc(f::list, vars::depends([anything $ nops(f)]))
     #...statements...
end proc:

In this way, it's the square brackets that force vars to be a list, the $ nops(f) that forces it to be a certain length, the anything is a primitive type that matches any single thing, and the depends is a keyword that signals that the type check for vars depends on f. For reasons that I don't understand, the depends isn't needed when the dependency is inside a satisfies.

Please let me know if you have any more questions.

@nidojan Okay, now we're getting somewhere. However, the errors are not quite the same. If you want me to take your question seriously, please point out how the two error messages are different. In the process, you may begin to understand the fundamental problem. Hint: It is a purely mathematical error; it has nothing to do with computer coding.

First 389 390 391 392 393 394 395 Last Page 391 of 709