I have two patches to make the geqo initialization and mutation
slightly better.

The first adjusts the mutation swaps to avoid having to re-pick
ties.  The second changes the initialization and shuffling algorithm
for the gene array to use an in-place Fisher-Yates shuffling
algorithm.

Diffs against commit 49124613f134b04594b1a5c46368eb0a5db16d4b
(i.e. tip of master as of when I re-made the diff).

On my system the patches pass a ./configure; make; make check

-- 
nw
>From c7f3c7cc37f943481b2358149210789be3d39ee9 Mon Sep 17 00:00:00 2001
From: Nathan Wagner <n...@hydaspes.if.org>
Date: Sun, 21 Sep 2014 09:30:01 +0000
Subject: [PATCH 1/2] cleanup geqo_mutation.c

Avoid a possible random number collision by choosing random
ranges better.  This will potentially change the output
of the algorithm since it avoids extra calls to geqo_randint().
---
 src/backend/optimizer/geqo/geqo_mutation.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/src/backend/optimizer/geqo/geqo_mutation.c 
b/src/backend/optimizer/geqo/geqo_mutation.c
index 1a06d49..c78bd2c 100644
--- a/src/backend/optimizer/geqo/geqo_mutation.c
+++ b/src/backend/optimizer/geqo/geqo_mutation.c
@@ -43,20 +43,18 @@ geqo_mutation(PlannerInfo *root, Gene *tour, int num_gene)
        int                     num_swaps = geqo_randint(root, num_gene / 3, 0);
        Gene            temp;
 
-
        while (num_swaps > 0)
        {
                swap1 = geqo_randint(root, num_gene - 1, 0);
-               swap2 = geqo_randint(root, num_gene - 1, 0);
+               swap2 = geqo_randint(root, num_gene - 2, 0);
 
-               while (swap1 == swap2)
-                       swap2 = geqo_randint(root, num_gene - 1, 0);
+               if (swap2 >= swap1)
+                       swap2++;
 
                temp = tour[swap1];
                tour[swap1] = tour[swap2];
                tour[swap2] = temp;
 
-
                num_swaps -= 1;
        }
 }
-- 
2.5.0

>From 47979bb844eda3821f08c1f00afc081ee0a3a260 Mon Sep 17 00:00:00 2001
From: Nathan Wagner <n...@hydaspes.if.org>
Date: Sun, 21 Sep 2014 13:02:48 +0000
Subject: [PATCH 2/2] rewrote array shuffler for geqo_recombination

This simplifies the array shuffling by doing it inplace
and eliminating a memory allocation and array initialization.

The output is identical in the sense that it still randomizes
an array, but the actual shuffled array will be different.
---
 src/backend/optimizer/geqo/geqo_recombination.c | 32 +++++++------------------
 1 file changed, 9 insertions(+), 23 deletions(-)

diff --git a/src/backend/optimizer/geqo/geqo_recombination.c 
b/src/backend/optimizer/geqo/geqo_recombination.c
index 652fadc..b327776 100644
--- a/src/backend/optimizer/geqo/geqo_recombination.c
+++ b/src/backend/optimizer/geqo/geqo_recombination.c
@@ -37,31 +37,17 @@
 void
 init_tour(PlannerInfo *root, Gene *tour, int num_gene)
 {
-       Gene       *tmp;
-       int                     remainder;
-       int                     next,
-                               i;
+       int     i, j;
 
-       /* Fill a temp array with the IDs of all not-yet-visited cities */
-       tmp = (Gene *) palloc(num_gene * sizeof(Gene));
-
-       for (i = 0; i < num_gene; i++)
-               tmp[i] = (Gene) (i + 1);
-
-       remainder = num_gene - 1;
-
-       for (i = 0; i < num_gene; i++)
-       {
-               /* choose value between 0 and remainder inclusive */
-               next = geqo_randint(root, remainder, 0);
-               /* output that element of the tmp array */
-               tour[i] = tmp[next];
-               /* and delete it */
-               tmp[next] = tmp[remainder];
-               remainder--;
+       /* shuffle tour in-place, uses Fisher-Yates inside-out algorithm */
+       for (i=0; i < num_gene; i++) {
+               j = geqo_randint(root, i, 0);
+               /* we could skip the compare and just assign */
+               if (i != j) {
+                       tour[i] = tour[j];
+               }
+               tour[j] = (Gene) i+1;
        }
-
-       pfree(tmp);
 }
 
 /* alloc_city_table
-- 
2.5.0

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to