www.pudn.com > dgpc.rar > gpkernel.c


/*======================================================================+
| PGPC: Parallel Genetic Programming in C                               |
| (c) 1995 Genetic Algorithm Technology Corp. all rights reserved       |
|   written by David Andre                                              |
+======================================================================*/
/*======================================================================+
| FILE: gpkernel.c                                                      |
| DESCRIPTION: Is the main GP kernel.  Runs on the meshnode breeder     |
|              process, and is the location of most major functions.    |
|                                                                       |
| REVISIONS:                                                            |
| Jan 24, 1995:  Works as of today, no known bugs.                      |
| Jan 26, 1995:  Added N Plus 2 Repro functionality                     |
| Feb 23, 1995:  Changed crossoverop to call choose point..(2-all) for  |
|                 choosing point in female parent                       |
| Mar 14, 1995:  Adding function-only crossover,                        |
| Mar 14, 1995:  Adding constrained syntactic generation                |
| Mar 17, 1995:  UNI-KERNEL VERSION STARTS HERE!                        |
+======================================================================*/


#include 
#include 

#ifdef __BORLANDC__
#include 
#include 
#include 
#else
#ifdef _ICC
#include 
#include 
#include 
#include 
#endif
#endif

#include 
#include 
#include 
#include "gp.h"
#ifdef _ICC
#include "mncommon.h"
#include "mnproto.h"
#include "gpi.h"
#else
#include "gpi_stub.h"
#include "pentstub.h"
#endif

#include "proto.h"
#include "newops.h"
#include 
#define PRINT_CROSSOVER_INDS OFF

/*----------------------------------------------------------------------*/
/*                               GLOBALS                                */
/*  I think that these only need to be globals on the meshnode          */
/*  processes.                                                          */
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/

Population gpop;
static char g_str[256];
int g_male_selection_method;

/*int g_index_ptr;*/


int gpstatGetRunNum()/*;*/ /*funcdef*/
{
    return(gpop.pop_startup_info.run_num);
}

float gpstatGetBestFitness()/*;*/ /*funcdef*/
{
    return(gpop.best_fitness);
}

int gpstatGetBestSoFarHits()/*;*/ /*funcdef*/
{
    return(gpop.best_so_far.hits);
}

int gpstatGetBestIndex()/*;*/ /*funcdef*/
{
    return(gpop.best_dude_index);
}

Individual * gpstatGetBestDude()/*;*/ /*funcdef*/
{
    return(&(gpop.best_so_far));
}

Population * gpinitGetPopptr()/*;*/ /*funcdef*/
{
    return(&gpop);
}

StartupInfo * gpinitGetParamptr()/*;*/ /*funcdef*/
{
    return(&(gpop.pop_startup_info));
}
		
int FullCompare(Individual * ind1, Individual * ind2)
{
    int i,j,k;
    int len1,len2;

    if (ind1->current_number_of_adfs != ind2->current_number_of_adfs)
        return(0);

    for (i=0;irpbs[i].tree[0].jump;
        len2 = ind2->rpbs[i].tree[0].jump;
        if (len1 != len2)
            return(0);
        for (j=0;jrpbs[i].tree[j].opcode != ind2->rpbs[i].tree[j].opcode)
                return(0);
        }
    }
    for (i=0;icurrent_number_of_adfs;i++)
    {
        len1 = ind1->adfs[i].tree[0].jump;
        len2 = ind2->adfs[i].tree[0].jump;
        if (len1 != len2)
            return(0);
        for (j=0;jadfs[i].tree[j].opcode != ind2->adfs[i].tree[j].opcode)
                return(0);
        }
    }
    return(1);

}

int QuickCompare(CompInd * c1, CompInd * c2)
{/*Returns a 1 if the two are quickly the same*/
    int i;
    for (i=0;i<10;i++)
    {
        if (c1->code[i] != c2->code[i])
            return(0);
    }
    return(1);
}

void init_pop_check(Population * pop)
{
   Individual * pind1;
   Individual * pind2;
   int cind1,cind2;
   int i,j,k;
   int index,branch;
#ifndef _ICC
   pind1 = &(pop->parent1);
   pind2 = &(pop->parent2);

   CreateIndividual(pind1);
   CreateIndividual(pind2);
   for (cind1=0;cind1pop_startup_info.num_individuals;cind1++)
   {
      for (cind2=cind1+1;cind2 < pop->pop_startup_info.num_individuals;cind2++)
      {
        if (QuickCompare(&(pop->members[cind1]),&(pop->members[cind2])))
        {
            /*printf("f");*/
            UnCompressIndividual(&(pop->members[cind1]),pind1);
            UnCompressIndividual(&(pop->members[cind2]),pind2);
            if (FullCompare(pind1,pind2) && pind1->rpbs[0].tree[0].jump > 10)
            {

                printf("S");
                fprintf(pop->out_file,"\n\nPERROR:: TWO INDS ARE THE SAME!!!!!\n");
                fprintf(pop->out_file,"PERROR:: They are %d and %d\n",cind1,cind2);

                PrintIndividual(pind1,pop->out_file);
                PrintIndividual(pind2,pop->out_file);
                fprintf(pop->out_file,"PERROR:: END OF PERROR\n\n");
            }
        }
      }
   }
#endif
}


void gpinitPopCreation(Population * pop)/*;*/ /*funcdef*/
{

    int i;
    for (i=0;i RUN_END_CRITERION))
	 return(0);
else
	 return(1);
}

void gpreproReproducePopulation(int counter)/*;*/ /*funcdef*/
{
				ReproducePopulation((int)( counter <= LAST_EARLY_GEN),counter);
           /* PopCommTest(&gpop);   */
}

void PreparePopulationForExportStep()/*;*/ /*funcdef*/
{
int i;

    gpop.num_emigrants =0;
    for (i=0;i
            gpop.members[worst_index].s_fitness) worst_index = i;
    }

    return(best_index);
}

/* Formerly initial.c file */

/*For the moment, I assume that all RPBs can have all ADFs*/



void InitializeIndividual(Individual * ind)/*;*/    /*funcdef - dgpc - InitializeIndividual */
{
    int i,j;
	 int temp;
    temp=0;
    i=0;j=0;

        ind->s_fitness = (float) UNDEFINED;
	ind->hits		 = 0;
        ind->beauty              = 0;
	
	ind->current_number_of_adfs = NUM_INITIAL_ADFS;
	for (i=0;iadf_arity[i]=MIN_NUM_ADF_ARGS;
                #if (USE_MULTI_TYPED_ADFS)
                    ind->adf_type[i] = -1;
                #endif
        }
        for (j=0;jrpbs[j].function_vector[i] = gpop.function_assignment[j][i];	
                        temp = (int) ind->rpbs[j].function_vector[i];
                        #ifdef _ICC
                        if (temp > MAX_NUM_ARGS || temp < -1)
                            __asm{seterr;};
                        #endif
                }
	}
	for (j=0;jadfs[j].function_vector[i] =   gpop.function_assignment[NUM_RPBS+j][i];	
                        temp = (int) ind->adfs[j].function_vector[i];
                        #ifdef _ICC
                        if (temp > MAX_NUM_ARGS || temp < -1)
                            __asm{seterr;};
                        #endif
                }
	}
    for (i=0;icode[i].opcode = -1;
        ind->code[i].jump   = -1;
    }

}


void InitializePopulation()/*;*/     /*funcdef - dgpc - InitializePopulation */
{
	int i,codep,bsize,temp;

        temp=0;
        for (i=0;irpbs[j]);
                    else
                        br = &(indtemp->adfs[j-NUM_RPBS]);
                    #ifdef _ICC
                    if (br == NULL)
                        __asm{seterr;};
                    #endif

                     for (k=0;kfunction_vector[k]) <  -1) ||
                            ((br->function_vector[k]) >  MAX_NUM_ARGS))
                        {
                            #ifdef _ICC
                                __asm{seterr;};
                            #else
                                fprintf(stderr,"Function vector is hosed in create_pop ");
                                fprintf(stderr,"branch# %d, function# %d, supposed arity %d\n",
                                            j,k,br->function_vector[k]);
                            #endif
                        }
                     }

    			if ((gpop.pop_startup_info.growth_method) == FULL)
				{
					size = max_new_tree_depth;
					grow = 1;
				}
				else if ((gpop.pop_startup_info.growth_method) == GROWTH)
				{
					size = max_new_tree_depth;
					grow = 0;
				}
				else
				{		/*RAMPED*/
                                size = (min_depth + (RandomInt(1+max_new_tree_depth-min_depth)));
                                /*size= (min_depth +   (i % (max_new_tree_depth - min_depth)));*/
					/*if (max_new_tree_depth != min_depth)
		 				if (!(i % (max_new_tree_depth - min_depth)))
		    					fcycle = (!fcycle);*/
					grow = RandomInt(2);  /*(fcycle);*/
				}
				if (j < NUM_RPBS)
                                {
                            #if (USE_USER_GENERATION_RPBS)
                                    UserCreateRandomTree(&(indtemp->rpbs[j]),
  								0, size, 1, grow,&gpop);
                                /*
                                SetConstraints(&gpop);
      				temp2 = CreateRandomTree(&(indtemp->rpbs[j]),
  								0, size, 1, grow,ROOT);
                                */
                            #else
                             #if (USE_CONSTRAINED_STRUCTURE)
                                temp2 = CreateRandomCSSTree(&(indtemp->rpbs[j]),0,size,1,grow);
                             #else
      				temp2 = CreateRandomTree(&(indtemp->rpbs[j]),
  								0, size, 1, grow);
                             #endif
                            #endif
                                }
				else
                                {
                            #if (USE_USER_GENERATION_ADFS)
					temp2 = 	
					UserCreateRandomTree((&(indtemp->adfs[(j-NUM_RPBS)])),
								0, size, 1, grow,&gpop);
                            #else
                             #if (USE_CONSTRAINED_STRUCTURE)
                                temp2 = CreateRandomCSSTree(&(indtemp->adfs[(j-NUM_RPBS)]),
                                                    0,size,1,grow);
                             #else
					temp2 = 	
/*					CreateRandomTree((&(indtemp->adfs[(j-NUM_RPBS)])),
								0, size, 1, grow);     */
					CreateRandomTree((&(indtemp->adfs[(j-NUM_RPBS)])),
								0, size, 1, grow);
                             #endif
                            #endif
                                }
		}
        indtemp->s_fitness = (float) UNDEFINED;
        #if (PRINT_INITIAL_POPULATION)
