// rand_tree.cc File for uniform random tree generator, with GPQUICK-2.1 // See ETL-TR-95-35 14 Nov 1995 Hitoshi Iba Random tree generator for GP // W.B.Langdon cs.bham.ac.uk 9 August 1997 #define main_version "$Revision: 1.20 $" //Modifications (in reverse order) //WBL 20 May 98 BUGFIX lookup() following email from Christian Igel // //WBL 7 Jul 98 Use RndOp //WBL 12 Jun 98 Allow caller to specify tree shape to rand_tree //WBL 11 Mar 98 Add code to create tables only one tree size //WBL 10 Mar 98 Speed up by, eg using static structure for gtree and stack //WBL 21 Jan 98 Use double precision (should take above 1e07 trees created) // remove code to remove trees less than FLT_EPSILON // Potentially changes GPQUICK_SEED, previous verison r1.4 //WBL 29 Dec 97 Optionally include number of different terminals and functions // of each arity when calculating tree shape probabilties // tree_count replaced by version in ntrees.cc r1.1 // Also ensure scope of for loop variables is limited //WBL 12 Aug 97 Use log of factorial, add remove i[4] loop //WBL 11 Aug 97 Extend range of size before overflow // BUGFIX limit (efficiency saving only), //WBL 1 Aug 97 File created from rand_tree-test.cc #include #include "pch.h" #include "chrome.h" #define DEBUG true //dont change! #define max_arity 4 double* log_fact; int log_fact_size = 0; void new_log_fact(const int x) { log_fact = new double[x+1]; log_fact_size = x+1; double f = 0; log_fact[0] = 0; for(int i=1;i=0&&c=0&&c=0&&c1)? arity:0); //function or terminal? for(int a=0; a0); return data[--sp]; } void push(gtree* t) {assert(spitem(i); j++) cout<<"y"; //} //cout<item(i)); //use static structure for speed for(int j=d->item(i); j>0; --j) tlist[i].setchild(j-1,sstack.pop()); sstack.push(&tlist[i]); // gtree* t[max_arity]; original code // //cout<<"Popping "<item(i)<item(i); j>0; --j) t[j-1] = s->pop(); // gtree* n = new gtree(d->item(i),t); // //cout<<" pushing ("<arity<<")"<push(n); // //cout<<" stack "<sp<<" deep"<0 || i[4]==0)) { //cout<<"("<max) max = tree; int* savei = new int[max_arity]; memcpy(savei,&i[1],sizeof(int)*max_arity); head = new tree_chain(tree,savei,head); } } //end all_arity //We rescale enties, by normalising we can convert back from logs //and discard many entries. Set normalise count relative to best //inividual tree_chain* curr; double total = 0; for(curr=head; curr!=NULL; curr = curr->next) { curr->count = exp((curr->count)-max); total += curr->count; } //Normalise a second time so total is unity. We now discard small entries tree_chain* next; tree_chain* prev = NULL; tac_size = 0; double running = 0; for(curr=head; curr!=NULL; curr = next) { next = curr->next; const double normalise = curr->count / total; /* if(normalise < FLT_EPSILON) {//could be bigger to trim tables more * if(curr==head) head=next; * delete curr->tree_arity_counts; * delete curr; * if(prev!=NULL) prev->next = next; * } * else{ */ prev = curr; tac_size++; running += normalise; curr->count = running; /* } */ } if((running<.9999999||running>1.0000001) && tac_size>0) cout<<"ERROR "<top) lookuperror(" bot>top ",f,bot); const int i = (top+bot)/2; //cout<0 && f < tac_index[i-1] ) top = i - 1; else if( f > tac_index[i] ) bot = i + 1; else { //cout<<" found "<limit)? NULL : table[length-lower_limit]->lookup(); } };//end rand_tree_tables //assumes ip set up //based on SubInit void Chrome::lable_tree(const gtree* tp, CSelector* const funcbag) { //assert(ip>=0&&ipparams[pMaxExpr]); const int a = tp->Arity(); int i; // do {i=funcbag->roulette();} while (funclist[i]->argnum != a); // if (funclist[i]->varnum == 0) {SETNODE(expr[ip],probl->RndOp(0,a),0);} //faster! // else // {SETNODE(expr[ip],i,rnd(funclist[i]->varnum));} ip++; for(i=0;iChild(i), funcbag); }//end lable_tree //assumes ip set up BOOL Chrome::rand_tree(const int length, const int chrometree, const gtree* tp) { //cout<<"rand_tree "<params->params[pMaxExpr]) return FALSE; //no room in expr if(tp!=NULL) lable_tree(tp, probl->funcbag[chrometree]); else { const int* tac = probl->rand_tree_lookup(length, chrometree); if(tac==NULL) return FALSE; gtree* tp = random_tree(length,tac); lable_tree(tp, probl->funcbag[chrometree]); // delete tp; now static structure for speedup } return TRUE; }//end rand_tree; //must be called after all functions have been added //call this OR init_rand_tree(int size_limit) NOT BOTH //create tables for one length only void Problem::init_1rand_tree(const int size) { new_log_fact(size); assert(NUM_TREES==1); //for (int t=0;tcount();i++) //t { const FHANDLE f = funcbag[0]->GetHandle(i); //t const int a = funclist[f]->argnum; assert(a<=max_arity); #ifdef RAND_TREE_ARITIES arity[a]++; #else arity[a] = 1; #endif } rand_tree[0] = new rand_tree_tables(arity,size); //t // } } //must be called after all functions have been added void Problem::init_rand_tree(int size_limit) { if(size_limit<0) size_limit = -size_limit;//use absolute value new_log_fact(size_limit); for (int t=0;tcount();i++) { const FHANDLE f = funcbag[t]->GetHandle(i); const int a = funclist[f]->argnum; assert(a<=max_arity); #ifdef RAND_TREE_ARITIES arity[a]++; #else arity[a] = 1; #endif } //could look for common arity masks between trees, but simplier to //assume they are different and so no saving can be made. rand_tree[t] = new rand_tree_tables(size_limit,arity); //time (&now); //cout<<" "<rand_tree_lookup(length); }