/*****************************************************************************
*     FILE: set.c: This file contains all the routines that set values in the
*                  context variable
*
*     Authors: David M. Levine, Philip L. Hallstrom, David M. Noelle
*****************************************************************************/
#include "pgapack.h"

/*U****************************************************************************
   PGASetPopSize - Specifies the size of the genetic algorithm population.
   The default population size is 100.

   Category: Generation

   Inputs:
      ctx     - context variable
      popsize - the genetic algorithm population size to use
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetPopSize(ctx,200);
      
****************************************************************************U*/
void PGASetPopSize (PGAContext *ctx, int popsize)
{

    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetPopSize", "Entered", 
                   PGA_VOID, NULL );

    if (ctx->sys.SetUpCalled)
	 PGAError(ctx, "PGASetPopSize: Function must be called BEFORE call to"
		  " PGASetUp", PGA_FATAL, PGA_VOID, NULL);
    else if (popsize < 1 || popsize % 2)
        PGAError( ctx, "PGASetPopSize: Invalid value of popsize:",
                  PGA_FATAL, PGA_INT, (void *) &popsize );
    else
        ctx->ga.PopSize = popsize;

    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetPopSize", "Exit", 
                   PGA_VOID, NULL );
    return;

}

/*U****************************************************************************
   PGASetStoppingRule - specify a stopping criterion.  If called more than
   once the different stopping criterion are ORed together.  Valid choices
   are PGA_STOP_MAXITER, PGA_STOP_TOOSIMILAR, or PGA_STOP_NOCHANGE to
   specify iteration limit reached, population too similar, or no change in
   the best solution found in a given number of iterations, respectively.
   The default is to stop when a maximum iteration limit (which by default
   is 1000) is reached.

   Category: Generation

   Inputs:
      ctx      - context variable
      stoprule - symbolic constant to specify stopping rule
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetStoppingRule(ctx,PGA_STOP_TOOSIMILAR);
      
****************************************************************************U*/
void PGASetStoppingRule (PGAContext *ctx, int stoprule)
{

    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetStoppingRule", "Entered", 
                   PGA_VOID, NULL );

    if (ctx->sys.SetUpCalled)
	 PGAError(ctx, "PGASetStoppingRule: Function must be called BEFORE "
		  "call to PGASetUp", PGA_FATAL, PGA_VOID, NULL);
    else
	 switch (stoprule)
	 {
	 case PGA_STOP_MAXITER  :
	 case PGA_STOP_NOCHANGE :
	 case PGA_STOP_TOOSIMILAR :
	      ctx->ga.StoppingRule |= stoprule;
	      break;
	 default:
	      PGAError( ctx,
		       "PGASetStoppingRule: Invalid value of stoprule:",
		       PGA_FATAL, PGA_INT, (void *) &stoprule );
	 };
    
    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetStoppingRule", "Exit", 
		  PGA_VOID, NULL );
    return;
}

/*U****************************************************************************
   PGASetMaxIter - specify the maximum number of iterations for the stopping
   rule PGA_STOP_MAXITER (which, by itself, is the default stopping rule and
   is always in effect).  The default value is 1000 iterations.
   
   Category: Generation

   Inputs:
      ctx     - context variable
      maxiter - the maximum number of GA iterations to run before stopping
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetMaxIter(ctx,5000);
      
****************************************************************************U*/
void PGASetMaxIter(PGAContext *ctx, int maxiter)
{
    
     PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetMaxIter", "Entered", 
                   PGA_VOID, NULL );
     
     if (ctx->sys.SetUpCalled)
	  PGAError(ctx, "PGASetMaxIter: Function must be called BEFORE "
		   "call to PGASetUp", PGA_FATAL, PGA_VOID, NULL);
     else if (maxiter < 1)
	  PGAError( ctx, "PGASetMaxIter: Invalid value of maxiter:",
		   PGA_FATAL, PGA_INT, (void *) &maxiter );
     else
	  ctx->ga.MaxIter = maxiter;
     
     PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetMaxIter", "Exit", 
		   PGA_VOID, NULL );
     return;
}

