Carl Love

Carl Love

28045 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

@Mac Dude I can assure you that the declaration

uses TT= TypeTools;

works. It produces more-readable code than

uses TypeTools;

because a reader reading AddType wouldn't necessarily know that that comes from the TypeTools package, but by TT:-AddType, they would know.

A ModuleLoad procedure can be defined anywhere before its invocation, either in the module's declarations or body, but its invocation (or any procedure's invocation for that matter) must appear in the body.

 

 

@Joe Riel The OP hopes to replace run with a serious procedure; they just want to get this Profiling wrapper working before including the actual procedure, which I suspect is an implementation of Zassenhaus's algorithm for factoring polynomials over the integers.

Doesn't profiling essentially rewrite the procedure, similar to what trace does? I wouldn't be surprised if there's some funny business with a module trying to rewrite itself.

 

@sand15athome It is clear from the early-termination rule for and and andmap (also called the McCarthy rule) that Joe's procedure will be much faster than mine if the difference between the tables is found early. The one to use should be determined based on what you expect the average case to be: equal tables or unequal tables.

@vv I'm not sure about the exact definition of "parse" as opposed to the other levels of interpretation. Yes, the syntax of the inner procedure is checked when it's originally entered. But the assignment := is not done; the experiment that I suggested with print will prove that. There's some subtler stuff that happens between the syntax checking and the assignment. I believe that that stuff is done on the initial entry for a module, but at the execution time for a module.

Is there some reason that you object to a module?

It's a good Question. Vote Up. I've tried several things with your code, but I haven't figured out anything.

Something that seems weird to me is having option object and also returning thismodule. However, this isn't the cause of your error. If you haven't already, I suggest that you read chapters 8 and 9 of the Maple Programming Guide. It's available in the in-app help: just enter ?ProgrammingGuide. However, I find these chapters somewhat sketchy, and the only other option for help is asking here. I consider MaplePrimes members Joe Riel and Acer the world's best public source of information on these module subtleties.

@vv If you use a module, then the inner procedures only need to be "compiled" (or parsed) once; whereas if you use nested procedures, then the inner procedures need to be compiled on every run of the outer procedure. Also, with the module, the initializations only need to be done once. You can see this by including

local dummy:= print("Initializing now.");

in each.

I automatically think of modules whenever I need a variable that can't be global and can't be local to the inner procedure. In this case, node is such a variable.

My module can be simplified a little, and I would've done so if I'd thought of it at the time. Your procedure can be simplfied likewise.

#Test case generator, anonymous-procedure version
MakeTreeTable:= module()
local
   i, node,
   nextnode:= proc() node:= node+1 end proc,      
   ModuleApply:= proc(depth::nonnegint, width::nonnegint)
      node:= 0;
      proc(depth :: nonnegint, width :: nonnegint)
         if depth = 0 then nextnode()
         else table([seq(nextnode()=thisproc(depth-1,width), i=1..width)]);
         end if
      end proc
      (depth, width)
   end proc
;
end module:

Although some people have a stylistic objection to explicitly invoked anonymous procedures.

@emendes Yes, you're using the term monomial correctly.

I only have a vague idea of what you're talking about. Are you saying that you want all the subsets of a certain set that contain the element x*y*theta[5]? It'd help my understanding if you'd use mathematical terms such as set and subset.

It's very likely that what you want can be done by the Iterator package in such a way that all the objects don't need to be created at once. If you want all the subsets as I described in the first paragraph, then certainly it can be done.

@Joe Riel In the worksheet below, I made three changes to the tests:

  • I made some perhaps-trivial-seeming modifications to your procedure TableTest that add up to a significant time savings.
  • I created a better test case generator by modifying your MakeTable so that it doesn't repeat the indices. This is so that the procedures being tested will have a more-realistic amount of garbage collection.
  • I created a wrapper for CodeTools:-Usage that more accurately accounts for the garbage collection.

(Sorry, the worksheet uploading is not working for me.)

restart:

#Carl's original nested-table equality tester
TableToSet:= T-> `if`(T::table, {op(2, thisproc~(T))[]}, T):
TablesEqual:= (A::table, B::table)-> 
   evalb(TableToSet(A) = TableToSet(B))
:

#Joe's original nested-table equality tester
TableTest1:= proc(a := NULL, b := NULL)
local aindx, bindx;
    if a::table and b::table then
        aindx := {indices(a)};
        bindx := {indices(b)};
        aindx = bindx and andmap(i->TableTest1(a[op(i)],b[op(i)]), aindx);
    else
        evalb(a = b);
    end if;
end proc:

