[GAP Forum] Iteration Over Lists of Lists
Wolstenholme, Robert
robert.wolstenholme08 at imperial.ac.uk
Fri Jan 17 09:23:43 GMT 2014
Thanks, this is what I wanted.
However, I timed it this morning and found it to actually be slower than the method I previously mentioned (currently speed is of significant importance for what I'm doing). I've included the test script below. You can vary the values of `n` (number of lists) and `k` (size of lists). Note for `n=6` and `k=9` I am getting,
IteratorOfCartesianProduct Method: 452ms
My Mentioned Method : 203ms
Python for Reference : 066ms
I was hoping for something nearer the speed of the Python implementation.
Code (can be copied and pasted)
####################################################################################
n := 6;
k := 9;
############################
#IteratorOfCartesianProduct Method#
############################
lol := [];
for i in [1..n] do
lol[i] := [1..k];
od;
a := 1;
start := Runtime();
for x in IteratorOfCartesianProduct(lol) do
#a := a + 1;
#Print("x: ", x, "\n");
od;
total1 := Runtime() - start;
###################
#My Mentioned Method#
###################
size_rc := List([1..n], x -> k);
base := List([1..n], x -> 1); #We store the iteration step state in base
a := 1;
start := Runtime();
repeat
#Perform whatever list[i][base[i]] calculations here
#a := a + 1;
#Print("Base: ", base, "\n");
#Execute the incrementor
base[1] := base[1] + 1;
for j in [2..n] do
if base[j-1] = size_rc[j-1] + 1 then
base[j] := base[j] + 1;
base[j-1] := 1;
fi;
od;
until base[n] = size_rc[n] + 1;
total2 := Runtime() - start;
Print("\nTotal1: ", total1, "\nTotal2: ", total2);
####################################################################################
Thanks,
Rob
________________________________________
From: Alexander Konovalov [alexander.konovalov at gmail.com]
Sent: 16 January 2014 22:19
To: Wolstenholme, Robert
Cc: forum at mail.gap-system.org
Subject: Re: [GAP Forum] Iteration Over Lists of Lists
Very briefly (sorry, don't have time for a larger explanation today)
- in this case, see IteratorOfCartesianProduct. For example, after
lists := [];
lists[1] := [1,2,3];
lists[2] := [4,5];
try this:
gap> for x in IteratorOfCartesianProduct(lists) do Print(x,"\n");od;
[ 1, 4 ]
[ 1, 5 ]
[ 2, 4 ]
[ 2, 5 ]
[ 3, 4 ]
[ 3, 5 ]
This iterates over the cartesian product without generating the list of all tuples from it, and should work fast enough.
Best wishes
Alexander
On 16 Jan 2014, at 22:13, "Wolstenholme, Robert" <robert.wolstenholme08 at imperial.ac.uk> wrote:
> Thanks for the reply. I don't think I was clear enough with my initial question though so have given the example below:
>
> ###################################################################################
> Consider
>
> lists := []
> lists[1] := [1,2,3]
> lists[2] := [4,5]
>
> I would now like to iterate over the cartesian product of `lists[1]` and `lists[2]` i.e. `[[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]`.
>
> For an example this small, you could simply store the cartesian product itself in a list and iterate over that. This obviously becomes very inefficient if we have more lists with a larger number of values.
>
>
> A better way is, if we have `n` lists and `size_rc[i] := Size(list[i])`, we can avoid storing/calculating the Cartesian product with
>
> base := List([1..n], x -> 1); #We store the iteration step state in base
> while base <> size_rc do
>
> #Perform whatever list[i][base[i]] calculations here
>
> #Execute the incrementor
> base[1] := base[1] + 1;
> for j in [2..n] do
> if base[j-1] = size_rc[j-1] + 1 then
> base[j] := base[j] + 1;
> base[j-1] := 1;
> fi;
> od;
> od;
>
> then at each loop of the while `base` contains the values we need.
>
> However this is still far slower than the Python implementation I mentioned before. I was wondering if there was a way in GAP to speed up this iteration (maybe by pointing to the memory locations of the lists)?
>
> Thanks,
> Rob
>
> ________________________________________
> From: Alexander Konovalov [alexander.konovalov at gmail.com]
> Sent: 16 January 2014 22:01
> To: Wolstenholme, Robert
> Cc: forum at mail.gap-system.org
> Subject: Re: [GAP Forum] Iteration Over Lists of Lists
>
> On 16 Jan 2014, at 20:03, "Wolstenholme, Robert" <robert.wolstenholme08 at imperial.ac.uk> wrote:
>
>> Is there a way in GAP to 'quickly' iterate of lists of lists i.e. like the Python itertools.product() function?
>>
>
> Yes, see `21.20 Operations for Lists' from the GAP Reference Manual. You may enter `?Operations for Lists' in GAP or see it online at
>
> http://www.gap-system.org/Manuals/doc/ref/chap21.html#X7DF510F7848CBBFD
>
> A random example just to expose the syntax and some functions:
>
> gap> l:=List([1..10],i -> [1..i]);
> [ [ 1 ], [ 1, 2 ], [ 1 .. 3 ], [ 1 .. 4 ], [ 1 .. 5 ], [ 1 .. 6 ],
> [ 1 .. 7 ], [ 1 .. 8 ], [ 1 .. 9 ], [ 1 .. 10 ] ]
> gap> Sum( List( l, x -> Product( List( x, Fibonacci ) ) ) );
> 124819000
>
>
> HTH,
> Alexander
>
>
>
>
More information about the Forum
mailing list