Joe Riel's blog

Building a Set

I recently discovered a minor variation on the technique of building a set using a table. The purpose for using a table rather than inserting new items directly into a set is that, in a loop, the latter technique is O(n2) rather than O(n).  The way I would normally do this is to assign a counter and an empty table, and then, in a loop, compute the new element, increment the counter, and insert the element into the table at the counter index.  For example,

Faster Permutations

A recent post asks how to create a Maple permutation iterator, that is, a procedure that, on successive calls, iterates through each permutation of a given input.  I suggested a routine that solved the problem, however, I wasn't satisfied with it.  It was slower than it should be.  Later I suggested an improvement.  Here is another improvement.  It uses the same algorithm (algorithm L, from The Art of Computer Programming, vol. 4, fasicle 2, by Donald E. Knuth) if the input has repeated elements, but uses a different method, algorithm T, ibid., if the input consists of distinct elements.  The sequences of permutations for the two algorithms differ, the second algorithm uses the initial order for the first element and consecutive outputs differ by one transposition.

Recursive Types

John Fredsted suggested using the following procedure (slightly modified) to determine whether an expression was deeply algebraic.

isDeeplyAlgebraic := proc(x)
	if not type(x,'algebraic') then false
	elif type(x,'atomic') then true
	else andmap(procname,x)
	end if
end proc:

Rather than using a procedure as a predicate, this seems more usefully expressed as a type.  A nice way to  do that is with Maple's TypeTools[AddType] procedure.  For example

TypeTools:-AddType('DeeplyAlgebraic1'
                   , proc(x)
                         if not x :: 'algebraic' then false;
                         elif x :: 'atomic' then true;
                         else andmap(type,x,'DeeplyAlgebraic1');
                         end if;
                     end proc);

Folding Associative Operators

Maple's foldl and foldr procedures provide a convenient means to generate an n-ary function from a binary operator. For example, from another thread, one can use foldl to create an n-ary and procedure from Maple's binary `and` function:

Sorting listlists of integers

In a previous blog entry I described a novel method, proposed by Robert Israel, for sorting a list of lists of small positive integers, specifically those less than 256. It is significantly faster than the usual method. Roman Pearce responded with a method for rapidly sorting listlists of integers (a listlist is a list of sublists with identical number of elements), regardless of size. While not as fast as Robert's technique, it, too, is significantly faster than the usual method and has no restriction on integer size.

Applying a function to nested elements

A poster on the usenet group comp.soft-sys.math.maple asked how to do the following more simply:
A:={ { [1,2],[3,4] } , { [5,6],[7,8] } }:
map(x->map(y->map(f,y),x),A);

       {{[f(1), f(2)], [f(3), f(4)]}, {[f(5), f(6)], [f(7), f(8)]}}
As has been discussed here recently, this can be readily done using evalindets. For example,
evalindets(A, list, integer, f);
       {{[f(3), f(4)], [f(1), f(2)]}, {[f(5), f(6)], [f(7), f(8)]}}

Sorting Lists of Lists of Small Integers

John Fredsted asks whether there is a built-in method in Maple for lexically sorting a list of lists of small positive integers. There is not, however, Robert Israel provided two methods for accomplishing the task. The first uses the standard technique for extending Maple's sort procedure, that is, assigning a boolean-valued binary function and passing it to sort. The second method that Robert provided is ingenious. Here it is, in full,
Ls:= map(convert,L,bytes):
Ls:= sort(Ls, lexorder):
map(convert,Ls,bytes);

It converts each list into a string, sorts the strings, then converts the strings back to lists. This method is significantly faster than the previous. It does, however, have a limitation; it can only operate on lists with positive integers in the range 1..255. While that limitation was suitable for the original poster's application, that will not always be the case.

Maple Overload

The Maple overload command provides a useful mechanism for splitting the implementation of a procedure that operates on different types of arguments into separate procedures. This article describes the mechanism that it uses to select the procedures, illustrates subtle issues, and shows how they can be resolved.

Naming Numbers

The latest edition of TUGboat (vol. 28 no. 2, 2007), the journal of the TeX users group, contains an article by Edward Reingold, Writing numbers in words in TeX, which, as its title states, gives TeX macros for converting integers to names. In this case, American English names. For my amusement Sunday I wrote the equivalent procedure in Maple.

trying and failing

Occasionally it is necessary to temporarily assign a global flag to perform an action. Consider, for illustration, a procedure that returns the inert form of a procedure. We want it to be able to work with procedures that are local to modules. To do that, we need to temporarily assign the kernel flag opaquemodules to false.

First Attempt

GetInert1 := proc(p::uneval)
local opacity,inert;
    opacity := kernelopts('opaquemodules'=false);
    inert := ToInert(eval(p));
    kernelopts('opaquemodules'=opacity);
    inert;
end proc:

Here is a small module to test this on:

Syndicate content
}