/*        #ifndef _ICC*/
        PrintIndividual(indtemp,gpop.out_file);
/*        #endif*/
        #endif
        CompressIndividual(indtemp, &(gpop.members[i]));
    }
    /* replace the first members of population with those to be read
       from a file, if filename is not null
  */

    	if ((gpop.pop_startup_info.num_primed_individuals) > 0)
    	{
           /* CopyIndividual(&(gpop.pop_startup_info.primed_individual),&(gpop.members[0]));        */
           CompressIndividual(&(gpop.pop_startup_info.primed_individual),&(gpop.members[0]));
  	}

        temp2=temp2;
}


/* Formerly individ.c file */


int FindGoodTree(int choice_type)/*;*/   /*funcdef - dgpc - FindGoodTree */
{
    int i;
    int tournament_indices[GOOD_TOURNAMENT_SIZE];
    int best_index;
    for (i=0;i
            gpop.members[worst_index].s_fitness)
    		worst_index = tournament_indices[i];
    return(worst_index);
}

/* Formerly repro.c file */
/*
Branch * GetRightBranch(Individual * dude, int bnum)
{
	if (bnum < NUM_RPBS)
		return( &(dude->rpbs[bnum]) );
	else
		return( &(dude->adfs[bnum - NUM_RPBS]) );
}
*/
int ChoosePoint(Branch * br,        /*funcdef - dgpc - ChoosePoint*/
                int CurTreeSize,           /*funcdef - dgpc - ChoosePoint*/
                int choice)/*;*/                /*funcdef - dgpc - ChoosePoint*/
{
/*
 if choice == 0, must choose a point with 0 arity
 if choice == 1, must choose a point with non-zero arity
 if choice == 2, can choose any point
*/
	int rnum;
	int done =0;
	int counter =0;

	while (!done)
	{

		counter++;
		if (CurTreeSize < 2)
			 choice = 2;
		rnum = RandomInt(CurTreeSize);
              /*  if (rnum > 0 && _function_is_constant(br->tree[rnum-1].opcode))
                    done=0;
                else  */
		    switch (choice) {
			case 0:	if (_function_arity(br->tree[rnum].opcode) == 0)
						done = 1;
					break;
			case 1:	if (_function_arity(br->tree[rnum].opcode) != 0)
						done =1;
					break;
			case 2:	done =1;
					break;
			default:	done=1;
					break;
			}
	}
	return(rnum);
}

int ValidSubtreeGivenFVector(Branch *br, int index, int * fvector)/*;*/ /*funcdef -- gpkernel.c */
{
int correct_flag = 1;
int temp;

temp = doValidSubtreeGivenFVector(br,index,fvector,&correct_flag);
    if (correct_flag)
        return(1);
    else
        return(0);
}

int doValidSubtreeGivenFVector(Branch *br,   /*funcdef - dgpc - doValidSubtreeGivenFVector*/
                         int index,           /*funcdef - dgpc - doValidSubtreeGivenFVector*/
                         int * fvector,
                         int * pcorrect)/*;*/  /*funcdef - dgpc - doValidSubtreeGivenFVector*/
{
	int i,num;
        int tvector[TOTAL_NUMBER_OF_FUNCTIONS];
	if (br->tree[index].opcode ==  EMPTY)
	{
	        sprintf(g_str,"Error, an unused node is being accessed at %d\n in doValidSubtreeGivenFVector\n",
                                                                      index);
                gpi_SendError(g_str);
		exit(1);
	}
	if (index > br->num_nodes)
	{	
		sprintf(g_str,
			"Oops!! Ran past the end of a tree, in doValidSubtreeGivenFVector!!\n");
                gpi_SendError(g_str);
		exit(1);
	}
	else
	{
        /*
        BASE CASE   1:  This node doesn't fit -- set pcorrect to 0 and return (must check in previous calls)
        BASE CASE   2:	This node is a terminal -- return
        INDUCTION CASE: CopyFvector for each arg, call recursively, return
        */
		num = _fv_map(br->tree[index].opcode);
                if (fvector[num] < 0)
                {
                    *pcorrect = 0;
                    return(index);
                }
                if (_function_arity(num) == 0)
                    return(index);
                if (_function_is_constant(br->tree[index].opcode))
                    return(index);
		for (i=0;((i< _function_arity(num)) && (*pcorrect)); i++)
		{
                        CopyFVector(fvector,tvector);
                        #if (USE_CONSTRAINED_STRUCTURE)
                            ConstrainedSyntaxFilters(tvector, br, num, i, &gpop);
                        #endif

			index = doValidSubtreeGivenFVector(br,index+1,tvector,pcorrect);
		}
	}
	return(index);
}



int MakeFunctionVector(Branch *br,  /*funcdef - dgpc - MakeFunctionVector*/
                       int index,          /*funcdef - dgpc - MakeFunctionVector*/
                       int * fvector)/*;*/ /*funcdef - dgpc - MakeFunctionVector*/
/*Assumes that the fvector is filled initially with not flags (-1)*/
/*returns the node_index at the end of the subtree...*/
{
	int i;
	for (i=0;itree[index].opcode ==  EMPTY)
	{
	        sprintf(g_str,"Error, an unused node is being accessed at %d\n in doMakeFunctionVector\n",
                                                                      index);
                gpi_SendError(g_str);
		exit(1);
	}
	if (index > br->num_nodes)
	{	
		sprintf(g_str,
			"Oops!! Ran past the end of a tree, in FillSubtreeFunctionVector!!\n");
                gpi_SendError(g_str);
		exit(1);
	}
	else
	{
		num = _fv_map(br->tree[index].opcode);
		fvector[num] = _function_arity(num);
                if (_function_is_constant(br->tree[index].opcode))
                    return(index);
		for (i=0;i< _function_arity(num); i++)
		{
			index = doMakeFunctionVector(br,index+1,fvector);
		}
	}
	return(index);
}


int CheckFVectorFit(Branch * br, /*funcdef - dgpc - CheckFVectorFit */
                      int * fvector)/*;*/ /*funcdef - dgpc - CheckFVectorFit */
{
	int fit;
	int i;
	fit =1;
	for (i=0;i=0) && (br->function_vector[i] !=   fvector[i]))
			fit=0;
	}
	return(fit);
}

int FVectorSubsumeP(int * fvector_large, int * fvector_small)
{
	int fit;
	int i=0;;
	fit =1;
	for (i=0;i=0) && (fvector_large[i] !=   fvector_small[i]))
			fit=0;
	}
	return(fit);

}

void CullPopulation(int * fvector)/*;*/ /*funcdef - dgpc - CullPopulation */
{
	int i,j;
	int match;
	Individual * ind;

        ind = &(gpop.tempind);
	gpop.number_in_culled_pop =0;
	for (i=0;i<(gpop.pop_startup_info.num_individuals);i++)
	{
                UnCompressIndividual(&(gpop.members[i]),ind);
                /*ind = &(gpop.members[i]);*/
		match=0;
		for (j=0;j<(NUM_RPBS + ind->current_number_of_adfs);j++)
			if (CheckFVectorFit(GetRightBranch(ind,j),fvector))
				match=1;
		if (match)
			gpop.culled_population[gpop.number_in_culled_pop++]=i;
	}	
	if (gpop.number_in_culled_pop <=0)
	{
		sprintf(g_str,"OOPS!.  No Individuals in the culled population!!!\n");
                gpi_SendError(g_str);
		exit(1);
	}
}	

int RandCullPopulation(int * fvector)/*;*/  /*funcdef - dgpc - RandCullPopulation */
{
	int i,j;
	int match,counter;
	Individual * ind;
        gpop.number_in_culled_pop =0;
        counter = 0;

        ind = &(gpop.tempind);
        while (gpop.number_in_culled_pop < GOOD_TOURNAMENT_SIZE &&
               counter < SEARCH_LIMIT_FOR_CROSSOVER)
        {

            counter++;
            match=0;
            i = RandomInt((gpop.pop_startup_info.num_individuals));
            UnCompressIndividual(&(gpop.members[i]),ind);
            /*ind = &(gpop.members[i]);*/
            for (j=0;j<(NUM_RPBS + ind->current_number_of_adfs);j++)
            {
			if (CheckFVectorFit(GetRightBranch(ind,j),fvector))
                        {
				match=1;
                        }
            }
	    if (match)
		gpop.culled_population[gpop.number_in_culled_pop++]=i;
        }
        if (counter >= SEARCH_LIMIT_FOR_CROSSOVER)
            return(0);
        else
            return(1);
}

int ChooseWRandomBranch(Individual * ind)
{
    int i,temp;
    int weight_list,sum;
    Branch * br;
        sum=0;
	 for (i=0;icurrent_number_of_adfs;i++)
	 {
		  br = GetRightBranch(ind,i);
		  sum += br->tree[0].jump;
	 }
	 temp = RandomInt(sum);
	 i=0;
	 sum=0;
	 while(i < NUM_RPBS+ind->current_number_of_adfs)
    {
        br = GetRightBranch(ind,i);
        sum += br->tree[0].jump;
        if (temp < sum)
        {
            return(i);
        }
        i++;
    }
    gpi_SendError("Error in choose weighted by points random branch\n");
    return(0);
}
                                		
int ChooseRandomBranch(int current_num_adfs)/*;*/ /*funcdef*/
{
    int i,temp;
    int weight_list,sum;
    sum=0;
    for (i=0;icurrent_number_of_adfs);i++)
			if (CheckFVectorFit(GetRightBranch(parent,i),fvector))
                        {
				fit_list[num_fit++] = i;
                		br = GetRightBranch(parent,i);
		                sum += br->tree[0].jump;
                        }
	if (num_fit==0)
	{
		sprintf(g_str, "Crossover female chosen incorrectly, exiting\n");
                gpi_SendError(g_str);
		exit(1);
	}
        temp=RandomInt(sum);
        sum=0;
        i=0;
        while (itree[0].jump;
            if (temp < sum)
    	       return(fit_list[i]);
            i++;
		  }
	return(-1);
}



