mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
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
This commit is contained in:
parent
7bd099d511
commit
59464bd6f9
@ -29,39 +29,33 @@
|
||||
*
|
||||
* Randomly generates a legal "traveling salesman" tour
|
||||
* (i.e. where each point is visited only once.)
|
||||
* Essentially, this routine fills an array with all possible
|
||||
* points on the tour and randomly chooses the 'next' city from
|
||||
* this array. When a city is chosen, the array is shortened
|
||||
* and the procedure repeated.
|
||||
*/
|
||||
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));
|
||||
/*
|
||||
* We must fill the tour[] array with a random permutation of the numbers
|
||||
* 1 .. num_gene. We can do that in one pass using the "inside-out"
|
||||
* variant of the Fisher-Yates shuffle algorithm. Notionally, we append
|
||||
* each new value to the array and then swap it with a randomly-chosen
|
||||
* array element (possibly including itself, else we fail to generate
|
||||
* permutations with the last city last). The swap step can be optimized
|
||||
* by combining it with the insertion.
|
||||
*/
|
||||
if (num_gene > 0)
|
||||
tour[0] = (Gene) 1;
|
||||
|
||||
for (i = 0; i < num_gene; i++)
|
||||
tmp[i] = (Gene) (i + 1);
|
||||
|
||||
remainder = num_gene - 1;
|
||||
|
||||
for (i = 0; i < num_gene; i++)
|
||||
for (i = 1; 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--;
|
||||
j = geqo_randint(root, i, 0);
|
||||
/* i != j check avoids fetching uninitialized array element */
|
||||
if (i != j)
|
||||
tour[i] = tour[j];
|
||||
tour[j] = (Gene) (i + 1);
|
||||
}
|
||||
|
||||
pfree(tmp);
|
||||
}
|
||||
|
||||
/* alloc_city_table
|
||||
|
Loading…
x
Reference in New Issue
Block a user