/*U****************************************************************************
   PGASetMaxNoChange - specifiy maximum number of iterations of no change in
   the evaluation function value of the best string before stopping.  The
   default value is 50.  The stopping rule PGA_STOP_NOCHANGE must have been
   set by PGASetStoppingRule for this function call to have any effect.
   
   Category: Generation

   Inputs:
      ctx     - context variable
      maxiter - the maximum number of GA iterations to run before stopping
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetMaxIter(ctx,5000);
      
****************************************************************************U*/
void PGASetMaxNoChange(PGAContext *ctx, int max_no_change)
{
     PGADebugPrint(ctx, PGADEBUG_ENTERED, "PGASetMaxNoChange", "Enter",
		   PGA_VOID, NULL);
     if (ctx->sys.SetUpCalled)
	  PGAError(ctx, "PGASetMaxNoChange: Function must be called BEFORE "
		   "call to PGASetUp", PGA_FATAL, PGA_VOID, NULL);
     else if (max_no_change > 0)
	  ctx->ga.MaxNoChange = max_no_change;
     else
	  PGAError(ctx, "PGASetMaxNoChange: Invalid value of max_no_change:",
		   PGA_FATAL, PGA_INT, (void *) &max_no_change);
     PGADebugPrint(ctx, PGADEBUG_EXIT, "PGASetMaxNoChange", "Exit",
		   PGA_VOID, NULL);
}

/*U****************************************************************************
   PGASetMaxSimilarity - Specifiy the maximum percent of homogeneity of the
   population before stopping.  The similarity measure is the same evaluation
   function value.  The default value is 95 percent.  The stopping rule
   PGA_STOP_TOOSIMILAR must have been set by PGASetStoppingRule for this
   function call to have any effect.
   
   Category: Generation

   Inputs:
      ctx     - context variable
      maxiter - the maximum number of GA iterations to run before stopping
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetMaxSimilarity(ctx,99);
      
****************************************************************************U*/
void PGASetMaxSimilarity(PGAContext *ctx, int max_similarity)
{
     PGADebugPrint(ctx, PGADEBUG_ENTERED, "PGASetMaxSimilarity", "Enter",
		   PGA_VOID, NULL);

     if (ctx->sys.SetUpCalled)
	  PGAError(ctx, "PGASetMaxSimilarity: Function must be called BEFORE "
		   "call to PGASetUp", PGA_FATAL, PGA_VOID, NULL);
     else if (max_similarity > 0 && max_similarity <= 100)
	  ctx->ga.MaxSimilarity = max_similarity;
     else
	 PGAError(ctx, "PGASetMaxSimilarity: Invalid value of max_similarity:",
		  PGA_FATAL, PGA_INT, (void *) &max_similarity);
     PGADebugPrint(ctx, PGADEBUG_EXIT, "PGASetMaxSimilarity", "Exit",
		   PGA_VOID, NULL);
}


/*U****************************************************************************
   PGASetNumReplace - specifies the number of new strings to create each
   GA generation.  The default is ten percent of the population size

   Category: Generation

   Inputs:
      ctx         - context variable
      pop_replace - the genetic algorithm population size to use
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetNumReplace(ctx,35);
      
****************************************************************************U*/
void PGASetNumReplace( PGAContext *ctx, int pop_replace)
{
    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetNumReplace", "Entered", 
                   PGA_VOID, NULL );

    if (pop_replace < 0)
      PGAError( ctx,
               "PGASetNumReplace: Invalid value of pop_replace:",
                PGA_FATAL, PGA_INT, (void *) &pop_replace );
    else
	ctx->ga.NumReplace = pop_replace;

    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetNumReplace", "Exit", 
                   PGA_VOID, NULL );
    return;
}

/*U****************************************************************************
   PGASetCrossoverType - specify the type of crossover to use. Valid choices
   are PGA_CROSSOVER_ONEPT, PGA_CROSSOVER_TWOPT, or PGA_CROSSOVER_UNIFORM for
   one-point, two-point, and uniform crossover, respectively.  The default is
   two-point crossover.

   Category: Crossover

   Inputs:
      ctx            - context variable
      crossover_type - symbolic constant to specify crossover type
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetCrossoverType(ctx, PGA_CROSSOVER_UNIFORM);
      
****************************************************************************U*/
void PGASetCrossoverType (PGAContext *ctx, int crossover_type)
{

    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetCrossoverType", "Entered", 
                   PGA_VOID, NULL );
    
    switch (crossover_type) {
        case PGA_CROSSOVER_ONEPT:
        case PGA_CROSSOVER_TWOPT:
        case PGA_CROSSOVER_UNIFORM:
            ctx->ga.CrossoverType = crossover_type;
            break;
        default:
            PGAError( ctx,
                     "PGASetCrossoverType: Invalid value of crossover_type:",
                      PGA_FATAL, PGA_INT, (void *) &crossover_type );
    };

    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetCrossoverType", "Exit", 
                   PGA_VOID, NULL );
    return;
}