int FindGoodBranch(Individual * parent,   /*funcdef - dgpc - FindGoodBranch*/
                     int *fvector)/*;*/     /*funcdef - dgpc - FindGoodBranch*/
{
	int i,temp;
	int fit_list[NUM_RPBS+MAX_NUM_ADFS];
	int num_fit=0;
        int sum;
        sum=0;        	
	for (i=0;i<(NUM_RPBS+parent->current_number_of_adfs);i++)
			if (CheckFVectorFit(GetRightBranch(parent,i),fvector))
								{
				fit_list[num_fit++] = i;
										  sum+= gpop.brweight[i];
								}
	if (num_fit==0)
	{
		sprintf(g_str, "Crossover female chosen incorrectly, exiting\n");
					 gpi_SendError(g_str);
		exit(1);
	}
		  temp=RandomInt(sum);
		  sum=0;
		  i=0;
		  while (ipoint1 = crosspt1;
#if (POINT_TYPING   )
	cr1_size = MakeFunctionVector(male_parent_branch, crosspt1,
                                            cross_frag_fvector)- crosspt1 +1;
        if (!RandCullPopulation(cross_frag_fvector))
	   CullPopulation(cross_frag_fvector);

        #if (SEDUCTION == ON)
    	   parent2 = FindTreeFromCulledPop(!g_male_selection_method);
        #else
    	   parent2 = FindTreeFromCulledPop(0);
        #endif
#else
	cr1_size = TraverseSubtree(male_parent_branch,crosspt1) -
                                                            crosspt1 +1;
        #if (SEDUCTION == ON)
            parent2 = FindGoodTree(!g_male_selection_method);
        #else
            parent2 = FindGoodTree(0);
        #endif
#endif
        repro_op->parent2 = parent2;
        gpop.members[parent2].usage++;
        UnCompressIndividual(&(gpop.members[parent2]),&(gpop.parent2));	
	
#if (POINT_TYPING)
  #ifdef SIZE_WEIGHTED_CROSSOVER_BRANCH_SELECTION
	 #if (SIZE_WEIGHTED_CROSSOVER_BRANCH_SELECTION)
	female_bnum = FindGoodSWBranch(&(gpop.parent2), cross_frag_fvector);
	 #else
	female_bnum = FindGoodBranch(&(gpop.parent2), cross_frag_fvector);
	 #endif
  #else
	female_bnum = FindGoodBranch(&(gpop.parent2), cross_frag_fvector);
  #endif
#else
        female_bnum = bnum;
#endif
        repro_op->brnum2 = female_bnum;
        repro_op->next_for_parent2 = gpop.members[parent2].op_list;
        gpop.members[parent2].op_list = repro_op;
}


#define DEBUG_GPAP OFF
void gpap(Branch *br,int pt,ParentInfo * pinfo)
{
    int i=0,j=0,k=0,temp=0;
    int unclaimed_children=0;

    pinfo->num_parents=0;
    unclaimed_children=0;
    #if (DEBUG_GPAP)
    fprintf(stdout,"\nIN gpap. pt is %d\n",pt);
    fflush(stdout);
    #endif
    for (i= pt-1; i>=0; i--)
    {
        if ((temp = ((_function_arity(br->tree[i].opcode) - unclaimed_children))) > 0)
        {/*IS PARENT*/
            pinfo->parents[pinfo->num_parents] = i;
            pinfo->branches[pinfo->num_parents++] = unclaimed_children;
            #if (DEBUG_GPAP)
            fprintf(stdout,"arity %d unc %d parent %d, arg %d\n",_function_arity(br->tree[i].opcode),
                                 unclaimed_children,i,unclaimed_children);
            #endif
            unclaimed_children =0; /*DA -- CHANGE  10-17-95*/
        }
        else
        {/*IS NOT PARENT*/
            unclaimed_children = 1 + (unclaimed_children - _function_arity(br->tree[i].opcode));
        }
    }
}


void DoCrossoverOp(int level,                       /*funcdef*/
                   Individual * child,              /*funcdef*/
                   ReproOpInfo * repro_op,          /*funcdef*/
                   Individual * parent)/*;*/        /*funcdef*/
{
	int p2_size =0, cr1_size=0, cr2_size=0,temp=0;
	int crosspt1=0, crosspt2=0;
	int done=0;
        int i=0,j=0,k=0;
#if (USE_CONSTRAINED_STRUCTURE)
	int cross_frag_fvector[TOTAL_NUMBER_OF_FUNCTIONS];
	int fvector[TOTAL_NUMBER_OF_FUNCTIONS];
        ParentInfo  pinfo;
#endif
	Branch * child_branch, *male_parent_branch, *female_parent_branch;

	int parent2=0,female_bnum=0;
        int ct=0;
#if (USE_CONSTRAINED_STRUCTURE)
/*        printf("TEST\n");*/
        for (i=0;ibrnum1);
        crosspt1 = repro_op->point1;
        #if (PRINT_CROSSOVER_INDS)
        fprintf(stdout,"\nIn Crossover, Male Parent: BrNum:%d,pt%d\n",repro_op->brnum1,crosspt1);
        PrintIndividual(parent,stdout);
        #endif
        cr1_size = TraverseSubtree(male_parent_branch,crosspt1) - crosspt1+1;
        parent2 = repro_op->parent2;
        UnCompressIndividual(&(gpop.members[parent2]),&(gpop.parent2));	
	CopyIndividual(&(gpop.parent2),child);
        female_bnum = repro_op->brnum2;
        #if (PRINT_CROSSOVER_INDS)
        fprintf(stdout,"In Crossover, Female Parent: BrNum:%d\n",repro_op->brnum2);
        PrintIndividual(&(gpop.parent2),stdout);
        #endif

	female_parent_branch = GetRightBranch(&(gpop.parent2),female_bnum);
	child_branch = GetRightBranch(child,female_bnum);
	p2_size = TraverseSubtree(female_parent_branch,0) +1;

#if (USE_CONSTRAINED_STRUCTURE)
#if 0
	temp = MakeFunctionVector(male_parent_branch, crosspt1,                    /*This is un-needed now*/
                                            cross_frag_fvector)- crosspt1 +1;
#endif
#endif                		
	while (!done  && ct < MAX_ATTEMPTS)
	{

                ct++;
             #if (USE_NO_LEAF_CROSSOVER )
		crosspt2 = ChoosePoint(female_parent_branch, p2_size, level); /*IN GENERAL SHOULD BE level=2*/
             #else
		crosspt2 = ChoosePoint(female_parent_branch, p2_size, 2);
             #endif
		cr2_size = TraverseSubtree(female_parent_branch,crosspt2) -
                                                                   crosspt2 +1;
		if ( (p2_size - cr2_size + cr1_size) <= child_branch->num_nodes)
			done=1;
                if ((DepthOfPointInBranch(female_parent_branch,crosspt2) +
                    DepthOfBranchFromPoint(male_parent_branch,crosspt1)) >
                        MAX_DEPTH_FOR_TREE)
                        done =0;
            #if (USE_CONSTRAINED_STRUCTURE)
               if (done)
               {
/*                printf("TEST -- JUST BEFORE GPAP\n");*/
                gpap(female_parent_branch,crosspt2,&pinfo);
                CopyFVector(female_parent_branch->function_vector,fvector);
                ConstrainedSyntaxFilters(fvector,female_parent_branch,TOP_OF_TREE,0,&gpop);
                for (i=pinfo.num_parents-1;i>=0;i--)
                {
                    ConstrainedSyntaxFilters(fvector,female_parent_branch,female_parent_branch->tree[pinfo.parents[i]].opcode,
                                                                          pinfo.branches[i],&gpop);
                }
                /*Compare male_fvector with point fvector.  If no match, done=0*/
                /*int FVectorSubsumeP(int * fvector_large, int * fvector_small)*/
                /*if (!FVectorSubsumeP(fvector,cross_frag_fvector))*/  /*This is, as far as I can tell, completely bogus*/
                 if (!ValidSubtreeGivenFVector(male_parent_branch, crosspt1,fvector))
                    done=0;
               }
            #endif
	}
        if (done)
        {
/*           fprintf(stdout,"DONE!\n");*/
	   if (crosspt2 != 0)
		CopySubtree(female_parent_branch, 0, crosspt2 -1, child_branch, 0);
	   CopySubtree(male_parent_branch, crosspt1, crosspt1 + cr1_size -1, \
						child_branch, crosspt2);
           if ( (crosspt2 + cr2_size -1) < (p2_size -1))
		CopySubtree(female_parent_branch, crosspt2 + cr2_size,
					p2_size-1, child_branch, crosspt2+cr1_size);
           #if (PRINT_CROSSOVER_INDS)
           fprintf(stdout,"CHILD (female crosspt %d)\n",crosspt2);
           PrintIndividual(child,stdout);
           #endif
        }
        else
        {
           #if (PRINT_CROSSOVER_INDS)
            printf("Bailed on Crossover\n");
           #endif
            CopyIndividual(&(gpop.parent2),child);
        }

}

/* DoCrossover actually performs crossover, copying the crossed over portions into the new children.
 It chooses the points, and performs the operation.  The 'level' argument refers to whether leaves or
 nodes will be chosen.  If it is 0, leaves will be chosen.  If it is 1, nodes will be chosen.
*/

int DoCrossover(int level,              /*funcdef - dgpc - DoCrossover*/
                Individual * child,     /*funcdef - dgpc - DoCrossover*/
                Individual * parent,    /*funcdef - dgpc - DoCrossover*/
                int bnum)/*;*/          /*funcdef - dgpc - DoCrossover*/
{
	int p1_size, p2_size, cr1_size, cr2_size;
	int crosspt1, crosspt2;
	int done=0;
	int cross_frag_fvector[TOTAL_NUMBER_OF_FUNCTIONS];
	Branch * child_branch, *male_parent_branch, *female_parent_branch;

	int parent2,female_bnum;
        int ct=0;
	ct=ct;
	male_parent_branch = GetRightBranch(parent, bnum);


	p1_size = TraverseSubtree(male_parent_branch, 0) +1;
	crosspt1 = ChoosePoint(male_parent_branch, p1_size, level);

#if (POINT_TYPING   )
	cr1_size = MakeFunctionVector(male_parent_branch, crosspt1,
                                            cross_frag_fvector)- crosspt1 +1;
        if (!RandCullPopulation(cross_frag_fvector))
	   CullPopulation(cross_frag_fvector);
        #if (SEDUCTION == ON)
    	   parent2 = FindTreeFromCulledPop(!g_male_selection_method);
        #else
    	   parent2 = FindTreeFromCulledPop(0);
        #endif
#else
	cr1_size = TraverseSubtree(male_parent_branch,crosspt1) -
                                                            crosspt1 +1;
        #if (SEDUCTION == ON)
            parent2 = FindGoodTree(!g_male_selection_method);
        #else
            parent2 = FindGoodTree(0);
        #endif
#endif
        UnCompressIndividual(&(gpop.members[parent2]),&(gpop.parent2));	
	CopyIndividual(&(gpop.parent2),child);
	
#if (POINT_TYPING        )
#   ifdef SIZE_WEIGHTED_CROSSOVER_BRANCH_SELECTION
#     if (SIZE_WEIGHTED_CROSSOVER_BRANCH_SELECTION)
	female_bnum = FindGoodSWBranch(&(gpop.parent2), cross_frag_fvector);
#     else
	female_bnum = FindGoodBranch(&(gpop.parent2), cross_frag_fvector);
#     endif
#   else
	female_bnum = FindGoodBranch(&(gpop.parent2), cross_frag_fvector);
#   endif
#else
        female_bnum = bnum;
#endif
	female_parent_branch = GetRightBranch(&(gpop.parent2),female_bnum);
	child_branch = GetRightBranch(child,female_bnum);
	p2_size = TraverseSubtree(female_parent_branch,0) +1;
		
	while (!done  && ct < MAX_ATTEMPTS)
	{

                ct++;
		crosspt2 = ChoosePoint(female_parent_branch, p2_size, level);
		cr2_size = TraverseSubtree(female_parent_branch,crosspt2) -
                                                                   crosspt2 +1;
		if ( (p2_size - cr2_size + cr1_size) <= child_branch->num_nodes)
			done=1;
                if ((DepthOfPointInBranch(female_parent_branch,crosspt2) +
                    DepthOfBranchFromPoint(male_parent_branch,crosspt1)) >
                        MAX_DEPTH_FOR_TREE)
                        done =0;

	}
        if (done)
        {
	   if (crosspt2 != 0)
		CopySubtree(female_parent_branch, 0, crosspt2 -1, child_branch, 0);
	   CopySubtree(male_parent_branch, crosspt1, crosspt1 + cr1_size -1, \
						child_branch, crosspt2);
           if ( (crosspt2 + cr2_size -1) < (p2_size -1))
		CopySubtree(female_parent_branch, crosspt2 + cr2_size,
					p2_size-1, child_branch, crosspt2+cr1_size);
        }
        else
            CopyIndividual(&(gpop.parent2),child);
	return(parent2);
}

/*MUST STILL BE FIXED FOR WVA CODE*/
void DoMutation(Branch * parent, Branch * child)/*;*/ /*funcdef - dgpc - DoMutation*/
{
	Branch mbranch;
	int p_size;
	int inspt;
	int c_size;
	int n_size;
	int done=0;
	int i;
        #if (USE_CONSTRAINED_STRUCTURE)
            ParentInfo pinfo;
            int        fvector[TOTAL_NUMBER_OF_FUNCTIONS];
        #endif
	int ct=0;
        ct=ct;
	mbranch.tree = (Fnode *) calloc(6000, sizeof(Fnode));
	mbranch.branchnum = child->branchnum;
	mbranch.num_nodes = child->num_nodes;
	mbranch.ind = child->ind;
	for (i=0;ifunction_vector[i];
	
	 p_size = TraverseSubtree(parent, 0) +1;
	 inspt = ChoosePoint(parent, p_size, 2);
	c_size = TraverseSubtree(parent, inspt)  - inspt +1;
	while (!done && ct < MAX_ATTEMPTS)
	{

                ct++;
		if (parent->branchnum < NUM_RPBS)
                {
                   #if (USE_CONSTRAINED_STRUCTURE)
                    gpap(parent,inspt,&pinfo);
                    CopyFVector(parent->function_vector,fvector);
                    ConstrainedSyntaxFilters(fvector,parent,TOP_OF_TREE,0,&gpop);
                    for (i=pinfo.num_parents-1;i>=0;i--)
                    {
                        ConstrainedSyntaxFilters(fvector,parent,parent->tree[pinfo.parents[i]].opcode,
                                                                              pinfo.branches[i],&gpop);
                    }
                    n_size = doCreateRandomCSSTree(&mbranch,0,(gpop.pop_startup_info.max_depth_for_mutation),0,0,fvector);
                                        /*Okay -- going to have to calculate parents and apply filters to get new
                        correct function vector to pass in --(both for adfs and here)*/
                    #else
			n_size = CreateRandomTree(&mbranch,0, (gpop.pop_startup_info.max_depth_for_mutation), 0,0) ;
                    #endif
                }
		else
                {
                    #if (USE_CONSTRAINED_STRUCTURE)
                    gpap(parent,inspt,&pinfo);
                    CopyFVector(parent->function_vector,fvector);
                    ConstrainedSyntaxFilters(fvector,parent,TOP_OF_TREE,0,&gpop);
                    for (i=pinfo.num_parents-1;i>=0;i--)
                    {
                        ConstrainedSyntaxFilters(fvector,parent,parent->tree[pinfo.parents[i]].opcode,
                                                                              pinfo.branches[i],&gpop);
                    }
                    n_size = doCreateRandomCSSTree(&mbranch,0,(gpop.pop_startup_info.max_depth_for_mutation),0,0,fvector);
                    /*Okay -- going to have to calculate parents and apply filters to get new
                        correct function vector to pass in --(both for adfs and here)*/

                    #else
			n_size = CreateRandomTree(&mbranch,0, (gpop.pop_startup_info.max_depth_for_mutation), 0,0);
                    #endif
                }
		if (p_size + n_size - c_size < child->num_nodes)
			done =1;
                if ((DepthOfPointInBranch(parent,inspt) +
                    depth_of_branch(&mbranch)) >=  MAX_DEPTH_FOR_TREE)
                        done =0;
	}
        if (done)
        {
	   if (inspt != 0)
		CopySubtree(parent, 0, inspt -1, child, 0);     	
           CopySubtree(&mbranch, 0, n_size, child, inspt);
	   if ( (inspt + c_size -1) < (p_size -1))
		CopySubtree(parent, inspt + c_size, p_size-1, child, inspt + n_size);
                /*
            printf("done, and completed mutation.\n");
            printf("parent\n");
            PrintIndividual((parent->ind),stdout);
            printf("child\n");
            PrintIndividual((child->ind),stdout);
            */
        }
        else
        {
/*            CopyTree(parent,child);        */
            CopyIndividual(parent->ind, child->ind);
            /*
            printf("bailed due to too many attempts");
            */
        }
	free(mbranch.tree);		
}

/* ReproducePopulation replaces the current population with the next generation of
Individuals.  */

void ReproducePopulation(int early, int counter)/*;*/ /*funcdef - dgpc - ReproducePopulation*/
{
    int i;

    for (i=0;i<(gpop.pop_startup_info.num_individuals);i++)
    {
        gpop.members[i].usage =0;
        gpop.members[i].forward=NULL;
        gpop.members[i].backward=NULL;
        gpop.members[i].op_list = NULL;
        gpop.repro_op_list[i].repro_op_type = -1;
        gpop.repro_op_list[i].parent1 = -1;
        gpop.repro_op_list[i].parent2 = -1;
        gpop.repro_op_list[i].brnum1 = -1;
        gpop.repro_op_list[i].brnum2 = -1;
        gpop.repro_op_list[i].point1 = -1;
        gpop.repro_op_list[i].next_for_parent1 = NULL;
        gpop.repro_op_list[i].next_for_parent2 = NULL;
    }

    for (i=0;i<(gpop.pop_startup_info.num_individuals);i++)
    {
        ChooseOneReproduction( early, counter, i);
    }
    ExecuteOperations();
}



ReproOpInfo * GetUnDoneOp(CompInd * dude) /*;*/ /*funcdef*/
{
    ReproOpInfo * rtemp;
    rtemp = dude->op_list;
    while (rtemp != NULL)
    {
        if (rtemp->repro_op_type != OP_DONE)
            return(rtemp);
        else
        {
            if (&(gpop.members[rtemp->parent1]) == dude)
                rtemp = rtemp->next_for_parent1;
            else if (&(gpop.members[rtemp->parent2]) == dude)
                rtemp = rtemp->next_for_parent2;
            else
            {
                gpi_SendError("Oops, Error in getundone op, none matching dude\n");
            }
        }
    }
    gpi_SendError("Huge error in get undone op, no ops undone!\n");
    #ifdef _ICC
        __asm{seterr;};
	 #endif
	 exit(1);
    return(NULL);
}

CompInd * RemoveFromCindList(CompInd * dude, CompInd * list)/*;*/ /*funcdef*/
{
    if (dude->backward != NULL)
        dude->backward->forward = dude->forward;
    else
        list = dude->forward;
    if (dude->forward != NULL)
        dude->forward->backward = dude->backward;
    dude->backward = NULL;
    dude->forward = NULL;
    return(list);
}

CompInd * PlaceOnCindList(CompInd * dude, CompInd * list)/*;*/ /*funcdef*/
{
    dude->forward = list;
    dude->backward = NULL;
    if (list != NULL)
        list->backward = dude;
    list = dude;
    return(list);
}

void ExecuteOperations(void)/*;*/ /*funcdef*/
{
    int i;
    int from_list;
    Individual * indtemp;
    CompInd * free_dude;
    CompInd *tind;
    ReproOpInfo * op_todo;
    indtemp = &(gpop.tempind);
    gpop.free1 = &(gpop.childx1);
    gpop.free2 = &(gpop.childx2);
    gpop.free1->usage = 0;
    gpop.free2->usage = 0;
    CreateIndividual(indtemp);
    InitializeIndividual(indtemp);
    gpop.free_list = NULL;
    gpop.one_list = NULL;
    gpop.two_list = NULL;
    gpop.more_list = NULL;


     gpop.free_list =PlaceOnCindList(gpop.free1,gpop.free_list);
     gpop.free_list =PlaceOnCindList(gpop.free2,gpop.free_list);
     for (i=0;i 2)
                 gpop.more_list = PlaceOnCindList(&(gpop.members[i]),gpop.more_list);
     }
     for (i=0;iparent1,
                                             op_todo->parent2,
                                             op_todo->repro_op_type);
        */
        UpDateDude(op_todo->parent1,from_list);

        if (op_todo->repro_op_type == CROSSOVER_ON_LEAVES ||
            op_todo->repro_op_type == CROSSOVER_ON_NODES)
        {
            UpDateDude(op_todo->parent2,from_list);
        }
        op_todo->repro_op_type = OP_DONE;

         if (gpop.free_list == NULL)
         {
            gpi_SendError("Error, no free dudes\n");
            #ifdef _ICC
                __asm{seterr;};
            #else
                exit(1);
            #endif
         }
         free_dude = gpop.free_list;
         gpop.free_list = free_dude->forward;
         if (free_dude->forward != NULL)
            free_dude->forward->backward = NULL;
         free_dude->backward = NULL;
         free_dude->forward = NULL;
         free_dude->usage = -1;
/*         PrintIndividual(&(gpop.tempind),stdout);*/
         CompressIndividual(&(gpop.tempind),free_dude);
    }
    if (gpop.free1->usage == -1)
    {
/*        gpi_SendTrace("used free1\n");*/
         free_dude = gpop.free_list;
         if (free_dude == NULL)
            gpi_SendTrace("Error, no free guys\n");
         gpop.free_list = free_dude->forward;
         if (free_dude->forward != NULL)
            free_dude->forward->backward = NULL;
         free_dude->backward = NULL;
         free_dude->forward = NULL;
         free_dude->usage = -1;
         UnCompressIndividual(gpop.free1,&(gpop.tempind));
         CompressIndividual(&(gpop.tempind),free_dude);
    }
    if (gpop.free2->usage == -1)
    {
/*        gpi_SendTrace("used free2\n");*/
         free_dude = gpop.free_list;
         if (free_dude == NULL)
            gpi_SendTrace("Error, no free guys\n");
         gpop.free_list = free_dude->forward;
         if (free_dude->forward != NULL)
            free_dude->forward->backward = NULL;
         free_dude->backward = NULL;
         free_dude->forward = NULL;
         free_dude->usage = -1;
         UnCompressIndividual(gpop.free2,&(gpop.tempind));
         CompressIndividual(&(gpop.tempind),free_dude);
    }
}




