MathGroup Archive 1998

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: prograMing: EquivalenceIndex



Xah wrote:
> 
> Another fun programing problem. In this problem, I'd be very interested
> if someone can come up with a solution that is either purely
> functional, or faster.
> 
> Problem:
> Write the function EquivalenceIndex. It's usage message is given below.
> 

Hi Xah, so this is my answer...

I didnt have enough spare time to recreate on your previous  prograMing
problems, but now I tried to recode your EquivalenceIndex function. 
First I made up the following short and fully functional version:

Remove[theSameAs,EquivalenceIndexCF1];           theSameAs[y_,li_] :=
Position[SameQ[#,z/.z->y]& /@ li,True]//Flatten;   (*1*)
EquivalenceIndexCF1[li_] := theSameAs[#,li]& /@ li //Union;            
(*2*)   

The definition on line 1 programs a function that gives you the indexes
of all the elements of li_ which are equivalent to y_. You may wonder
about
the "z/.z->y" thing, but writing just "y" instead doesnt work (why?).
Line 2 automatically applies the function of line 1 to all the members
of li_.
Equal element of the resulting list are deleted ("//Union"). The main
drawback of this is that elements of li_ which are already  known to
be in a equivalent class are tested again. (They are  a l l  tested !).

So I coded a mixture of functional and loop programming:

Remove[EquivalenceIndexCF2];
EquivalenceIndexCF2[li_, sameTestQ_:SameQ]:= Module[
    {
        idx={}, 
        l = Transpose@{li,Range@Length@li},                            
(*3*)
        elem, theSameAsElemIndexes
    },
    While[
        l != {},
        elem = First@First@l;                                          
(*4*)
        theSameAsElemIndexes = 
            Flatten @ Position[sameTestQ[elem,First@#]& /@ l, True];   
(*5*)
        AppendTo[
            idx,
            Part[l, theSameAsElemIndexes] /. {__,x_Integer}->x         
(*6*)
        ];
        l = Part[l, Complement[Range@Length@l, theSameAsElemIndexes] ];
(*7*)
    ];
    idx
];

Here li_ is eventually cut down. 
First the elements of li_ are supplied with their positions in li_ (see
line 3), e.g. f[x] in position 1 ist getting {f[x],1}.  
Then in each step of the "While"-loop the equivalence class of the first
element
of the first elem/pos-group (in our example: f[x]) is computed: First
you get their elements' positions in the (after previous steps, like in
line 1) 
remaining l-List (line 5), then the indexes of these elements in respect
to
the original li_ are extracted (line 6).  The equivalence class is
subtracted from l (line 7). 

We compare the four versions:
(on a Pentium 150 running OS/2, Mathematica 2.2.1 under Warp-Windows
3.11)

li=Table[Random[Integer,{1,6}],{200},{3}]; timeList = {
 Timing@EquivalenceIndexXah1[li],
 Timing@EquivalenceIndexXah2[li],
 Timing@EquivalenceIndexCF1[li],
 Timing@EquivalenceIndexCF2[li]
};

We get times that show that the CF2-Version is fastest:

First/@timeList
{2. Second, 4.12 Second, 3.72 Second, 1.38 Second}

where the results (after Mathematica-ordering via Union) are equal:

Equal@@Union/@(Part[#,2]& /@ timeList) True


regards
Clemens



  • Prev by Date: Re: Importing .pix files .
  • Next by Date: Re: lattice definition: help
  • Prev by thread: Re: prograMing: EquivalenceIndex
  • Next by thread: Re: prograMing: EquivalenceIndex