#Joe's procedure with some small modifications by Carl
TableTest2:= proc(a, b)
local aindx;
    if a::table and b::table then
        aindx := [indices(a, 'indexorder')];
        aindx = [indices(b, 'indexorder')] and andmap(i-> TableTest2(a[i[]],b[i[]]), aindx);
    else
        a = b;
    end if;
end proc:

#Test case generator
MakeTreeTable:= module()
local
   i, node,
   nextnode:= proc() node:= node+1 end proc,      
   MakeTable:= proc(depth :: nonnegint, width :: nonnegint)
      if depth = 0 then nextnode()
      else table([seq(nextnode()=thisproc(depth-1,width), i=1..width)]);
      end if
   end proc,
   ModuleApply:= proc(depth::nonnegint, width::nonnegint)
      node:= 0;
      MakeTable(depth, width)
   end proc
;
end module:

#Wrapper for CodeTools:-Usage that more accurately accounts for garbage collection
TimeTest:= module()
export output;
local
   #I read once that it takes 4 gc()s to collect all garbage. Some confirmation
   #of that would be welcome.
   gc4:= proc() to 4 do gc() od end proc,
   TestWithGC:= proc(Code::uneval)
      output:= CodeTools:-Usage(Code);
      CodeTools:-Usage(gc4()); #End test by collecting the garbage that the test made.
      output
   end proc,
   ModuleApply:= proc(Code::uneval)
      gc4(); #Start test with a fresh slate.
      CodeTools:-Usage(TestWithGC(Code))
   end proc
;
end module:

#Equal test cases
(A,B):= 'MakeTreeTable(5,10)' $ 2:

TimeTest(TableTest2(A,B));
memory used=33.40MiB, alloc change=256.00MiB, cpu time=547.00ms, real time=536.00ms, gc time=78.12ms
memory used=16.44KiB, alloc change=0 bytes, cpu time=344.00ms, real time=244.00ms, gc time=328.12ms
memory used=33.47MiB, alloc change=256.00MiB, cpu time=891.00ms, real time=782.00ms, gc time=406.25ms
                              true
TimeTest(TableTest1(A,B));
memory used=45.09MiB, alloc change=0 bytes, cpu time=735.00ms, real time=623.00ms, gc time=171.88ms
memory used=16.39KiB, alloc change=0 bytes, cpu time=312.00ms, real time=237.00ms, gc time=296.88ms
memory used=45.15MiB, alloc change=0 bytes, cpu time=1.05s, real time=860.00ms, gc time=468.75ms
                              true
TimeTest(TablesEqual(A,B));
memory used=84.59MiB, alloc change=32.00MiB, cpu time=500.00ms, real time=437.00ms, gc time=125.00ms
memory used=16.34KiB, alloc change=0 bytes, cpu time=344.00ms, real time=286.00ms, gc time=312.50ms
memory used=84.64MiB, alloc change=32.00MiB, cpu time=844.00ms, real time=723.00ms, gc time=437.50ms
                              true

 

@sand15athome You now have a reputation of 15 on the account sand15athome, so you should be able to vote up.

@emendes Ah. The cyclic dependency error must be a bug in Maple 14, because obviously there is no cyclic dependency.

I simplified the code of the procedure a little:

MyTest:= (
   F::list(algebraic), 
   V::And(list(name), satisfies(V-> nops(V)=nops(F)))
)->
   andmap(
      k-> ormap(depends, [F[..k-1][], F[k+1..][]], V[k]),  
      {$1..nops(V)}
   )
:

 

@Ronan The control to insert formatted code is the rightmost button on the second row of the toolbar in the editor. It looks like < > on top of a dog-eared piece of paper.

Tom Leslie also can't upload worksheets.

@vv I don't know about it being more-efficient computerwise, but it's much easier for me to think about multi-indices than nested tables. So perhaps it's more efficient brainwise.

My untested guess is that multi-indices would be a little bit less efficient computerwise because the indices need to be formed, then garbage-collected, as sequences.

I have an idea about constructing a time test of this, but I need to go right now, so I'll continue this later.

It is quite a chore to read through and edit your code, simply because it is not formatted. Please present your code with some reasonable style of indentation and line breaking. The error that you describe would be quite easy to find if the code was formatted. And please omit the prompts > from your code. It is also a chore for us to remove those.

@emendes They're polynomials.

I'm not familiar with the "cyclic" error. Can you post the exact error message so that I can fix it for Maple 14?

@Preben Alsholm The full Active Comversations page does seem to get updated immediatey. However, that's always another scroll, click, and page refresh away after you've deleted spam. Upon finishing deletion, it now takes you to the MaplePrimes home page. I don't like that. I'd like it to take you to the Active Conversations page immediately.

First 376 377 378 379 380 381 382 Last Page 378 of 709