void UpDateDude(int parent, int from_list)/*;*/ /*funcdef*/
{
    if (gpop.members[parent].usage == 1)
    {
        gpop.one_list = RemoveFromCindList(&(gpop.members[parent]),gpop.one_list);
        gpop.free_list = PlaceOnCindList(&(gpop.members[parent]),gpop.free_list);
    }
    else if (gpop.members[parent].usage == 2)
    {        gpop.two_list =RemoveFromCindList(&(gpop.members[parent]),gpop.two_list);
        gpop.one_list = PlaceOnCindList(&(gpop.members[parent]),gpop.one_list);
    }
    else if (gpop.members[parent].usage > 2)
    {
        gpop.more_list = RemoveFromCindList(&(gpop.members[parent]),gpop.more_list);
        if (gpop.members[parent].usage == 3)
            gpop.two_list = PlaceOnCindList(&(gpop.members[parent]),gpop.two_list);
        else
            gpop.more_list = PlaceOnCindList(&(gpop.members[parent]),gpop.more_list);
    }
    gpop.members[parent].usage--;

}

void DoReproductiveOp(ReproOpInfo * op_to_do, Individual *child,int child_num)/*;*/ /*funcdef*/
{
    int temp;
    UnCompressIndividual(&(gpop.members[op_to_do->parent1]),&(gpop.parent1));
    CopyIndividual( &(gpop.parent1), child);
    #if (REPRO_ERROR_CHECKING)
    if (ErrorInDude(child))
    {
        gpi_SendError("ERROR from copying in do repro op \n");
        exit(1);
    }
    #endif
    #if GENERATION_VARIED_FITNESS
        child->s_fitness = UNDEFINED;
    #endif
    if (op_to_do->repro_op_type == CROSSOVER_ON_NODES)
    {
        DoCrossoverOp(1,child,op_to_do,&(gpop.parent1));
        child->s_fitness = UNDEFINED;
        #if (REPRO_ERROR_CHECKING)
        if (ErrorInDude(child))
        {
            gpi_SendError("ERROR from docrossoverop -- nodes\n");
            exit(1);
        }
        #endif
    }
    else if (op_to_do->repro_op_type == CROSSOVER_ON_LEAVES)
    {
        DoCrossoverOp(0,child,op_to_do,&(gpop.parent1));
        child->s_fitness = UNDEFINED;
       #if (REPRO_ERROR_CHECKING)
        if (ErrorInDude(child))
        {
            gpi_SendError("ERROR from docrossoverop -- leaves\n");
            exit(1);
        }
       #endif
    }
    else if (op_to_do->repro_op_type == MUTATION)
    {
        DoMutation(GetRightBranch(&(gpop.parent1),op_to_do->brnum1),
                   GetRightBranch(child,op_to_do->brnum1));
#if 0
    printf("in do op Parent -- MUTATION");
    PrintIndividual(&(gpop.parent1),stdout);
    printf("in do op Child -- MUTATION");
    PrintIndividual(child,stdout);
#endif
        child->s_fitness = UNDEFINED;
      #if (REPRO_ERROR_CHECKING)
        if (ErrorInDude(child))
        {
            gpi_SendError("ERROR from mutation\n");
            exit(1);
        }
      #endif
    }
    else if (op_to_do->repro_op_type == BRCREATE)
    {
        temp = DoBranchCreation(child,&(gpop.parent1));
        temp=temp;/*to keep compiler from complaining*/
      #if (REPRO_ERROR_CHECKING)
        if (ErrorInDude(child))
        {
            gpi_SendError("ERROR from branchcreate\n");
            exit(1);
        }
      #endif
    }
    #if (USE_IPBCO || USE_ITERATION_GROUP_CREATION)
    else if (op_to_do->repro_op_type == IPB_BRC)
    {
        #if (USE_IPBCO)
            temp = DoIterationPerformingBranchCreation(child,&(gpop.parent1));
        #else
            temp = DoIterationGroupCreation(child,&(gpop.parent1));
        #endif
        temp=temp;
        child->s_fitness = UNDEFINED;
      #if (REPRO_ERROR_CHECKING)
        if (ErrorInDude(child))
        {
            gpi_SendError("ERROR from IPBbranchcreate\n");
            exit(1);
        }
       #endif
    }
    #endif
    else if (op_to_do->repro_op_type == BRDUP)
    {
        temp = 	DoBranchDuplication(child,&(gpop.parent1));
      #if (REPRO_ERROR_CHECKING)
        if (ErrorInDude(child))
        {
            gpi_SendError("ERROR from branch duplication\n");
            exit(1);
        }
      #endif
    }
    else if (op_to_do->repro_op_type == BRDEL)
    {
        temp = DoBranchDeletion(child,&(gpop.parent1));
        child->s_fitness = UNDEFINED;
      #if (REPRO_ERROR_CHECKING)
        if (ErrorInDude(child))
        {
            gpi_SendError("ERROR from branch deletion\n");
            exit(1);
        }
      #endif
    }
    else if (op_to_do->repro_op_type == ARGDUP)
    {
        temp = DoArgumentDuplication(child,&(gpop.parent1));
      #if (REPRO_ERROR_CHECKING)
        if (ErrorInDude(child))
        {
            gpi_SendError("ERROR from do arg duplication\n");
            exit(1);
        }
       #endif
    }
    else if (op_to_do->repro_op_type == ARGDEL)
    {
        temp = DoArgumentDeletion(child,&(gpop.parent1));
      #if (REPRO_ERROR_CHECKING)
        if (ErrorInDude(child))
        {
            gpi_SendError("ERROR from do arg deletion\n");
            exit(1);
        }
      #endif
        child->s_fitness = UNDEFINED;
    }
}



void ChooseOneReproduction(int early, int counter, int ind_num)/*;*/ /*funcdef - dgpc - DoOneReproduction*/
{
	int parent1;
	float fraction;
	int bnum1,bnum2,bnum;
        int temp;

        #if (SEDUCTION == ON)
            g_male_selection_method = (counter+ind_num) %2;
        #else
            g_male_selection_method =0;
        #endif
	parent1 = FindGoodTree(g_male_selection_method);
        counter=counter;
        bnum2=bnum2;
        UnCompressIndividual(&(gpop.members[parent1]),&(gpop.parent1));
        (gpop.members[parent1].usage)++;
        gpop.repro_op_list[ind_num].next_for_parent1 = gpop.members[parent1].op_list;
        gpop.members[parent1].op_list = &(gpop.repro_op_list[ind_num]);
        gpop.repro_op_list[ind_num].parent1 = parent1;
        gpop.repro_op_list[ind_num].parent2 = -1;
	fraction = (float) RandomFloat((float)1.0);
        gpop.repro_op_list[ind_num].repro_op_type = COPY;
    if ( (early && (fraction < (
        (gpop.pop_startup_info.early_crossover_fraction_for_node)+
	(gpop.pop_startup_info.early_crossover_fraction_for_leaves)))) ||
	(!early && (fraction <
        (gpop.pop_startup_info.crossover_fraction_for_node)+
	(gpop.pop_startup_info.crossover_fraction_for_leaves))))
    {
        #ifdef SIZE_WEIGHTED_CROSSOVER_BRANCH_SELECTION
        #   if (SIZE_WEIGHTED_CROSSOVER_BRANCH_SELECTION)
        	bnum = ChooseWRandomBranch(&(gpop.parent1));
        #   else
    	        bnum = (int) RandomInt(gpop.parent1.current_number_of_adfs + NUM_RPBS);	
        #   endif
        #else
    	        bnum = (int) RandomInt(gpop.parent1.current_number_of_adfs + NUM_RPBS);	
        #endif
        gpop.repro_op_list[ind_num].brnum1 = bnum;
 	if ( (early && (fraction <
            (gpop.pop_startup_info.early_crossover_fraction_for_node))) ||
	   (!early&& (fraction <
            (gpop.pop_startup_info.crossover_fraction_for_node))))
        {
	   DoCrossoverPrep(1, &(gpop.repro_op_list[ind_num]),
                             &(gpop.parent1), bnum);
           gpop.repro_op_list[ind_num].repro_op_type = CROSSOVER_ON_NODES;

        }
	else
        {
    	   DoCrossoverPrep(0, &(gpop.repro_op_list[ind_num]),
                              &(gpop.parent1), bnum);
           gpop.repro_op_list[ind_num].repro_op_type = CROSSOVER_ON_LEAVES;
        }
    }
    else if ((early && (fraction <
            (gpop.pop_startup_info.early_crossover_fraction_for_node) +
            (gpop.pop_startup_info.early_crossover_fraction_for_leaves) +
	    (gpop.pop_startup_info.early_mutation_fraction))) ||
	    (!early && (fraction <
            (gpop.pop_startup_info.crossover_fraction_for_node) +
	    (gpop.pop_startup_info.crossover_fraction_for_leaves) +
	    (gpop.pop_startup_info.mutation_fraction))))
    {
        gpop.repro_op_list[ind_num].repro_op_type = MUTATION;
        #ifdef SIZE_WEIGHTED_CROSSOVER_BRANCH_SELECTION
        #   if (SIZE_WEIGHTED_CROSSOVER_BRANCH_SELECTION)
        	bnum = ChooseWRandomBranch(&(gpop.parent1));
        #   else
    	        bnum = (int) RandomInt(gpop.parent1.current_number_of_adfs + NUM_RPBS);	
        #   endif
        #else
    	        bnum = (int) RandomInt(gpop.parent1.current_number_of_adfs + NUM_RPBS);	
        #endif
        gpop.repro_op_list[ind_num].brnum1 = bnum;
    }
    else if ((early && (fraction <
            (gpop.pop_startup_info.early_crossover_fraction_for_node) +
            (gpop.pop_startup_info.early_crossover_fraction_for_leaves) +
	    (gpop.pop_startup_info.early_mutation_fraction) +
	    (gpop.pop_startup_info.early_branch_creation_fraction))) ||
            (!early && (fraction <
            (gpop.pop_startup_info.crossover_fraction_for_node) +
	    (gpop.pop_startup_info.crossover_fraction_for_leaves) +
	    (gpop.pop_startup_info.mutation_fraction) +
	    (gpop.pop_startup_info.branch_creation_fraction))))			
    {
        gpop.repro_op_list[ind_num].repro_op_type = BRCREATE;
    }
    else if ((early && (fraction <
            (gpop.pop_startup_info.early_crossover_fraction_for_node) +
	    (gpop.pop_startup_info.early_crossover_fraction_for_leaves) +
	    (gpop.pop_startup_info.early_mutation_fraction) +
	    (gpop.pop_startup_info.early_branch_creation_fraction) +
	    (gpop.pop_startup_info.early_branch_duplication_fraction))) ||
	    (!early && (fraction <
            (gpop.pop_startup_info.crossover_fraction_for_node) +
	    (gpop.pop_startup_info.crossover_fraction_for_leaves) +
	    (gpop.pop_startup_info.mutation_fraction) +
	    (gpop.pop_startup_info.branch_creation_fraction) +
            (gpop.pop_startup_info.branch_duplication_fraction))))			
    {
        gpop.repro_op_list[ind_num].repro_op_type = BRDUP;
    }
    else if ((early && (fraction <
            (gpop.pop_startup_info.early_crossover_fraction_for_node) +
            (gpop.pop_startup_info.early_crossover_fraction_for_leaves) +
            (gpop.pop_startup_info.early_mutation_fraction) +
            (gpop.pop_startup_info.early_branch_creation_fraction) +
            (gpop.pop_startup_info.early_branch_duplication_fraction) +
            (gpop.pop_startup_info.early_branch_deletion_fraction))) ||
            (!early && (fraction < (gpop.pop_startup_info.crossover_fraction_for_node) +
            (gpop.pop_startup_info.crossover_fraction_for_leaves) +
            (gpop.pop_startup_info.mutation_fraction) +
            (gpop.pop_startup_info.branch_creation_fraction) +
            (gpop.pop_startup_info.branch_duplication_fraction) +
            (gpop.pop_startup_info.branch_deletion_fraction))))			
    {
        gpop.repro_op_list[ind_num].repro_op_type = BRDEL;
    }
    else if ((early && (fraction <
            (gpop.pop_startup_info.early_crossover_fraction_for_node) +
            (gpop.pop_startup_info.early_crossover_fraction_for_leaves) +
            (gpop.pop_startup_info.early_mutation_fraction) +
            (gpop.pop_startup_info.early_branch_creation_fraction) +
            (gpop.pop_startup_info.early_branch_duplication_fraction) +
            (gpop.pop_startup_info.early_branch_deletion_fraction) +
            (gpop.pop_startup_info.early_arg_duplication_fraction))) ||
    	    (!early && (fraction <
            (gpop.pop_startup_info.crossover_fraction_for_node) +
            (gpop.pop_startup_info.crossover_fraction_for_leaves) +
            (gpop.pop_startup_info.mutation_fraction) +
            (gpop.pop_startup_info.branch_creation_fraction) +
            (gpop.pop_startup_info.branch_duplication_fraction) +
            (gpop.pop_startup_info.branch_deletion_fraction) +
            (gpop.pop_startup_info.arg_duplication_fraction))))
    {
        gpop.repro_op_list[ind_num].repro_op_type = ARGDUP;
    }    else if ((early && (fraction <
            (gpop.pop_startup_info.early_crossover_fraction_for_node) +
            (gpop.pop_startup_info.early_crossover_fraction_for_leaves) +
            (gpop.pop_startup_info.early_mutation_fraction) +
            (gpop.pop_startup_info.early_branch_creation_fraction) +
            (gpop.pop_startup_info.early_branch_duplication_fraction) +
            (gpop.pop_startup_info.early_branch_deletion_fraction) +
            (gpop.pop_startup_info.early_arg_duplication_fraction) +
            (gpop.pop_startup_info.early_arg_deletion_fraction))) ||
	    (!early &&
            (fraction < (gpop.pop_startup_info.crossover_fraction_for_node) +
            (gpop.pop_startup_info.crossover_fraction_for_leaves) +
            (gpop.pop_startup_info.mutation_fraction) +
            (gpop.pop_startup_info.branch_creation_fraction) +
            (gpop.pop_startup_info.branch_duplication_fraction) +
            (gpop.pop_startup_info.branch_deletion_fraction) +
            (gpop.pop_startup_info.arg_duplication_fraction) +
            (gpop.pop_startup_info.arg_deletion_fraction))))
    {
        gpop.repro_op_list[ind_num].repro_op_type = ARGDEL;
    }
    #if (USE_IPBCO || USE_ITERATION_GROUP_CREATION)
        else if ((early && (fraction <
           (gpop.pop_startup_info.early_crossover_fraction_for_node) +
           (gpop.pop_startup_info.early_crossover_fraction_for_leaves) +
            (gpop.pop_startup_info.early_mutation_fraction) +
            (gpop.pop_startup_info.early_branch_creation_fraction) +
            (gpop.pop_startup_info.early_branch_duplication_fraction) +
            (gpop.pop_startup_info.early_branch_deletion_fraction) +
            (gpop.pop_startup_info.early_arg_duplication_fraction) +
            (gpop.pop_startup_info.early_arg_deletion_fraction) +
            (gpop.pop_startup_info.early_ipbco_fraction))) ||
	    (!early &&
            (fraction < (gpop.pop_startup_info.crossover_fraction_for_node) +
            (gpop.pop_startup_info.crossover_fraction_for_leaves) +
            (gpop.pop_startup_info.mutation_fraction) +
            (gpop.pop_startup_info.branch_creation_fraction) +
            (gpop.pop_startup_info.branch_duplication_fraction) +
            (gpop.pop_startup_info.branch_deletion_fraction) +
            (gpop.pop_startup_info.arg_duplication_fraction) +
            (gpop.pop_startup_info.arg_deletion_fraction)+
            (gpop.pop_startup_info.ipbco_fraction))))
    {
        gpop.repro_op_list[ind_num].repro_op_type = IPB_BRC;
    }
    #endif	


}						