/*U****************************************************************************
   PGASetCrossoverProb - Probability that a selected string will undergo
   crossover.  The default is 0.85.

   Category: Crossover

   Inputs:
      ctx - context variable
      p   - the crossover probability
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetCrossoverProb(ctx,0.001);
      
****************************************************************************U*/
void PGASetCrossoverProb( PGAContext *ctx, double crossover_prob)
{
    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetCrossoverProb", "Entered", 
                   PGA_VOID, NULL );
    
    if ((crossover_prob < 0.0) || (crossover_prob > 1.0))
        PGAError ( ctx,
                  "PGASetCrossoverProb: Invalid value of crossover_prob:",
                   PGA_FATAL, PGA_DOUBLE, (void *) &crossover_prob);
    else
        ctx->ga.CrossoverProb = crossover_prob;

    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetCrossoverProb", "Exit", 
                   PGA_VOID, NULL );
    return;
}

/*U****************************************************************************
   PGASetUniformCrossProb - Probability used in uniform crossover to specify
   that an allele value value be selected from a particular parent. The
   default is 0.6.  The crossover type must have been set to
   PGA_CROSSOVER_UNIFORM with PGASetCrossoverType for this function call
   to have any effect.

   Category: Crossover

   Inputs:
      ctx - context variable
      p   - the crossover probability
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetUniformCrossProb(ctx,0.9);
      
****************************************************************************U*/
void PGASetUniformCrossProb( PGAContext *ctx, double uniform_cross_prob)
{
    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetUniformCrossProb", "Entered", 
                   PGA_VOID, NULL );
    
    if ((uniform_cross_prob < 0.0) || (uniform_cross_prob > 1.0))
        PGAError ( ctx,
                  "PGASetUniformCrossProb: Invalid value of uniform_cross_prob:",
                   PGA_FATAL,
                   PGA_DOUBLE,
		  (void *) &uniform_cross_prob);
    else
        ctx->ga.UniformCrossProb = uniform_cross_prob;

    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetUniformCrossProb", "Exit", 
                   PGA_VOID, NULL );
    return;
}


/*U****************************************************************************
   PGASetSelectType - specify the type of selection to use. Valid choices
   are PGA_SELECT_PROPORTIONAL, PGA_SELECT_SUS, PGA_SELECT_TOURNAMENT, and 
   PGA_SELECT_PTOURNAMENT for proportional, stochastic universal selection,
   tournament, and probabilistic tournament selection, respectively.  The
   default is tournament selection.

   Category: Selection

   Inputs:
      ctx         - context variable
      select_type - symbolic constant to specify selection type
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetSelectType(ctx, PGA_SELECT_SUS);
      
****************************************************************************U*/
void PGASetSelectType( PGAContext *ctx, int select_type)
{

    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetSelectType", "Entered", 
                   PGA_VOID, NULL );
    
    switch (select_type) {
        case PGA_SELECT_PROPORTIONAL:
        case PGA_SELECT_SUS:
        case PGA_SELECT_TOURNAMENT:
        case PGA_SELECT_PTOURNAMENT:
            ctx->ga.SelectType = select_type;
            break;
        default:
            PGAError ( ctx,
                       "PGASetSelectType: Invalid value of select_type:",
                       PGA_FATAL, PGA_INT, (void *) &select_type);
	break;
    }

    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetSelectType", "Exit", 
                   PGA_VOID, NULL );
    return;
}


/*U****************************************************************************
   PGASetPTournamentProb - Specifies the probability that the string that wins
   a binary tournament will be selected. The default value is 0.6. This
   function will have no effect unless PGA_SELECT_PTOURNAMENT was specified
   as the type of selection to use with PGASetSelectType.

   Category: Selection

   Inputs:
      ctx - context variable
      p   - the probability of selecting the better string
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetPTournamentProb(ctx,0.8);
      
****************************************************************************U*/
void PGASetPTournamentProb(PGAContext *ctx, double ptournament_prob)
{
     PGADebugPrint(ctx, PGADEBUG_ENTERED, "PGASetPTournament", "Entered",
		   PGA_VOID, NULL);

     ctx->ga.PTournamentProb = ptournament_prob;

     PGADebugPrint(ctx, PGADEBUG_EXIT, "PGASetPTournament", "Entered",
		   PGA_VOID, NULL);
}


