void TreeRandomizer::stepwiseAddition(pllInstance *tr, partitionList *pr, nodeptr p, nodeptr q, ParallelSetup& pl)
{            
  nodeptr 
    r = q->back;

  unsigned int 
    mp;
  
  int 
    counter = 4;
  
  p->next->back = q;
  q->back = p->next;

  p->next->next->back = r;
  r->back = p->next->next;
   
  computeTraversalInfoParsimony(p, tr->ti, &counter, tr->mxtips, PLL_FALSE);              
  tr->ti[0] = counter;
  tr->ti[1] = p->number;
  tr->ti[2] = p->back->number;
    
  mp = evaluateParsimonyIterativeFast(tr, pr);

  auto result = std::vector<nat>{mp}; 
  // std::cout <<  "my score was " << mp << std::endl; 
  result = pl.getChainComm().allReduce(result);
  mp = result.at(0); 
  // std::cout << "after allreduce "<< mp << std::endl; 
  
  
  if(mp < tr->bestParsimony)
    {    
      tr->bestParsimony = mp;
      tr->insertNode = q;     
    }
 
  q->back = r;
  r->back = q;
   
  if(q->number > tr->mxtips
#if 0 
     && tr->parsimonyScore[q->number] > 0
#endif
     )
    {         
      stepwiseAddition(tr, pr, p, q->next->back, pl);
      stepwiseAddition(tr, pr, p, q->next->next->back, pl);
    }
}
static void stepwiseAddition(tree *tr, nodeptr p, nodeptr q)
{            
  nodeptr 
    r = q->back;

  unsigned int 
    mp;
  
  int 
    counter = 4;
  
  p->next->back = q;
  q->back = p->next;

  p->next->next->back = r;
  r->back = p->next->next;
   
  computeTraversalInfoParsimony(p, tr->ti, &counter, tr->mxtips, FALSE);              
  tr->ti[0] = counter;
  tr->ti[1] = p->number;
  tr->ti[2] = p->back->number;
    
  mp = evaluateParsimonyIterativeFast(tr);
  
  if(mp < tr->bestParsimony)
    {    
      tr->bestParsimony = mp;
      tr->insertNode = q;     
    }
 
  q->back = r;
  r->back = q;
   
  if(q->number > tr->mxtips && tr->parsimonyScore[q->number] > 0)
    {	      
      stepwiseAddition(tr, p, q->next->back);	      
      stepwiseAddition(tr, p, q->next->next->back);              	     
    }
}
void pllMakeParsimonyTreeFast(tree *tr)
{   
  nodeptr  
    p, 
    f;    

  int 
    i, 
    nextsp,
    *perm        = (int *)malloc((size_t)(tr->mxtips + 1) * sizeof(int));  

  unsigned int 
    randomMP, 
    startMP;         
  
  assert(!tr->constrained);

  makePermutationFast(perm, tr->mxtips, tr);
  
  tr->ntips = 0;    
  
  tr->nextnode = tr->mxtips + 1;       
  
  buildSimpleTree(tr, perm[1], perm[2], perm[3]);      
  
  f = tr->start;       
  
  while(tr->ntips < tr->mxtips) 
    {	
      nodeptr q;
      
      tr->bestParsimony = INT_MAX;
      nextsp = ++(tr->ntips);             
      p = tr->nodep[perm[nextsp]];                 
      q = tr->nodep[(tr->nextnode)++];
      p->back = q;
      q->back = p;
        
      if(tr->grouped)
	{
	  int 
	    number = p->back->number;	  	 

	  tr->constraintVector[number] = -9;
	}
          
      stepwiseAddition(tr, q, f->back);      	  	 
      
      {
	nodeptr	  
	  r = tr->insertNode->back;
	
	int counter = 4;
	
	hookupDefault(q->next,       tr->insertNode, tr->numBranches);
	hookupDefault(q->next->next, r, tr->numBranches);
	
	computeTraversalInfoParsimony(q, tr->ti, &counter, tr->mxtips, FALSE);              
	tr->ti[0] = counter;
	
	newviewParsimonyIterativeFast(tr);	
      }
    }    
  
  printf("ADD: %d\n", tr->bestParsimony); 
  
  nodeRectifierPars(tr);
  
  randomMP = tr->bestParsimony;        
  
  do
    {
      startMP = randomMP;
      nodeRectifierPars(tr);
      for(i = 1; i <= tr->mxtips + tr->mxtips - 2; i++)
	{
	  rearrangeParsimony(tr, tr->nodep[i], 1, 20, FALSE);
	  if(tr->bestParsimony < randomMP)
	    {		
	      restoreTreeRearrangeParsimony(tr);
	      randomMP = tr->bestParsimony;
	    }
	}      		  	   
    }
  while(randomMP < startMP);
  
  printf("OPT: %d\n", tr->bestParsimony);
} 
void TreeRandomizer::createStepwiseAdditionParsimonyTree(TreeAln &traln, ParallelSetup& pl )
{   
  auto *tr = &(traln.getTrHandle()); 
  auto *pr = &(traln.getPartitionsHandle()); 

  assert(tr->fastParsimony == PLL_FALSE); 
    
  nodeptr  
    p, 
    f;    

  int 
    nextsp; 
  auto perm = std::vector<int>(tr->mxtips+1,  0); 
       
  assert(!tr->constrained);

  makePermutationFast(perm.data(), tr->mxtips, tr);
  
  tr->ntips = 0;    
  
  tr->nextnode = tr->mxtips + 1;       
  
  buildSimpleTree(tr, pr, perm[1], perm[2], perm[3]);
  
  f = tr->start;       
  
  while(tr->ntips < tr->mxtips) 
    {   
      nodeptr q;
      
      tr->bestParsimony = std::numeric_limits<nat>::max();
      nextsp = ++(tr->ntips);             
      p = tr->nodep[perm[nextsp]];                 
      q = tr->nodep[(tr->nextnode)++];
      p->back = q;
      q->back = p;
        
      if(tr->grouped)
        {
          int 
            number = p->back->number;            

          tr->constraintVector[number] = -9;
        }
          
      stepwiseAddition(tr, pr, q, f->back, pl);
      
      // std::cout <<  SyncOut() << "bestPars: "<< tr->bestParsimony << std::endl; 
      
      {
        nodeptr   
          r = tr->insertNode->back;
        
        int counter = 4;
        
        hookupDefault(q->next,       tr->insertNode);
        hookupDefault(q->next->next, r);
        
        computeTraversalInfoParsimony(q, tr->ti, &counter, tr->mxtips, PLL_FALSE);              
        tr->ti[0] = counter;
        
        newviewParsimonyIterativeFast(tr, pr);
      }
    }    
}