/* Formerly tree.c file */


/*----------------------------------------------------------------*/

void CopySubtree(Branch * from_br,  /*funcdef - dgpc - CopySubtree*/
                  int from_start,           /*funcdef - dgpc - CopySubtree*/
                  int from_end,             /*funcdef - dgpc - CopySubtree*/
		  Branch * to_br,    /*funcdef - dgpc - CopySubtree*/
                  int to_start)/*;*/        /*funcdef - dgpc - CopySubtree*/
{
	int i,j;
	for (i=from_start, j=to_start; i <= from_end; i++,j++)
	{
		to_br->tree[j].opcode = from_br->tree[i].opcode;
	}
}




/*-----------------------------------------------------------------------------*/
int CreateRandomTree(Branch * br, int index, int mdepth, int top, int fillfull)/*;*/ /*funcdef - dgpc - CreateRandomTree*/
{
int i, temp1,temp2, flag;
int passindex;
i=0;temp1=0;temp2=0;flag=0;passindex=0;

    #ifdef _ICC
    if (br == NULL)
        __asm{seterr;};
    #endif

    if (mdepth > gpop.pop_startup_info.max_new_tree_depth ||
        index > br->num_nodes || index < 0)
    {
        #ifdef _ICC
            __asm{seterr;};
        #else
            gpi_SendError("Error in create_random_tree\n");
            exit(1);
        #endif
     }
     for (i=0;ifunction_vector[i]) <  -1) ||
            ((br->function_vector[i]) >  MAX_NUM_ARGS))
        {
            #ifdef _ICC
                __asm{seterr;};
            #else
                fprintf(stderr,"Function vector is hosed in crt\n");
            #endif
        }
     }

   temp1=temp1;
	if (mdepth <= 0 || index > (br->num_nodes -
					((gpop.pop_startup_info.max_new_tree_depth)*(MAX_NUM_ARGS-1))))
			 /* therefore must be a zero argument function*/
	{
		flag=0;
		while (!flag)
		{

			temp2 = ChooseRandomFunction(&gpop,0,br); /*RandomInt(gpop.num_functions[br->branchnum]);*/
			if (_function_arity(temp2) == 0)
				flag = 1;
		}
		br->tree[index].opcode = temp2;

		if ((temp2 >= br->ind->current_number_of_adfs) &&
					gpop.func_table[temp2].constant)
                {
                   br->tree[index].opcode =
                                 gpop.num_general_functions -1
                                    + RandomInt(MAXNUMFORARANDOMCONSTANT -
                                      (gpop.num_general_functions-2));
                    return(index+1);
                }
		return(index+1);
	}
	else if (top || fillfull)
	{
		flag=0;
		while (!flag)
		{

			temp2 = ChooseRandomFunction(&gpop,1,br); /*RandomInt(gpop.num_functions[br->branchnum]);*/
			if (_function_arity(temp2) > 0)
				flag = 1;
		}	
		br->tree[index].opcode = temp2;
		passindex = index+1;
                #if (USE_PROB_SPECIFIC_EARLY_TREE_END)
                    mdepth = ProbSpecificEarlyTreeEnd(mdepth, temp2,&gpop);
                #endif
		for (i=0; i< _function_arity(temp2); i++)
			passindex = CreateRandomTree(br, passindex, mdepth -1, 0, fillfull);
		return(passindex);
	}
	else
	{
		flag=0;
		while (!flag)
		{

			temp2 = ChooseRandomFunction(&gpop,2,br); /*RandomInt(gpop.num_functions[br->branchnum]);*/
			if (_function_arity(temp2) >= 0)
				flag = 1;
		}	
		
		br->tree[index].opcode = temp2;
		if ((temp2 >= br->ind->current_number_of_adfs) &&
					gpop.func_table[temp2].constant)
                {
                       br->tree[index].opcode =
                                 gpop.num_general_functions -1
                                    + RandomInt(MAXNUMFORARANDOMCONSTANT -
                                      (gpop.num_general_functions-2));
                    return(index+1);
                }
		passindex = index+1;
                #if (USE_PROB_SPECIFIC_EARLY_TREE_END)
                    mdepth = ProbSpecificEarlyTreeEnd(mdepth, temp2,&gpop);
                #endif
		for (i=0; i< _function_arity(temp2); i++)
			passindex = CreateRandomTree(br, passindex, mdepth -1, 0, fillfull);
		return(passindex);
	}
}

/*----------------------------------------------------*/

int CreateRandomADFTree(Branch * br,  /*funcdef - dgpc - CreateRandomADFTree*/
                           int index,           /*funcdef - dgpc - CreateRandomADFTree*/
        		   int mdepth,          /*funcdef - dgpc - CreateRandomADFTree*/
                           int top,             /*funcdef - dgpc - CreateRandomADFTree*/
                           int fillfull)/*;*/   /*funcdef - dgpc - CreateRandomADFTree*/
{
int i, temp1,temp2, flag;
int passindex,rtmp,test;


i=0;temp1=0;temp2=0;flag=0;passindex=0;rtmp=0;test=0;
#ifdef _ICC
if (br == NULL)
    __asm{seterr;};
#endif

    if (mdepth > gpop.pop_startup_info.max_new_tree_depth ||
        index > br->num_nodes || index < 0)
    {
        #ifdef _ICC
            __asm{seterr;};
        #else
            gpi_SendError("Error in create_random_adf_tree\n");
            exit(1);
        #endif
     }
     for (i=0;ifunction_vector[i]) <  -1) ||
            ((br->function_vector[i]) >  MAX_NUM_ARGS))
        {
            #ifdef _ICC
                __asm{seterr;};
            #else
                fprintf(stderr,"Function vector is hosed in cradft\n");
            #endif
        }
     }


   temp1=temp1;
	if (mdepth <= 0 || index > (br->num_nodes -
					((gpop.pop_startup_info.max_new_tree_depth)*
                                           (MAX_NUM_ARGS-1))))
			 /* therefore must be a zero argument function*/
	{
		flag=0;
		while (!flag)
		{

			temp2 = ChooseRandomFunction(&gpop,0,br); /*RandomInt(gpop.num_functions[br->branchnum]);*/
			if (_function_arity(temp2) == 0)
				flag = 1;
		}
		br->tree[index].opcode = temp2;
		if ((temp2 >= (MAX_NUM_ADF_ARGS+MAX_NUM_ADFS)) &&
		        gpop.func_table[temp2].constant)
               {
                       br->tree[index].opcode = gpop.num_general_functions -1
                                                + RandomInt(MAXNUMFORARANDOMCONSTANT -
                                               (gpop.num_general_functions-1));
                    return(index+1);
                }
		return(index+1);
	}
	else if (top || fillfull)
	{
		flag=0;
		while(!flag)
		{

			temp2 = ChooseRandomFunction(&gpop,1,br); /*RandomInt(gpop.num_functions[br->branchnum]);*/
			if (_function_arity(temp2) > 0)
				flag = 1;
		}	
		br->tree[index].opcode = temp2;

		passindex = index+1;
                #if (USE_PROB_SPECIFIC_EARLY_TREE_END)
                    mdepth = ProbSpecificEarlyTreeEnd(mdepth, temp2,&gpop);
                #endif
		for (i=0; i< _function_arity(temp2); i++)
			passindex = CreateRandomADFTree(br, passindex, mdepth -1, 0, fillfull);
		return(passindex);
	}
	else
	{
		flag=0;
		while(!flag)
		{

			temp2 = ChooseRandomFunction(&gpop,2,br); /*RandomInt(gpop.num_functions[br->branchnum]);*/
			if (_function_arity(temp2) >= 0)
				flag = 1;
		}	
		
		br->tree[index].opcode = temp2;
		if ((temp2 >= (MAX_NUM_ADF_ARGS+MAX_NUM_ADFS)) &&
		        gpop.func_table[temp2].constant)
                {
                       rtmp = gpop.num_general_functions-1 + RandomInt(MAXNUMFORARANDOMCONSTANT-
                                                                (gpop.num_general_functions-2));
                       br->tree[index].opcode =rtmp;
                                /* gpop.constants[rtmp]; */
                                 /*[gpop.num_general_functions -1
                                    + RandomInt(MAXNUMFORARANDOMCONSTANT -
                                      (gpop.num_general_functions-2))]; */
                       test =2;
                       test=test;
                    return(index+1);
                }
		passindex = index+1;
                #if (USE_PROB_SPECIFIC_EARLY_TREE_END)
                    mdepth = ProbSpecificEarlyTreeEnd(mdepth, temp2,&gpop);
                #endif
		for (i=0; i< _function_arity(temp2); i++)
			passindex = CreateRandomADFTree(br, passindex, mdepth -1, 0, fillfull);
		return(passindex);
	}
}
	
/*----------------------------------------------------*/
/*
void CopyFVector(int * fvector_from, int * fvector_to)
{
    int i;
    for (i=0;ifunction_vector,fvector);
  ConstrainedSyntaxFilters(fvector, br, TOP_OF_TREE, 0, &gpop);
  return(doCreateRandomCSSTree(br,index,mdepth,top,fillfull,fvector));
  #endif
}

int doCreateRandomCSSTree(Branch * br, int index, int mdepth, int top, int fillfull,int * fvector)/*;*/ /*funcdef - dgpc - doCreateRandomCSSTree*/
{
int i, temp1,temp2, flag;
int passindex,zeros,nonzeros;
int tvector[TOTAL_NUMBER_OF_FUNCTIONS];

i=0;temp1=0;temp2=0;flag=0;passindex=0;

    #ifdef _ICC
    if (br == NULL)
        __asm{seterr;};
    #endif

    if (mdepth > gpop.pop_startup_info.max_new_tree_depth ||
        index > br->num_nodes || index < 0)
    {
        #ifdef _ICC
            __asm{seterr;};
        #else
            gpi_SendError("Error in create_random_tree\n");
            exit(1);
        #endif
     }
     for (i=0;ifunction_vector[i]) <  -1) ||
            ((br->function_vector[i]) >  MAX_NUM_ARGS))
        {
            #ifdef _ICC
                __asm{seterr;};
            #else
                fprintf(stderr,"Function vector is hosed in crt\n");
            #endif
        }
     }
   CopyFVector(fvector,tvector);
   temp1=temp1;
   zeros=0;
   nonzeros=0;
   for (i=0;i 0)
            nonzeros =1;

   }

	if ((!nonzeros) || (mdepth <= 0) || (index > (br->num_nodes -
					((gpop.pop_startup_info.max_new_tree_depth)*(MAX_NUM_ARGS-1)))))
			 /* therefore must be a zero argument function*/
	{
		flag=0;
		while (!flag)
		{

			temp2 = ChooseRandomCSSFunction(&gpop,0,br,fvector); /*RandomInt(gpop.num_functions[br->branchnum]);*/
			if (_function_arity(temp2) == 0)
				flag = 1;
		}
		br->tree[index].opcode = temp2;

		if ((temp2 >= br->ind->current_number_of_adfs) &&
					gpop.func_table[temp2].constant)
                {
                   br->tree[index].opcode =
                                 gpop.num_general_functions -1
                                    + RandomInt(MAXNUMFORARANDOMCONSTANT -
                                      (gpop.num_general_functions-2));
                    return(index+1);
                }
		return(index+1);
	}
	else if (top || fillfull)
	{
		flag=0;
		while (!flag)
		{

			temp2 = ChooseRandomCSSFunction(&gpop,1,br,fvector); /*RandomInt(gpop.num_functions[br->branchnum]);*/
			if (_function_arity(temp2) > 0)
				flag = 1;
		}	
		br->tree[index].opcode = temp2;
		passindex = index+1;
                #if (USE_PROB_SPECIFIC_EARLY_TREE_END)
                    mdepth = ProbSpecificEarlyTreeEnd(mdepth, temp2,&gpop);
                #endif
		for (i=0; i< _function_arity(temp2); i++)
                {
                        CopyFVector(tvector,fvector);
                    #if (USE_CONSTRAINED_STRUCTURE)
                        ConstrainedSyntaxFilters(fvector, br, temp2, i, &gpop);
                    #endif
			passindex = doCreateRandomCSSTree(br, passindex, mdepth -1, 0, fillfull,fvector);
                }
		return(passindex);
	}
	else
	{
		flag=0;
		while (!flag)
		{

			temp2 = ChooseRandomCSSFunction(&gpop,2,br,fvector); /*RandomInt(gpop.num_functions[br->branchnum]);*/
			if (_function_arity(temp2) >= 0)
				flag = 1;
		}	
		
		br->tree[index].opcode = temp2;
		if ((temp2 >= br->ind->current_number_of_adfs) &&
					gpop.func_table[temp2].constant)
                {
                       br->tree[index].opcode =
                                 gpop.num_general_functions -1
                                    + RandomInt(MAXNUMFORARANDOMCONSTANT -
                                      (gpop.num_general_functions-2));
                    return(index+1);
                }
		passindex = index+1;
                #if (USE_PROB_SPECIFIC_EARLY_TREE_END)
                    mdepth = ProbSpecificEarlyTreeEnd(mdepth, temp2,&gpop);
                #endif
		for (i=0; i< _function_arity(temp2); i++)
                {
                        CopyFVector(tvector,fvector);
                    #if (USE_CONSTRAINED_STRUCTURE)
                        ConstrainedSyntaxFilters(fvector, br, temp2, i, &gpop);
                    #endif
			passindex = doCreateRandomCSSTree(br, passindex, mdepth -1, 0, fillfull,fvector);
                }
		return(passindex);
	}
}


/*----------------------------------------------------*/

int TraverseSubtree(Branch * br, int index)/*;*/  /*funcdef - dgpc - TraverseSubtree*/
    /* returns the node_index at the end of the subtree...*/
{
	int i,num,divby0;

        divby0 = divby0;
	if (br->tree[index].opcode == EMPTY) {
		sprintf(g_str,"Error, an unused node is being accessed at %d\n in traverse",index);
                gpi_SendError(g_str);
                exit(1);
               /* return(-1); */
        }
	if (index >= br->num_nodes)
	{	
		sprintf(g_str, "Oops!! Ran past the end of a tree, in TraverseSubtree!!\n");
                gpi_SendError(g_str);
                /* force error to show backtrace in debugger
                divby0 = 1/0; */

		exit(1);
	}
	else
	{
                if (_function_is_constant(br->tree[index].opcode))
                {
                    return(index);
                }
		num = index;
		for (i=0;i< _function_arity(br->tree[num].opcode);i++)
		{
			index = TraverseSubtree(br, index+1);
		}	
	}
	return(index);
}

int RiskyTraverseSubtree(Branch * br, int index)/*;*/  /*funcdef - dgpc - TraverseSubtree*/
    /* returns the node_index at the end of the subtree...*/
{
	int i,num,divby0;

        divby0 = divby0;
	if (br->tree[index].opcode == EMPTY) {
		sprintf(g_str,"Error, an unused node is being accessed at %d\n in traverse",index);
                gpi_SendError(g_str);
                return(br->num_nodes+100);
               /* return(-1); */
        }
	if (index >= br->num_nodes)
	{	
		sprintf(g_str, "Oops!! Ran past the end of a tree, in RiskyTraverseSubtree!!\n");
                gpi_SendError(g_str);
                /* force error to show backtrace in debugger
                divby0 = 1/0; */
                return(br->num_nodes+100);
	}
	else
    	{
                if (index < br->num_nodes && _function_is_constant(br->tree[index].opcode))
                {
                    return(index);
                }
		num = index;
                if (index < br->num_nodes)
 		 for (i=0;i< _function_arity(br->tree[num].opcode);i++)
		 {
                     if (index < br->num_nodes)
			 index = TraverseSubtree(br, index+1);
		 }
                else
                  index += 100; 	
	}
	return(index);
}


int DoDepthOfPointInBranch(Branch *br, int index,   /*funcdef*/
                                       int point, int  level, int * depth)  /*;*/ /*funcdef*/
{
        int i,num;
	if (br->tree[index].opcode ==  EMPTY) {
		sprintf(g_str,"Error, an unused node is being accessed at %d\n in traverse",index);
                gpi_SendError(g_str);
                exit(1);
               /* return(-1); */
        }
	if (index >= br->num_nodes)
	{	
		sprintf(g_str, "Oops!! Ran past the end of a tree, in DepthOfPointTraverseSubtree!!\n");
                gpi_SendError(g_str);
                /* force error to show backtrace in debugger
                divby0 = 1/0; */
		exit(1);
	}
	else
	{
                if (level > MAX_DEPTH_FOR_TREE)
                {
                    *depth = 0;
                    return(-1);
                }
                if (index == point)
                {
                    *depth = level+1;
                    return(-1);
                }
                if (_function_is_constant(br->tree[index].opcode))
                {
                    return(index);
                }
		num = index;
		for (i=0;i< _function_arity(br->tree[num].opcode);i++)
		{
			index = DoDepthOfPointInBranch(br, index+1,point,level+1,
                                                                    depth );
                        if (index == -1)
                            return(-1);
                 }
	}
	return(index);
}

int do_depth_of_branch(Branch *br, int index, int * depth)/*;*/ /*funcdef*/
{
int i,num,thisdepth,deepest;

        (*depth)++;
        deepest=*depth;

	if (br->tree[index].opcode ==  EMPTY) {
		sprintf(g_str,"Error, an unused node is being accessed at %d\n in traverse",index);
                gpi_SendError(g_str);
                exit(1);
               /* return(-1); */
        }
	if (index >= br->num_nodes)
	{	
		sprintf(g_str, "Oops!! Ran past the end of a tree, in Do_Depth_Of_BranchTraverseSubtree!!\n");
                gpi_SendError(g_str);
                /* force error to show backtrace in debugger
                divby0 = 1/0; */
		exit(1);
	}
	else
	{
                if (*depth > MAX_DEPTH_FOR_TREE)
                {
                    *depth = MAX_DEPTH_FOR_TREE+1;
                    return(-1);
                }
                if (_function_is_constant(br->tree[index].opcode))
                {
                    return(index);
                }
		num = index;
                thisdepth = *depth;
		for (i=0;i< _function_arity(br->tree[num].opcode);i++)
		{
                        *depth = thisdepth;
			index = do_depth_of_branch(br, index+1,depth );
                        if (*depth > deepest)
                            deepest = *depth;
                        if (index == -1)
                            return(-1);
                 }
                *depth = deepest;
	}
	return(index);
}

int depth_of_branch(Branch *br)/*;*/ /*funcdef*/
{
    int depth;
    depth =0;
    do_depth_of_branch(br, 0,&depth);
    return(depth);
}

int DepthOfBranchFromPoint(Branch *br,int point)/*;*/ /*funcdef*/
{
    int depth;
    depth =0;
    do_depth_of_branch(br, point,&depth);
    return(depth);
}

int DepthOfPointInBranch(Branch *br,int point)/*;*/ /*funcdef*/
{
    int depth;
    depth =0;
    DoDepthOfPointInBranch(br, 0, point, 0,&depth);
    if (depth ==0)
    {
        sprintf(g_str,"Error in getting the depth at point %d -- IS NOT IN THIS TREE\n",
                                                point);
        gpi_SendError(g_str);
        exit(1);
    }
    return(depth);
}
/*
GTYPE EvalBranch(Branch *br,Population *pop)
{
int temp;
GTYPE temp2;

temp = br->ind->index_ptr;
br->ind->index_ptr  =0;
temp2 = _eval_subtree(br,pop);
br->ind->index_ptr  =temp;
return(temp2);

}

*/
void CompressIndividual(Individual *ind,     /*funcdef*/
                        CompInd * cind)/*;*/ /*funcdef*/
{
 int i, j;
 static int counter=0;
 Branch *br;

 cind->s_fitness=ind->s_fitness;
 cind->current_number_of_adfs = (signed char) ind->current_number_of_adfs;
 cind->hits = (int) ind->hits;
 cind->beauty = ind->beauty;
 for (i=0;i< MAX_NUM_ADFS + NUM_RPBS; i++)
 {
    for (j=gpop.brstart[i]; j<= gpop.brend[i]; j++)
    {
        cind->code[j] = (Snode) ind->code[j].opcode;
    }
   #if (POINT_TYPING)
    for (j=0;jfunction_vector[i][j] = br->function_vector[j];
    }
    #endif
 }
  for (j=0;jadf_type[j] = (signed char) ind->adf_type[j];
    #endif
  }
}

void UnCompressIndividual(CompInd * cind,       /*funcdef*/
                          Individual *ind)/*;*/ /*funcdef*/
{
int i, j;
Branch * br;

 ind->s_fitness=cind->s_fitness;
 ind->current_number_of_adfs = (int) cind->current_number_of_adfs;
 ind->hits = (int) cind->hits;
 ind->beauty = cind->beauty;
 ind->index_ptr =0;
 for (i=0;i< MAX_NUM_ADFS + NUM_RPBS; i++)
 {
    for (j=gpop.brstart[i]; j<= gpop.brend[i]; j++)
    {
        ind->code[j].opcode = (int) cind->code[j];
    }
    br = GetRightBranch(ind, i);
    br->branchnum = i;
    br->num_nodes = gpop.brsize[i];
    br->tree = &(ind->code[gpop.brstart[i]]);
    br->ind = ind;
   #if (POINT_TYPING)
    for (j=0;jfunction_vector[j] = cind->function_vector[i][j];
   #else
    for (j=0;jfunction_vector[j] = gpop.function_assignment[i][j];
   #endif
    for (j=MAX_NUM_ADFS + MAX_NUM_ADF_ARGS;jfunction_vector[j] = gpop.function_assignment[i][j];
    /*Set Jump Points and Value Points*/
     SetJumpsAndVals(br, (i < ind->current_number_of_adfs+NUM_RPBS));
  }
  for (j=0;jadf_arity[j] = ind->rpbs[0].function_vector[j];
    #if (USE_MULTI_TYPED_ADFS)
     ind->adf_type[j] = (int) cind->adf_type[j];
    #endif
  }
}

void SetJumpsAndVals(Branch * br,int valid)/*;*/ /*funcdef*/
{
int left;
int index;
int temp;
left =1;
index=0;

    while(left >0 && valid) /*changed 7/25/95 da*/
    {
        br->tree[index].jump = TraverseSubtree(br,index) +1;
        temp =  _function_arity(br->tree[index].opcode);
        if (temp < 0 && valid)
        {
            sprintf(g_str,"Illegal node in tree %d, index %d,temp%d,opcode %d,string %s in setjumps\n",
                br->branchnum,index,temp,br->tree[index].opcode,&(br->tree[index]));
            gpi_SendError(g_str);
            exit(1);
        }
        left += temp;
        left--;
        index++;
    }

}

int ErrorInDude(Individual * ind)
{
int left;
int index;
int temp;
Branch * br;
int temp2;
int i;

    for (i=0;icurrent_number_of_adfs;i++)
    {
        left =1;
        index=0;
        br = GetRightBranch(ind,i);
        while(left >0)
        {
            temp2 = RiskyTraverseSubtree(br,index) +1;
            if (temp2 > br->num_nodes)
            {
                sprintf(g_str,"Error, too many nodes in tree %d\n",i);
                gpi_SendError(g_str);
                return(1);
            }
            temp =  _function_arity(br->tree[index].opcode);
/*            printf("temp %d, index %d, tree %d, opcode %d\n",temp,index,i,br->tree[index].opcode);*/
            if (temp < 0)
            {
                sprintf(g_str,"Error Found Illegal node in tree %d, index %d,temp%d,opcode %d\n",
                    i,index,temp,br->tree[index].opcode);
                gpi_SendError(g_str);
                return(1);
            }

            left += temp;
            left--;
            index++;
        }
    }
    return(0);
}