/*U****************************************************************************
   PGASetFitnessType - Set the type of fitness algorithm to use. Valid choices
   are PGA_FITNESS_RAW, PGA_FITNESS_NORMAL, or PGA_FITNESS_RANKING for
   raw fitness (the evaluation function value), linear normalization, or
   linear ranking, respectively.  The default is PGA_FITNESS_RAW.

   Category: Fitness

   Inputs:
      ctx          - context variable
      fitness_type - symbolic constant to specify fitness type
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetFitnessType(ctx,PGA_FITNESS_RANKING);
      
****************************************************************************U*/
void PGASetFitnessType( PGAContext *ctx, int fitness_type)
{

    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetFitnessType", "Entered", 
                   PGA_VOID, NULL );
    
    switch (fitness_type) {
        case PGA_FITNESS_RAW:
        case PGA_FITNESS_NORMAL:
        case PGA_FITNESS_RANKING:
            ctx->ga.FitnessType = fitness_type;
            break;
        default:
            PGAError ( ctx,
                      "PGASetFitnessType: Invalid value of fitness_type:",
                       PGA_FATAL, PGA_INT, (void *) &fitness_type);
	break;
    }

    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetFitnessType", "Exit", 
                   PGA_VOID, NULL );
    return;
}

/*U****************************************************************************
   PGASetFitnessMinType - sets the type of algorithm used if a minimization
   problem is specified to determine how values are remapped for maximization.
   Valid choices are PGA_FITNESSMIN_RECIPROCAL and PGA_FITNESSMIN_CMAX to do
   the mapping using the reciprocal of the evaluation function, or by
   subtracting the worst evaluation function value from each evaluation
   function value, respectively.  The default is PGA_FITNESSMIN_CMAX

   Category: Fitness

   Inputs:
      ctx          - context variable
      fitness_type - symbolic constant to specify fitness minimization type
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetFitnessMinType(ctx,PGA_FITNESSMIN_CMAX);
      
****************************************************************************U*/
void PGASetFitnessMinType( PGAContext *ctx, int fitness_type)
{

    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetFitnessMinType", "Entered", 
                   PGA_VOID, NULL );
    
    switch (fitness_type) {
        case PGA_FITNESSMIN_RECIPROCAL:
        case PGA_FITNESSMIN_CMAX:
            ctx->ga.FitnessMinType = fitness_type;
            break;
        default:
            PGAError ( ctx,
                      "PGASetFitnessMinType: Invalid value of fitness_type:",
                       PGA_FATAL, PGA_INT, (void *) &fitness_type);
	break;
    }

    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetFitnessMinType", "Exit", 
                   PGA_VOID, NULL );
    return;
}

/*U****************************************************************************
   PGASetFitnessRankMax - The value of the parameter Max when using linear
   ranking for fitness determination. The default value is 1.2.  The value
   must be from the interval [1.0,2.0].  The fitness type must have been set
   to PGA_FITNESS_RANKING  with PGASetFitnessType for this function call
   to have any effect.

   Category: Fitness

   Inputs:
      ctx - context variable
      max - the value of the parameter Max when using linear ranking
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetFitnessRankMax(ctx,1.1);
      
****************************************************************************U*/
void PGASetFitnessRankMax( PGAContext *ctx, double fitness_rank_max)
{
    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetFitnessRankMax", "Entered", 
                   PGA_VOID, NULL );
    
    if ((fitness_rank_max < 1.0) || (fitness_rank_max > 2.0))
        PGAError ( ctx,
                  "PGASetFitnessRankMax: Invalid value of fitness_rank_max:",
                   PGA_FATAL, PGA_DOUBLE, (void *) &fitness_rank_max);
    else
        ctx->ga.FitnessRankMax = fitness_rank_max;

    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetFitnessRankMax", "Exit", 
                   PGA_VOID, NULL );
    return;
}


