Skip to content

Commit 59464bd

Browse files
committed
Improve implementation of GEQO's init_tour() function.
Rather than filling a temporary array and then copying values to the output array, we can generate the required random permutation in-place using the Fisher-Yates shuffle algorithm. This is shorter as well as more efficient than before. It's pretty unlikely that anyone would notice a speed improvement, but shorter code is better. Nathan Wagner, edited a bit by me
1 parent 7bd099d commit 59464bd

File tree

1 file changed

+19
-25
lines changed

1 file changed

+19
-25
lines changed

src/backend/optimizer/geqo/geqo_recombination.c

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,39 +29,33 @@
2929
*
3030
* Randomly generates a legal "traveling salesman" tour
3131
* (i.e. where each point is visited only once.)
32-
* Essentially, this routine fills an array with all possible
33-
* points on the tour and randomly chooses the 'next' city from
34-
* this array. When a city is chosen, the array is shortened
35-
* and the procedure repeated.
3632
*/
3733
void
3834
init_tour(PlannerInfo *root, Gene *tour, int num_gene)
3935
{
40-
Gene *tmp;
41-
int remainder;
42-
int next,
43-
i;
36+
int i,
37+
j;
4438

45-
/* Fill a temp array with the IDs of all not-yet-visited cities */
46-
tmp = (Gene *) palloc(num_gene * sizeof(Gene));
47-
48-
for (i = 0; i < num_gene; i++)
49-
tmp[i] = (Gene) (i + 1);
50-
51-
remainder = num_gene - 1;
39+
/*
40+
* We must fill the tour[] array with a random permutation of the numbers
41+
* 1 .. num_gene. We can do that in one pass using the "inside-out"
42+
* variant of the Fisher-Yates shuffle algorithm. Notionally, we append
43+
* each new value to the array and then swap it with a randomly-chosen
44+
* array element (possibly including itself, else we fail to generate
45+
* permutations with the last city last). The swap step can be optimized
46+
* by combining it with the insertion.
47+
*/
48+
if (num_gene > 0)
49+
tour[0] = (Gene) 1;
5250

53-
for (i = 0; i < num_gene; i++)
51+
for (i = 1; i < num_gene; i++)
5452
{
55-
/* choose value between 0 and remainder inclusive */
56-
next = geqo_randint(root, remainder, 0);
57-
/* output that element of the tmp array */
58-
tour[i] = tmp[next];
59-
/* and delete it */
60-
tmp[next] = tmp[remainder];
61-
remainder--;
53+
j = geqo_randint(root, i, 0);
54+
/* i != j check avoids fetching uninitialized array element */
55+
if (i != j)
56+
tour[i] = tour[j];
57+
tour[j] = (Gene) (i + 1);
6258
}
63-
64-
pfree(tmp);
6559
}
6660

6761
/* alloc_city_table

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy