/* Standard option - calculate the probability, the matrix of * expected information and the diagonal values of the variance * Dump these to disk and calculate the determinant of the * expectation matrix.*/ void standard(struct treenode *node_p,FILE *file_p,unsigned int e){ #include "variables.h" int a,b; /* Make a copy of the tree, fill and calculate the likelihoods*/ tree2=treecopy(node_p,0); filltree(node_p,tree2,0); if(sample_file_p!=NULL) fprintf(sample_file_p,"#Points 1\n\n"); /* We aren't altering the rate, so factor is 1*/ factor=1.0; factor_flag=0; det=find_information(node_p,tree2,e,factor_flag,factor); /* Print the required output - may be more than one value*/ b=1; if(NOTMODE(DETINDIV) && ISMODE(INDIVIDUAL)) b=individual; for(a=0;a<b;a++) fprintf(file_p,"%s = %1.11E\n",outstring,det[a]); if(ISMODE(HKY) && NOTMODE(NOKAPPA) && NOTMODE(PERCENTILE)) fprintf(file_p,"Information about Kappa = %1.11E\n",det[b]); free(det); }
static void dopush(Dataptr matrix, Treestack *sp, const Branch *const barray, const long root) /* push tree in barray (of root root) on to stack *sp */ { lvb_assert(sp->next <= sp->size); if (sp->next == sp->size) upsize(matrix, sp); treecopy(matrix, sp->stack[sp->next].tree, barray); sp->stack[sp->next].root = root; sp->next++; } /* end dopush() */
static int callinstr(Node **np, NodeList **init, int wr, int skip) { Node *f, *b, *n; Type *t; int class, hascalls; n = *np; //print("callinstr for %+N [ %O ] etype=%E class=%d\n", // n, n->op, n->type ? n->type->etype : -1, n->class); if(skip || n->type == T || n->type->etype >= TIDEAL) return 0; t = n->type; if(isartificial(n)) return 0; b = basenod(n); // it skips e.g. stores to ... parameter array if(isartificial(b)) return 0; class = b->class; // BUG: we _may_ want to instrument PAUTO sometimes // e.g. if we've got a local variable/method receiver // that has got a pointer inside. Whether it points to // the heap or not is impossible to know at compile time if((class&PHEAP) || class == PPARAMREF || class == PEXTERN || b->op == OINDEX || b->op == ODOTPTR || b->op == OIND || b->op == OXDOT) { hascalls = 0; foreach(n, hascallspred, &hascalls); if(hascalls) { n = detachexpr(n, init); *np = n; } n = treecopy(n); makeaddable(n); if(t->etype == TSTRUCT || isfixedarray(t)) { f = mkcall(wr ? "racewriterange" : "racereadrange", T, init, uintptraddr(n), nodintconst(t->width)); } else f = mkcall(wr ? "racewrite" : "raceread", T, init, uintptraddr(n)); *init = list(*init, f); return 1; } return 0; }
long treestack_pop(Dataptr matrix, Branch *barray, long *root, Treestack *sp) { long val; /* return value */ if (sp->next >= 1){ sp->next--; treecopy(matrix, barray, sp->stack[sp->next].tree); *root = sp->stack[sp->next].root; val = 1; } else{ val = 0; } return val; } /* end treestack_pop() */
long treestack_print(Dataptr matrix, Treestack *sp, FILE *const outfp, Lvb_bool onerandom) { const long d_obj1 = 0L; /* 1st obj. for output trees */ long root; /* root of current tree */ long i; /* loop counter */ long lower; /* lowest index of trees to print */ long upper; /* 1 + upper index of trees to print */ Branch *barray; /* current unpacked tree */ /* "local" dynamic heap memory */ barray = treealloc(matrix); if (onerandom == LVB_TRUE) /* choose one random tree to print */ { lower = randpint(sp->next - 1); upper = lower + 1; } else { lower = 0; upper = sp->next; } for (i = lower; i < upper; i++) { treecopy(matrix, barray, sp->stack[i].tree); if (sp->stack[i].root != d_obj1) lvb_reroot(barray, sp->stack[i].root, d_obj1); root = d_obj1; lvb_treeprint(matrix, outfp, barray, root); } if (fflush(outfp) != 0) crash("file write error when writing best trees"); /* deallocate "local" dynamic heap memory */ free(barray); return upper - lower; /* number of trees printed */ } /* end treestack_print() */
/* Routine to vary the length of all branches by the same factor * and dump the expected information to disk. Since we are altering * the rate of change, we need to include a factor in all the information * calculations*/ void growtree(struct treenode *node_p,FILE *file_p,unsigned int e){ #include "variables.h" int steps,a,b,c; double f_min,f_max,f; struct treenode *tree; /* Code to get the factors from the users*/ printf("Altering length of all branches by same factor\n\n"); printf("Please enter min. factor, max factor and number of points:\n"); do{ printf("\tmin. factor:"); scanf("%lf",&f_min); }while(f_min<=0); do{ printf("\tmax. factor:"); scanf("%lf",&f_max); }while(f_min>=f_max); do{ printf("\tnumber of points:"); scanf("%d",&steps); }while(steps<=0); /* Dump text to file explaining what we are about to do*/ fprintf(file_p,"#Results from Varying length of all branches by factor\n"); fprintf(file_p,"#Factor\t\t\t%s\n",outstring); if(ISMODE(MATRICES)) fprintf(matrix_file_p,"#Matrices from Varying length of all branches by factor\n"); if(sample_file_p!=NULL){ fprintf(sample_file_p,"#Points %d\n",steps); fprintf(sample_file_p,"#Samples from varying length of all branches by factor\n"); } if(ISMODE(PROBS)) fprintf(prob_file_p,"#Probabilities from varying length of all branches by factor\n"); /* Start main loop*/ /* Make two copies of the tree*/ tree2=treecopy(node_p,0); tree=treecopy(node_p,0); /* Calculate what factor we need to include in the calculations*/ for(c=0;c<(steps);c++){ if(steps==1) /* Prevent divide by zero if only one step*/ f=f_min; else f=f_min+c*(f_max-f_min)/(steps-1); factor=f; factor_flag=-1; /* Flag = -1 means that we want to include the * factor on all branches*/ /* Add all the information to one copy from the original tree*/ filltree(node_p,tree,0); /* Change all the length in the tree to the scaled version * The array branch[] currently points to those of 'tree'*/ for(b=0;b<branches;b++){ branch[b]->length[0]=branch[b]->length[0]*f; a=findnode(branch[b]->node[0],branch[b]); (branch[b]->node[0])->length[a]=branch[b]->length[0]; } /* Make copy of the tree with scaled branches*/ filltree(tree,tree2,0); /* Branch[] now points to those in tree2 * Make leaves point to those on tree*/ leaves=0; doleaf(tree,0); printf("Doing factor %E\n",f); /* If we've been asked to print out the intermediate trees, then * dump them to all the open files*/ if(ISMODE(TREES)) print_tree(tree,file_p,0); fprintf(file_p,"%E\n",f); if(ISMODE(MATRICES)){ fprintf(matrix_file_p,"\n#Factor %E\n",f); if(ISMODE(TREES)) print_tree(tree,matrix_file_p,0); } if(ISMODE(VARIANCE)){ fprintf(variance_file_p,"\n#Factor %E\n",f); if(ISMODE(TREES)) print_tree(tree,variance_file_p,0); } if(sample_file_p!=NULL){ fprintf(sample_file_p,"\n#Factor %E\n",f); if(ISMODE(TREES)) print_tree(tree,sample_file_p,0); } if(ISMODE(PROBS)){ fprintf(prob_file_p,"\n#Factor %E\n",f); if(ISMODE(TREES)) print_tree(tree,prob_file_p,0); } det=find_information(tree,tree2,e,factor_flag,factor); /* Possible may want to print out more than one result*/ b=1; if(ISMODE(INDIVIDUAL)) b=individual; if(ISMODE(INDIVIDUAL)){ if(ISMODE(DETINDIV)){ fprintf(file_p,"\t\t\t%E\tD(",det[0]); for(a=0;a<b-1;a++) fprintf(file_p,"%d,",interesting_branches[a]); fprintf(file_p,"%d)\n",interesting_branches[a]); }else for(a=0;a<b;a++) fprintf(file_p,"\t\t\t%E\t%d\n",det[a],interesting_branches[a]); }else fprintf(file_p,"\t\t\t%E\tD\n",det[0]); if(ISMODE(HKY) && NOTMODE(NOKAPPA) && NOTMODE(PERCENTILE)) fprintf(file_p,"\t\t\t%E\tKappa\n",det[b]); free(det); } }
/* Routine to slid one branch of a node along the a branch * The moving node is assumed to be simple!*/ void greasebranch(struct treenode *node_p,FILE *file_p,unsigned int e){ #include "variables.h" int steps,a,b,c; int slippe,to,from,to_root,to_false_root; int sp_case; double f_min,f_max,f,l; extern int root; struct treenode *movingnode,*node_c; struct treenode *tree; /* Make two copies of the tree*/ tree2=treecopy(node_p,0); tree=treecopy(node_p,0); filltree(node_p,tree,0); /* Print out the tree branches and respective numbers*/ printf("\n"); for(a=0;a<branches;a++) printf("Branch %d goes from %s to %s\n",a ,(branch[a]->node[0])->name,branch[a]->name); /* Get the necessary parameters from the user*/ do{ printf("\nWhich branch would you like to move?"); scanf("%d",&slippe); }while(slippe<0 || slippe>branches); do{ printf("\nWhich branch would you like to move branch %d along(towards)?" ,slippe); scanf("%d",&to); printf("\nWhich branch would you like to move branch %d along(away)?" ,slippe); scanf("%d",&from); }while(to<0 || to>branches || from<0 || from>branches); /* Out of the three parameters given, two of them must point * the common node.*/ movingnode=(branch[to]->node[0]==branch[from]->node[0]) ?branch[to]->node[0]:branch[slippe]->node[0]; /* Find which branch in the common node points to each of the * parameter branches.*/ from=findnode(movingnode,branch[from]); to=findnode(movingnode,branch[to]); slippe=findnode(movingnode,branch[slippe]); /* Get the amount of variation from the user*/ printf("Sliding branch leading to %s\n\n",branch[slippe]->name); printf("Please enter min. & max. distance to move and number of points:\n"); do{ printf("\tmin. distance:"); scanf("%lf",&f_min); }while(f_min<=-movingnode->length[from] || f_min>=movingnode->length[to]); do{ printf("\tmax. distance:"); scanf("%lf",&f_max); }while(f_min>=f_max || f_max>=movingnode->length[to]); do{ printf("\tnumber of points:"); scanf("%d",&steps); }while(steps<=0); /* Are we moving the branch towards the (code) root?*/ to_false_root=(to==0)?0:1; /* Work out where root node is relative to movingnode. * Needed to work out whether to increase or decrease branch * lengths when moving node*/ to_root=to_false_root; /* Correct unless we are between the * two roots in the tree */ /* If we have a genetic root...*/ if(ISMODE(ROOTED)){ /* Decide depending on whether the root is floating or not, * which node it refers to*/ node_c=(ISMODE(NODEASROOT))?branch[root]->node[0]:branch[root]; /* Iterate from the genetic root to the code root and set * "to_root" as appropriate. to_root only differs from to_false_root * if we are moving a branch between the two roots*/ while(node_c!=tree){ /* If we reach movingnode without passing either the to or from * node first, then we must have come down on of the other branches * or our root is the movingnode itself. In either case, we can't * keep evolutionary times fixed - problem*/ if(node_c==movingnode){ printf("Moving branch containing root - can't keep evolutionary times fixed\n"); exit(0); } /* We encounter the "to" node first and so must be moving * towards the genetic root*/ if(node_c==movingnode->node[to]){ to_root=0; break; } /* We encounter the from root first and so must be moving * away from the genetic node*/ if(node_c==movingnode->node[from]){ to_root=1; break; } /* Iterate up one step*/ node_c=node_c->node[0]; } /* If the root is on the branch we are moving, bad things * happen (TM) Moving the branch can't be done if evolutionary * times are fixed. * We have deal with the case when root is on the moving bit of * tree but not the false root.*/ if(slippe==0){ /* Decide where the root is depending on whether it is fixed * or floating*/ node_c=(ISMODE(NODEASROOT))?branch[root]->node[0]:branch[root]; a=0; /* We may assume that the code root is on the moving branch of * the tree. If we have to pass through movingnode to get from * the genetic root to the code root then we are fine*/ while(node_c!=tree){ if(node_c==movingnode){ a=1; break; } node_c=node_c->node[0]; } /* One special case if the movingnode is the fixed root*/ if(ISMODE(NODEASROOT) && branch[root]->node[0]==movingnode) a=0; /* If both the code and genetic roots are on the moving section * of tree, complain*/ if(a==0){ printf("Moving branch containing root - can't keep evolutionary" " times fixed\n"); exit(0); } } /* If the root of the tree is on the same branch as we are moving across * then we'll have trouble when we cross it - give warning*/ if(NOTMODE(NODEASROOT)) /* genetic root is floating*/ if(to_root==0) /* we are heading towards it*/ /* Depending on whether we are going away or towards the * code root, see if the genetic root is on the branch we are * moving along*/ if((to_false_root==0 && branch[root]==movingnode) ||(to_false_root==1 && branch[root]->node[0]==movingnode)) fprintf(file_p,"# *** Root in branch moving across. Beware, here be dragons ***\n"); } /* Dump some information to file informing user what we are about * to do*/ fprintf(file_p,"#Results from sliding branch from %s to" " %s along branch from %s to %s\n" ,movingnode->name,(movingnode->node[slippe])->name ,(movingnode->node[from])->name,(movingnode->node[to])->name); fprintf(file_p,"#Distance moved towards %s\t%s\n",(movingnode->node[to])->name,outstring); if(ISMODE(MATRICES)) fprintf(matrix_file_p,"#Matrices from sliding branch from %s to" " %s along branch from %s to %s\n" ,movingnode->name,(movingnode->node[slippe])->name ,(movingnode->node[from])->name,(movingnode->node[to])->name); if(sample_file_p!=NULL){ fprintf(sample_file_p,"#Points %d\n",steps); fprintf(sample_file_p,"#Samples from sliding branch from %s to" " %s along branch from %s to %s\n" ,movingnode->name,(movingnode->node[slippe])->name ,(movingnode->node[from])->name,(movingnode->node[to])->name); } if(ISMODE(PROBS)) fprintf(prob_file_p,"#Probabilities from sliding branch from %s to" " %s along branch from %s to %s\n" ,movingnode->name,(movingnode->node[slippe])->name ,(movingnode->node[from])->name,(movingnode->node[to])->name); /* l is the total length of the "branch" we are moving across*/ l=movingnode->length[to]+movingnode->length[from]; if(steps==1) f=f_min; else f=(f_max-f_min)/(steps-1); /* We aren't changing any rates, so we don't need to apply the * factor to any information (so factor=1)*/ factor=1.0; factor_flag=0; /* Initialise the tree...*/ movingnode->length[to]-=f_min; if(to==0){ b=findnode(movingnode->node[0],movingnode); (movingnode->node[to])->length[b]=movingnode->length[to]; } else (movingnode->node[to])->length[0]=movingnode->length[to]; movingnode->length[from]+=f_min; if(from==0){ b=findnode(movingnode->node[0],movingnode); (movingnode->node[from])->length[b]=movingnode->length[from]; } else (movingnode->node[from])->length[0]=movingnode->length[from]; /* If the tree is rooted, then we must preserve evolutionary * times. This requires adding bits onto any other branches * connected to the moving node, bar the to and from branches.*/ if(ISMODE(ROOTED)){ /* Case moving towards the evolutionary root - all branches * connected to the moving node, bar from and to need to have * the distance added onto them*/ sp_case=(movingnode==tree)?1:0; if(to_root==0){ if(sp_case==1 && to!=0 && from!=0){ b=findnode(movingnode->node[0],movingnode); movingnode->length[0]+=f_min; (movingnode->node[0])->length[b]=movingnode->length[0]; } for(a=sp_case;a<DOODAH && movingnode->node[a]!=NULL;a++) if(a!=to && a!=from){ (movingnode->node[a])->length[0]+=f_min; movingnode->length[a]=(movingnode->node[a])->length[0]; } } /* Else we are moving away from it and all branches connected to * the moving node need the distance subtracted from them. Same * special case as above*/ else{ if(sp_case==1 && to!=0 && from!=0){ b=findnode(movingnode->node[0],movingnode); movingnode->length[0]-=f_min; (movingnode->node[0])->length[b]=movingnode->length[0]; } for(a=sp_case;a<DOODAH && movingnode->node[a]!=NULL;a++) if(a!=to && a!=from){ (movingnode->node[a])->length[0]-=f_min; movingnode->length[a]=(movingnode->node[a])->length[0]; } } } for(c=0;c<steps;c++){ /* Adding new lengths - if any of the markers are zero then * we have to search for the correct pointer in the parent node*/ movingnode->length[to]-=(c!=0)*f; /* Also need to update length of branch that leads to this * one. If to=0 then we must look up the tree*/ if(to==0){ b=findnode(movingnode->node[0],movingnode); (movingnode->node[to])->length[b]=movingnode->length[to]; } else (movingnode->node[to])->length[0]=movingnode->length[to]; movingnode->length[from]+=(c!=0)*f; /* Also need to update length of branch that leads to this * one. If from=0 then we must look up the tree*/ if(from==0){ b=findnode(movingnode->node[0],movingnode); (movingnode->node[from])->length[b]=movingnode->length[from]; } else (movingnode->node[from])->length[0]=movingnode->length[from]; /* If the tree is rooted, then we must preserve evolutionary * times. This requires adding bits onto any other branches * connected to the moving node, bar the to and from branches.*/ if(ISMODE(ROOTED)){ /* Case moving towards the evolutionary root - all branches * connected to the moving node, bar from and to need to have * the distance added onto them*/ sp_case=(movingnode==tree)?1:0; /* Is the movingnode the code root?*/ if(to_root==0){ if(sp_case==1 && to!=0 && from!=0){ b=findnode(movingnode->node[0],movingnode); movingnode->length[0]+=(c!=0)*f; (movingnode->node[0])->length[b]=movingnode->length[0]; } for(a=sp_case;a<DOODAH && movingnode->node[a]!=NULL;a++) if(a!=to && a!=from){ (movingnode->node[a])->length[0]+=(c!=0)*f; movingnode->length[a]=(movingnode->node[a])->length[0]; } } /* Else we are moving away from it and all branches connected to * the moving node need the distance subtracted from them. Same * special case as above*/ else{ if(sp_case==1 && to!=0 && from!=0){ b=findnode(movingnode->node[0],movingnode); movingnode->length[0]-=(c!=0)*f; (movingnode->node[0])->length[b]=movingnode->length[0]; } for(a=sp_case;a<DOODAH && movingnode->node[a]!=NULL;a++) if(a!=to && a!=from){ (movingnode->node[a])->length[0]-=(c!=0)*f; movingnode->length[a]=(movingnode->node[a])->length[0]; } } } /* Fill in second copy of tree from first and update the leaf * array to point to tree*/ filltree(tree,tree2,0); leaves=0; doleaf(tree,0); /* Print a bit of information to all open files*/ printf("Doing distance %E\n",c*f+f_min); if(ISMODE(TREES)) print_tree(tree,file_p,0); fprintf(file_p,"%E\n",c*f+f_min); if(ISMODE(MATRICES)){ fprintf(matrix_file_p,"\n#Distance %E\n",c*f+f_min); if(ISMODE(TREES)) print_tree(tree,matrix_file_p,0); } if(ISMODE(VARIANCE)){ fprintf(variance_file_p,"\n#Distance %E\n",c*f+f_min); if(ISMODE(TREES)) print_tree(tree,variance_file_p,0); } if(sample_file_p!=NULL){ fprintf(sample_file_p,"\n#Distance %E\n",c*f+f_min); if(ISMODE(TREES)) print_tree(tree,sample_file_p,0); } if(ISMODE(PROBS)){ fprintf(prob_file_p,"\n#Distance %E\n",c*f+f_min); if(ISMODE(TREES)) print_tree(tree,prob_file_p,0); } det=find_information(tree,tree2,e,factor_flag,factor); /* Possible may want to print out more than one result*/ b=1; if(ISMODE(INDIVIDUAL)) b=individual; if(ISMODE(INDIVIDUAL)){ if(ISMODE(DETINDIV)){ fprintf(file_p,"\t\t\t%E\tD(",det[0]); for(a=0;a<b-1;a++) fprintf(file_p,"%d,",interesting_branches[a]); fprintf(file_p,"%d)\n",interesting_branches[a]); }else for(a=0;a<b;a++) fprintf(file_p,"\t\t\t%E\t%d\n",det[a],interesting_branches[a]); }else fprintf(file_p,"\t\t\t%E\tD\n",det[0]); if(ISMODE(HKY) && NOTMODE(NOKAPPA) && NOTMODE(PERCENTILE)) fprintf(file_p,"\t\t\t%E\tKappa\n",det[b]); free(det); } }
/* Routine to vary the length of one branch though several * multipliers. This has little meaning when considering a clock-like * (rooted) tree*/ void growbranch(struct treenode *node_p,FILE *file_p,unsigned int e){ #include "variables.h" int steps,a,b,c; int elastic; double f_min,f_max,f; struct treenode *tree; /* Test to see whether tree is rooted - changing branch * length in unrooted trees doesn't have much experimental * meaning */ if(((mode&4)|(mode&32))!=0) printf("\a\n**Changing branch length in a rooted tree doesn't" " have meaning\n**in an experimental design problem!\n\n\a"); /* Make two copies of the tree*/ tree2=treecopy(node_p,0); tree=treecopy(node_p,0); /* Fill in the first*/ filltree(node_p,tree,0); /* Choose branch to stretch - better be elastic*/ printf("\n"); for(a=0;a<branches;a++) printf("Branch %d goes from %s to %s\n",a ,(branch[a]->node[0])->name,branch[a]->name); do{ printf("\nWhich branch would you like to alter?"); scanf("%d",&elastic); }while(elastic<0 || elastic>branches); /* Get length scaling factors from user*/ printf("Altering length of a branch leading to" " %s by a varying factor\n\n",branch[elastic]->name); printf("Please enter min. factor, max factor and number of points:\n"); do{ printf("\tmin. factor:"); scanf("%lf",&f_min); }while(f_min<=0); do{ printf("\tmax. factor:"); scanf("%lf",&f_max); }while(f_min>=f_max); do{ printf("\tnumber of points:"); scanf("%d",&steps); }while(steps<=0); /* Dump the necessary information to file*/ fprintf(file_p,"#Results from varying length of branch" " between %s and %s by factor\n" ,(branch[elastic]->node[0])->name,branch[elastic]->name); fprintf(file_p,"#Factor\t\t\t%s\n",outstring); if(ISMODE(MATRICES)) fprintf(matrix_file_p,"#Matrices from varying length of branch" " between %s and %s by factor\n" ,(branch[elastic]->node[0])->name,branch[elastic]->name); if(sample_file_p!=NULL){ fprintf(sample_file_p,"#Points %d\n",steps); fprintf(sample_file_p,"#Samples from varying length of branch" " between %s and %s by factor\n" ,(branch[elastic]->node[0])->name,branch[elastic]->name); } if(ISMODE(PROBS)) fprintf(prob_file_p,"#Probabilities from varying length of branch" " between %s and %s by factor\n" ,(branch[elastic]->node[0])->name,branch[elastic]->name); /* Main loop to stretch the branch*/ for(c=0;c<steps;c++){ /* Calculate the factor wanted and set the flag - we only * want to apply the factor to one of the informations this * time*/ if(steps==1) f=f_min; else f=f_min+c*(f_max-f_min)/(steps-1); factor=f; factor_flag=elastic; /* Fill in first copy from the original*/ filltree(node_p,tree,0); /* Branch[] points to those of 'tree' * Change length of the branch by factor - need to find the node * that points from the other side of the branch.*/ branch[elastic]->length[0]=branch[elastic]->length[0]*f; a=findnode(branch[elastic]->node[0],branch[elastic]); (branch[elastic]->node[0])->length[a]=branch[elastic]->length[0]; /* Fill in the second copy from the first (with the new branch * length and set all the leaves to point to "tree"*/ filltree(tree,tree2,0); leaves=0; doleaf(tree,0); printf("Doing Factor %E\n",f); /* If we are printing out the intermediate trees, then dump them * to every file*/ if(ISMODE(TREES)) print_tree(tree,file_p,0); fprintf(file_p,"%E\n",f); if(ISMODE(MATRICES)){ fprintf(matrix_file_p,"\n#Factor %E\n",f); if(ISMODE(TREES)) print_tree(tree,matrix_file_p,0); } if(ISMODE(VARIANCE)){ fprintf(variance_file_p,"\n#Factor %E\n",f); if(ISMODE(TREES)) print_tree(tree,variance_file_p,0); } if(sample_file_p!=NULL){ fprintf(sample_file_p,"\n#Factor %E\n",f); if(ISMODE(TREES)) print_tree(tree,sample_file_p,0); } if(ISMODE(PROBS)){ fprintf(prob_file_p,"\n#Factor %E\n",f); if(ISMODE(TREES)) print_tree(tree,prob_file_p,0); } det=find_information(tree,tree2,e,factor_flag,factor); /* Possible may want to print out more than one result*/ b=1; if(ISMODE(INDIVIDUAL)) b=individual; if(ISMODE(INDIVIDUAL)){ if(ISMODE(DETINDIV)){ fprintf(file_p,"\t\t\t%E\tD(",det[0]); for(a=0;a<b-1;a++) fprintf(file_p,"%d,",interesting_branches[a]); fprintf(file_p,"%d)\n",interesting_branches[a]); }else for(a=0;a<b;a++) fprintf(file_p,"\t\t\t%E\t%d\n",det[a],interesting_branches[a]); }else fprintf(file_p,"\t\t\t%E\tD\n",det[0]); if(ISMODE(HKY) && NOTMODE(NOKAPPA) && NOTMODE(PERCENTILE)) fprintf(file_p,"\t\t\t%E\tKappa\n",det[b]); free(det); } }
long anneal(Treestack *bstackp, const Branch *const inittree, long root, const double t0, const double t1, const long maxaccept, const long maxpropose, const long maxfail, FILE *const lenfp, unsigned char **bmat, long m, long n, const long *weights, long *current_iter, Lvb_bool log_progress) /* seek parsimonious tree from initial tree in inittree (of root root) * with initial temperature t0, and subsequent temperatures obtained by * multiplying the current temperature by (t1 / t0) ** n * t0 where n is * the ordinal number of this temperature, after at least maxaccept changes * have been accepted or maxpropose changes have been proposed, whichever is * sooner; * return the length of the best tree(s) found after maxfail consecutive * temperatures have led to no new accepted solution; * lenfp is for output of current tree length and associated details; * *current_iter should give the iteration number at the start of this call and * will be used in any statistics sent to lenfp, and will be updated on * return */ { long accepted = 0; /* changes accespted */ Lvb_bool dect; /* should decrease temperature */ double deltah; /* change in energy (1 - C.I.) */ long deltalen; /* change in length with new tree */ long failedcnt = 0; /* "failed count" for temperatures */ long iter = 0; /* iteration of mutate/evaluate loop */ long len; /* length of current tree */ long prev_len = UNSET; /* length of previous tree */ long lenbest; /* bet length found so far */ long lendash; /* length of proposed new tree */ long lenmin; /* minimum length for any tree */ double ln_t; /* ln(current temperature) */ long t_n = 0; /* ordinal number of current temperature */ Lvb_bool newtree; /* accepted a new configuration */ double pacc; /* prob. of accepting new config. */ Lvb_bool probaccd; /* have accepted based on Pacc */ long proposed = 0; /* trees proposed */ double r_lenmin; /* minimum length for any tree */ long rootdash; /* root of new configuration */ double t = t0; /* current temperature */ double t1_to_t0; /* T1:T0 ratio */ Branch *x; /* current configuration */ Branch *xdash; /* proposed new configuration */ extern Dataptr matrix; /* data matrix */ /* "local" dynamic heap memory */ x = treealloc(brcnt(matrix->n), matrix->m); xdash = treealloc(brcnt(matrix->n), matrix->m); treecopy(x, inittree); /* current configuration */ len = getplen(x, root, m, n, weights); dect = LVB_FALSE; /* made LVB_TRUE as necessary at end of loop */ /* if t1_to_t0 is going to be very small, set it to zero without * calculating it, to avoid underflow. Use this relation: * if T1 / T0 < eps, * ln (T1/T0) < ln eps * i.e., * ln T1 - ln T0 < ln eps */ lvb_assert ((t0 >= LVB_EPS) && (t1 >= LVB_EPS) && (t1 <= t0) && (t0 <= 1.0)); if (log_wrapper(t1) - log_wrapper(t0) < log_wrapper(LVB_EPS)) t1_to_t0 = 0.0; else t1_to_t0 = t1 / t0; lenbest = len; treestack_push(bstackp, inittree, root); /* init. tree initially best */ if ((log_progress == LVB_TRUE) && (*current_iter == 0)) { fprintf(lenfp, "\nRearrangement: Length:\n"); } lenmin = getminlen(matrix); r_lenmin = (double) lenmin; while (1) { if ((log_progress == LVB_TRUE) && ((len != prev_len) || ((*current_iter % STAT_LOG_INTERVAL) == 0))) { lenlog(lenfp, *current_iter, len); } prev_len = len; *current_iter += 1; /* occasionally re-root, to prevent influence from root position */ if ((*current_iter % REROOT_INTERVAL) == 0) root = arbreroot(x, root); lvb_assert(t > DBL_EPSILON); newtree = LVB_FALSE; probaccd = LVB_FALSE; /* mutation: alternate between the two mutation functions */ if (iter % 2) { rootdash = root; mutate_spr(xdash, x, root); /* global change */ } else { rootdash = root; mutate_nni(xdash, x, root); /* local change */ } lendash = getplen(xdash, rootdash, m, n, weights); lvb_assert (lendash >= 1L); deltalen = lendash - len; deltah = (r_lenmin / (double) len) - (r_lenmin / (double) lendash); if (deltah > 1.0) /* getminlen() problem with ambiguous sites */ deltah = 1.0; if (deltalen <= 0) /* accept the change */ { if (lendash <= lenbest) /* store tree if new */ { if (lendash < lenbest) /* very best so far */ treestack_clear(bstackp); /* discard old bests */ if (treestack_push(bstackp, xdash, rootdash) == 1) newtree = LVB_TRUE; /* new */ } /* update current tree and its stats */ prev_len = len; len = lendash; treeswap(&x, &root, &xdash, &rootdash); if (lendash < lenbest) /* very best so far */ lenbest = lendash; } else /* poss. accept change for the worse */ { /* Mathematically, * Pacc = e ** (-1/T * deltaH) * therefore ln Pacc = -1/T * deltaH * * Computationally, if Pacc is going to be small, we * can assume Pacc is 0 without actually working it * out. * i.e., * if ln Pacc < ln eps, let Pacc = 0 * substituting, * if -deltaH / T < ln eps, let Pacc = 0 * rearranging, * if -deltaH < T * ln eps, let Pacc = 0 * This lets us work out whether Pacc will be very * close to zero without dividing anything by T. This * should prevent overflow. Since T is no less * than eps and ln eps is going to have greater * magnitude than eps, underflow when calculating * T * ln eps is not possible. */ if (-deltah < t * log_wrapper(LVB_EPS)) { pacc = 0.0; /* Call uni() even though its not required. It * would have been called in LVB 1.0A, so this * helps make results identical to results with * that version. */ (void) uni(); } else /* possibly accept the change */ { pacc = exp_wrapper(-deltah/t); if (uni() < pacc) /* do accept the change */ { probaccd = LVB_TRUE; treeswap(&x, &root, &xdash, &rootdash); } } if (probaccd == LVB_TRUE) { prev_len = len; len = lendash; } } proposed++; if (newtree == LVB_TRUE) accepted++; /* decide whether to reduce temperature */ if (accepted >= maxaccept) /* enough new trees */ { failedcnt = 0; /* this temperature a 'success' */ dect = LVB_TRUE; } else if (proposed >= maxpropose) /* enough proposals */ { failedcnt++; if (failedcnt >= maxfail) /* system frozen */ break; /* end of cooling */ else /* decrease temp. */ dect = LVB_TRUE; } if (dect == LVB_TRUE) { t_n++; /* originally n is 0 */ /* near the start of the function we ensure t1_to_t0 is * either zero or no less than LVB_EPS */ if (t1_to_t0 < LVB_EPS) t = LVB_EPS; else { ln_t = ((double) t_n) * log_wrapper(t1_to_t0) + log_wrapper(t0); if (ln_t < log_wrapper(LVB_EPS)) t = LVB_EPS; else t = pow_wrapper(t1_to_t0, (double) t_n) * t0; } proposed = 0; accepted = 0; dect = LVB_FALSE; } iter++; } /* free "local" dynamic heap memory */ free(x); free(xdash); return lenbest; } /* end anneal() */