/*U****************************************************************************
   PGASetMutationType - set type of mutation to use.  The type of mutation
   varies with the data type.  Valid choices are PGA_MUTATION_FIXED,
   PGA_MUTATION_STRINGLEN, PGA_MUTATION_HAMMING, PGA_MUTATION_UNIFORM, or
   PGA_MUTATION_GAUSSIAN.  See the user guide for more details.

   Category: Mutation

   Inputs:
      ctx           - context variable
      mutation_type - symbolic constant to specify the mutation type
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetMutationType(ctx, PGA_MUTATION_UNIFORM);
      
****************************************************************************U*/
void PGASetMutationType( PGAContext *ctx, int mutation_type)
{
     PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetMutationType", "Entered", 
                   PGA_VOID, NULL );
    
     switch (mutation_type)
     {
     case PGA_MUTATION_FIXED:
     case PGA_MUTATION_STRINGLEN:
     case PGA_MUTATION_HAMMING:
     case PGA_MUTATION_UNIFORM:
     case PGA_MUTATION_GAUSSIAN:
	  ctx->ga.MutationType = mutation_type;
	  break;
     default:
	  PGAError ( ctx,
		    "PGASetMutationType: Invalid value of mutation_type:",
		    PGA_FATAL, PGA_INT, (void *) &mutation_type);
	  break;
     }

    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetMutationType", "Exit", 
                   PGA_VOID, NULL );
    return;
}

/*U****************************************************************************
   PGASetMutateOnlyNoCross - A boolean flag to indicate if recombination uses
   crossover OR mutation on selected strings (the default), or crossover AND
   mutation.
  
   Category: Generation

   Inputs:
      ctx  - context variable
      flag - PGATRUE (default) or PGAFALSE
      
   Outputs:
      None

   Example:
      To use crossover AND mutation for recombination use
      
      PGAContext *ctx;
      :
      PGASetMutateOnlyNoCross(ctx,PGAFALSE);
      
****************************************************************************U*/
void PGASetMutateOnlyNoCross( PGAContext *ctx, int mutate_only_no_cross)
{
    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetMutateOnlyNoCross","Entered", 
                   PGA_VOID, NULL );
    
    switch (mutate_only_no_cross) {
        case PGATRUE:
        case PGAFALSE:
            ctx->ga.MutateOnlyNoCross = mutate_only_no_cross;
            break;
        default:
            PGAError ( ctx,
                      "PGASetMutateOnlyNoCross: Invalid value of mutate_only_no_cross:",
                       PGA_FATAL, PGA_INT, (void *) &mutate_only_no_cross);
	break;
    }
    
    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetMutateOnlyNoCross","Exit", 
                   PGA_VOID, NULL );
    return;
}


/*U****************************************************************************
   PGASetMutationRealVal - Set multiplier to mutate Real strings with.  The
   use of this value depends on the type of mutation being used.  See the user
   guide for more details.  The default value is 0.1.

   Category: Mutation

   Inputs:
      ctx - context variable
      val - the mutation value to use for Real mutation
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetMutationRealVal(ctx,50.0);
      
****************************************************************************U*/
void PGASetMutationRealVal( PGAContext *ctx, double val)
{
    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetMutationRealVal", "Entered", 
                   PGA_VOID, NULL );
    
    if (val < 0.0) 
        PGAError ( ctx,
                  "PGASetMutationRealVal: Invalid value of val:",
                   PGA_FATAL, PGA_DOUBLE, (void *) &val);
    else
        ctx->ga.MutateRealVal = val;

    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetMutationRealVal", "Exit", 
                   PGA_VOID, NULL );

    return;
}

/*U****************************************************************************
   PGASetMutationIntegerVal - Set multiplier to mutate Integer strings with.
   The use of this value depends on the type of mutation being used.  See the
   user guide for more details.  The default value is 1.

   Category: Mutation

   Inputs:
      ctx - context variable
      val - the mutation value to use for Integer mutation
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetMutationIntegerVal(ctx,5);
      
****************************************************************************U*/
void PGASetMutationIntegerVal( PGAContext *ctx, int val)
{
    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetMutationIntegerVal",
                   "Entered", PGA_VOID, NULL );
    
    if (val < 0.0) 
        PGAError ( ctx,
                  "PGASetMutationIntegerVal: Invalid value of val:",
                   PGA_FATAL, PGA_DOUBLE, (void *) &val);
    else
        ctx->ga.MutateIntegerVal = val;

    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetMutationIntegerVal", "Exit", 
                   PGA_VOID, NULL );

    return;
}

/*U****************************************************************************
   PGASetNoDuplicates - A boolean flag to indicate if duplicate strings are
   allowed in the population. The default is to allow duplicate strings
  
   Category: Generation

   Inputs:
      ctx  - context variable
      flag - PGATRUE (default) or PGAFALSE
      
   Outputs:
      None

   Example:
      To not allow duplicate strings use
      
      PGAContext *ctx;
      :
      PGASetNoDuplicates(ctx,PGATRUE);
      
****************************************************************************U*/
void PGASetNoDuplicates( PGAContext *ctx, int no_dup)
{
    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetNoDuplicates", "Entered", 
                   PGA_VOID, NULL );
    
    switch (no_dup) {
        case PGATRUE:
        case PGAFALSE:
            ctx->ga.NoDuplicates = no_dup;
            break;
        default:
            PGAError ( ctx, "PGASetNoDuplicates: Invalid value of no_dup:",
                       PGA_FATAL, PGA_INT, (void *) &no_dup);
            break;
    }

    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetNoDuplicates", "Exit", 
                   PGA_VOID, NULL );
    return;    
}

/*U****************************************************************************
   PGASetMutationProb - Specifies the probability that a given gene will
   be mutated.  May interact with PGASetMutationType.  The default is the
   reciprocal of the string length

   Category: Mutation

   Inputs:
      ctx - context variable
      p   - the mutation probability
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetMutationProb(ctx,0.001);
      
****************************************************************************U*/
void PGASetMutationProb(PGAContext *ctx, double mutation_prob)
{
    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetMutationProb", "Entered", 
                   PGA_VOID, NULL );
    
    if ((mutation_prob < 0.0) || (mutation_prob > 1.0))
        PGAError ( ctx,
                  "PGASetMutationProb: Invalid value of mutation_prob:",
                   PGA_FATAL, PGA_DOUBLE, (void *) &mutation_prob);
    else
	 switch (ctx->ga.MutationType)
	 {
	 case PGA_MUTATION_FIXED:
	 case PGA_MUTATION_UNIFORM:
	 case PGA_MUTATION_GAUSSIAN:
	 case PGA_UNINITIALIZED_INT:
	      ctx->ga.MutationProb = mutation_prob;
	      break;
	 case PGA_MUTATION_STRINGLEN:
	 case PGA_MUTATION_HAMMING:
	      PGAError(ctx, "PGASetMutationProb: Cannot set mutation_prob:",
		       PGA_FATAL, PGA_DOUBLE, (void *) &mutation_prob);
	      break;
	 }

    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetMutationProb", "Exit", 
                   PGA_VOID, NULL );

    return;
}

/*U****************************************************************************
   PGASetPopReplacement - Choose method of sorting strings to copy from old
   population to new population

   Category: Generation

   PGASetSelectType - specify the type of selection to use. Valid choices
   are PGA_POPREPL_BEST, PGA_POPREPL_RANDOM_NOREP, or PGA_POPREPL_RANDOM_REP
   for copying the best strings, or  random string, with or without
   replacement, respectively, from the old population into the new one
   (the rest of the new population will be created by recombination).
   The default is PGA_POPREPL_BEST.

   Inputs:
      ctx         - context variable
      pop_replace - symbolic constant to specify the population replacement
                    strategy
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetPopReplacement(ctx, PGA_POPREPL_RANDOM_NOREP);
      
****************************************************************************U*/
void PGASetPopReplacement( PGAContext *ctx, int pop_replace)
{
    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetPopReplacement", "Entered", 
                   PGA_VOID, NULL );
    
    switch (pop_replace) {
    case PGA_POPREPL_BEST:
    case PGA_POPREPL_RANDOM_NOREP:
    case PGA_POPREPL_RANDOM_REP:
        ctx->ga.PopReplace = pop_replace;
	break;
    default:
        PGAError ( ctx,
                  "PGASetPopReplacement: Invalid value of pop_replace:",
                   PGA_FATAL, PGA_INT, (void *) &pop_replace);
	break;
    }
    
    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetPopReplacement", "Exit", 
                   PGA_VOID, NULL );
    return;    
}

/*U****************************************************************************
   PGASetPrintFreq - Specifies the frequency with which genetic algorithm
   statistics are reported.  The default is every 10 GA iterations.

   Category: Reporting

   Inputs:
      ctx        - context variable
      print_freq - the genetic algorithm population size to use
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetPrintFreq(ctx,1);
      
****************************************************************************U*/
void PGASetPrintFreq( PGAContext *ctx, int print_freq)
{
    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetPrintFreq", "Entered", 
                   PGA_VOID, NULL );
    
    if (print_freq < 0)
        PGAError ( ctx,
                  "PGASetPrintFreq: Invalid value of print_freq:",
                   PGA_FATAL,
                   PGA_INT,
		  (void *) &print_freq);
    else
        ctx->rep.PrintFreq = print_freq;
    
    PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetPrintFreq", "Exit", 
                   PGA_VOID, NULL );
    return;
}

/*U****************************************************************************
   PGASetRandomInit - A boolean flag to indicate whether to randomly
   initialize strings.  The deafult is random initialization.
  
   Category: Initialization

   Inputs:
      ctx  - context variable
      flag - PGATRUE (default) or PGAFALSE
      
   Outputs:
      None

   Example:
      To set all strings to zero use
      
      PGAContext *ctx;
      :
      PGASetRandomInit(ctx,PGAFALSE);
      
****************************************************************************U*/
void PGASetRandomInit(PGAContext *ctx, int RandomBoolean)
{
     PGADebugPrint(ctx, PGADEBUG_ENTERED, "PGASetRandomInit", "Entered",
		   PGA_VOID, NULL);

     switch (RandomBoolean)
     {
     case PGATRUE:
     case PGAFALSE:
	  ctx->init.RandomInit = RandomBoolean;
	  break;
     default:
	  PGAError(ctx, "PGASetRandomInit: Invalid value of RandomBoolean:",
		   PGA_FATAL, PGA_INT, (void *) &RandomBoolean);
	  break;
     }
     PGADebugPrint(ctx, PGADEBUG_EXIT, "PGASetRandomInit", "Exit",
		   PGA_VOID, NULL);
}

/*U****************************************************************************
   PGASetDebugLevel - set a debug level to PGATRUE.  Only valid if PGAPack
   was compiled to include debugging calls.  See the user guide for details.
  
   Category: Debugging

   Inputs:
      ctx   - context variable
      level - the debug level to set to PGATRUE.
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetDebugLevel(ctx, 70)
      
****************************************************************************U*/
void PGASetDebugLevel(PGAContext *ctx, int level)
{
     ctx->debug.PGADebugFlags[level] = PGATRUE;
}

/*U****************************************************************************
   PGASetPrintOptions - set flags to indicate what GA statistics should be
   printed whenever output is printed.  May be called more than once to
   specify different report options.  Valid choices are PGA_OFFLINE,
   PGA_ONLINE, PGA_WORST, PGA_HAMMING, and PGA_STRING to specify offline
   analysis, online analysis, the worst string in the population, the
   Hamming distance of the population, and the actual allel values of the
   best string.  The best string is always printed.

   Category: Reporting

   Inputs:
      ctx    - context variable
      option - symbolic constant to specify a print option
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetPrintOptions(ctx, PGA_WORST);
      
****************************************************************************U*/
void PGASetPrintOptions (PGAContext *ctx, int option)
{
     switch (option) 
     {
     case PGA_OFFLINE :
     case PGA_ONLINE :
     case PGA_WORST :
     case PGA_HAMMING :
     case PGA_STRING :
	  ctx->rep.PrintOptions |= option;
	  break;
     default :
	  PGAError (ctx, "PGASetPrintOption: Invalid value of option:",
		    PGA_FATAL, PGA_INT, (void *) &option);
	  break;
     }
}


/*U****************************************************************************
   PGASetBinaryInitProb - specify the probability of initializing a bit to
   one in initialization when a binary string is used as the data type.
   The default value is 0.5.

   Category: Initialization

   Inputs:
      ctx - context variable
      p   - the binary initialization probability
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetBinaryInitProb(ctx,0.01);
      
****************************************************************************U*/
void PGASetBinaryInitProb ( PGAContext *ctx, double probability )
{
    PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetBinaryInitProb", "Entered", 
                   PGA_VOID, NULL );

    if ( (probability <= 1.0) && (probability >= 0.0) )
      ctx->init.BinaryProbability = probability;
    else
      PGAError( ctx, "PGASetBinaryInitProb: Invalid value of probability:",
                PGA_FATAL, PGA_INT, (void *) &probability );
    return;
}


