* geqo_selection.c
* linear selection scheme for the genetic query optimizer
*
- * Copyright (c) 1994, Regents of the University of California
+ * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: geqo_selection.c,v 1.8 1999/07/15 15:19:15 momjian Exp $
+ * src/backend/optimizer/geqo/geqo_selection.c
*
*-------------------------------------------------------------------------
*/
/* */
/*************************************************************/
-#include <math.h>
-
#include "postgres.h"
-#include "nodes/pg_list.h"
-#include "nodes/relation.h"
-#include "nodes/primnodes.h"
-
-
-#include "optimizer/internal.h"
-#include "optimizer/paths.h"
-#include "optimizer/pathnode.h"
-#include "optimizer/clauses.h"
-#include "optimizer/cost.h"
+#include <math.h>
-#include "optimizer/geqo_gene.h"
-#include "optimizer/geqo_selection.h"
#include "optimizer/geqo_copy.h"
#include "optimizer/geqo_random.h"
+#include "optimizer/geqo_selection.h"
-static int linear(int max, double bias);
+static int linear_rand(PlannerInfo *root, int max, double bias);
-/* geqo_selection
- *
+
+/*
+ * geqo_selection
* according to bias described by input parameters,
- * second genes are selected from the pool
+ * first and second genes are selected from the pool
*/
void
-geqo_selection(Chromosome *momma, Chromosome *daddy, Pool *pool, double bias)
+geqo_selection(PlannerInfo *root, Chromosome *momma, Chromosome *daddy,
+ Pool *pool, double bias)
{
int first,
second;
- first = (int) linear(pool->size, bias);
- second = (int) linear(pool->size, bias);
-
+ first = linear_rand(root, pool->size, bias);
+ second = linear_rand(root, pool->size, bias);
+
+ /*
+ * Ensure we have selected different genes, except if pool size is only
+ * one, when we can't.
+ *
+ * This code was observed to hang up in an infinite loop when the
+ * platform's implementation of erand48() was broken. We now always use
+ * our own version.
+ */
if (pool->size > 1)
{
while (first == second)
- second = (int) linear(pool->size, bias);
+ second = linear_rand(root, pool->size, bias);
}
- geqo_copy(momma, &pool->data[first], pool->string_length);
- geqo_copy(daddy, &pool->data[second], pool->string_length);
+ geqo_copy(root, momma, &pool->data[first], pool->string_length);
+ geqo_copy(root, daddy, &pool->data[second], pool->string_length);
}
-/* linear
+/*
+ * linear_rand
* generates random integer between 0 and input max number
* using input linear bias
*
+ * bias is y-intercept of linear distribution
+ *
* probability distribution function is: f(x) = bias - 2(bias - 1)x
* bias = (prob of first rule) / (prob of middle rule)
- *
*/
-
static int
-linear(int pool_size, double bias) /* bias is y-intercept of linear
- * distribution */
+linear_rand(PlannerInfo *root, int pool_size, double bias)
{
double index; /* index between 0 and pop_size */
double max = (double) pool_size;
- index = max * (bias - sqrt((bias * bias) - 4.0 * (bias - 1.0) * geqo_rand()))
- / 2.0 / (bias - 1.0);
+ /*
+ * If geqo_rand() returns exactly 1.0 then we will get exactly max from
+ * this equation, whereas we need 0 <= index < max. Also it seems
+ * possible that roundoff error might deliver values slightly outside the
+ * range; in particular avoid passing a value slightly less than 0 to
+ * sqrt(). If we get a bad value just try again.
+ */
+ do
+ {
+ double sqrtval;
+
+ sqrtval = (bias * bias) - 4.0 * (bias - 1.0) * geqo_rand(root);
+ if (sqrtval > 0.0)
+ sqrtval = sqrt(sqrtval);
+ index = max * (bias - sqrtval) / 2.0 / (bias - 1.0);
+ } while (index < 0.0 || index >= max);
return (int) index;
}