/*U****************************************************************************
   PGASetRandomSeed - set a seed for the random number generator.  The
   default is to use a random seed.  Specifying a seed exlicitly allows
   for reproducibility of runs

   Category: Random

   Inputs:
      ctx  - context variable
      seed - seed  for the random number generator
      
   Outputs:
      None

   Example:
      PGAContext *ctx;
      :
      PGASetRandomSeed(ctx,1);
      
****************************************************************************U*/
void PGASetRandomSeed(PGAContext *ctx, int seed)
{
     PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetRandomSeed", "Entered", 
                   PGA_VOID, NULL );
    
     if (ctx->sys.SetUpCalled)
	  PGAError(ctx, "PGASetRandomSeed: Function must be called BEFORE "
		   "call to PGASetUp", PGA_FATAL, PGA_VOID, NULL);
     else if ( seed < 1 )
	  PGAError ( ctx, "PGASetRandomSeed: Invalid value of seed:",
		    PGA_FATAL, PGA_INT, (void *) &seed);
     else
	  ctx->init.RandomSeed = seed;

     PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetRandomSeed", "Exit", 
                   PGA_VOID, NULL );
     return;
}

/*U****************************************************************************
   PGASetUserFunction - specifies the name of a user-written function
   to call to provide a specific GA capability (e.g., crossover,
   mutation, etc.).  This function MUST be used when using a nonnative
   datatype and must be called once for each of
   PGA_USERFUNCTION_CREATESTRING, PGA_USERFUNCTION_MUTATION,
   PGA_USERFUNCTION_CROSSOVER, PGA_USERFUNCTION_WRITESTRING,
   PGA_USERFUNCTION_COPYSTRING, PGA_USERFUNCTION_DUPLICATE,
   PGA_USERFUNCTION_RANDOMIZE to specify string creation, mutation,
   crossover, writing, copying, duplicating, and random initializing,
   respectively.  It MAY be called when using a native datatype to
   replace the built-in functions PGAPack has for that datatype (For
   example, if the Integer data type is used for a traveling
   salesperson problem, the user may want to provide their own custom
   cvrossover operator).  See the user guide and the examples in
   ./examples/c directory for more details.

   Category: Generation

   Inputs:
      ctx - context variable
      constant - symbolic constant .......
      f   - name of the function to use
      
   Outputs:
      None

   Example:
      void MyRandomize(PGAContext *, void *);
      PGAContext *ctx;
      :
      PGASetUserRandomize(ctx, PGA_USERFUNCTION_RANDOMIZE, MyRandomize);

****************************************************************************U*/
void PGASetUserFunction(PGAContext *ctx, int constant, void *f)
{
     PGADebugPrint( ctx, PGADEBUG_ENTERED, "PGASetUserFunction", "Entered",
		   PGA_VOID, NULL );
     if (f == NULL)
	  PGAError ( ctx, "PGASetUserFunction: Invalid function", PGA_FATAL,
		    PGA_VOID, NULL);
     else
	  switch (constant)
	  {
	  case PGA_USERFUNCTION_CREATESTRING:
		  ctx->ops.CreateString = (void (*)(PGAContext *, int, int,
						    int))f;
	       break;
	  case PGA_USERFUNCTION_MUTATION:
	       ctx->ops.Mutation = (int (*)(PGAContext *, int, int, double))f;
	       break;
	  case PGA_USERFUNCTION_CROSSOVER:
	       ctx->ops.Crossover = (void (*)(PGAContext *, int, int, int, int,
					      int, int))f;
	       break;
	  case PGA_USERFUNCTION_WRITESTRING:
	       ctx->ops.WriteString = (void (*)(PGAContext *, FILE *, int,
						int))f;
	       break;
	  case PGA_USERFUNCTION_COPYSTRING:
	       ctx->ops.CopyString = (void (*)(PGAContext *, int, int, int,
					       int))f;
	       break;
	  case PGA_USERFUNCTION_DUPLICATE:
	       ctx->ops.Duplicate = (int (*)(PGAContext *, int, int, int,
					     int))f;
	       break;
	  case PGA_USERFUNCTION_RANDOMIZE:
	       ctx->ops.Randomize = (void (*)(PGAContext *, int, int))f;
	       break;
	  default:
	       PGAError(ctx, "PGASetUserFunc: Invalid constant:", PGA_FATAL,
			PGA_INT, (void *) &constant);
	       break;
	  }

     PGADebugPrint( ctx, PGADEBUG_EXIT, "PGASetUserFunction", "Exit", 
                   PGA_VOID, NULL );
}
