#include <stack>
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <string>
#include <sstream>
#include "PhylogenyTreeBasic.h"
#include "Utils3.h"
#include "Utils4.h"

// ***************************************************************************
// The following code is largely based on Gusfield's 1991 Paper
// ***************************************************************************
extern void OutputQuotedString(ofstream &outFile, const char *buf);


string GetStringFromId(int id)
{
	char buf[100];
	snprintf( buf,100, "%d", id );
	return buf;
}


int GetNewickNumLeaves(const string &strNewick, char chSepLeft, char chSepRight, char midSep )
{
	// the number of leaves of newick is equal to the number of separator char plus one
	int res = 0;
	bool fCount = false;	// only count when seeing left sep (
	for(int i=0; i<(int)strNewick.length(); ++i)
	{
		if( strNewick[i] == chSepLeft)
		{
			fCount = true;
		}
		else if( strNewick[i] == chSepRight)
		{
			if( fCount == true)
			{
				// add the last one
				res ++;
			}

			fCount = false;
		}
		else if( strNewick[i] == midSep  )
		{
			if( fCount == true )
			{
				res ++;
			}
			else
			{
				fCount = true;
			}
		}
	}
	return res;
}

void GetTaxaFromNWStr( const string &strNewick, set<string> &setTaxa )
{
    PhylogenyTreeBasic phtree;
    phtree.ConsOnNewick( strNewick );
    string strNW2;
    phtree.ConsNewick(strNW2);
cout << "GetTaxaFromNWStr: strNW2: " << strNW2 << endl;
    string strNewickTrim = strNW2;
    for(int i=0; i<strNewickTrim.length(); ++i)
    {
        char ch = strNewickTrim[i];
        if( ch == '(' || ch == ')' || ch == ',' || ch == ';' )
        {
            strNewickTrim[i] = ' ';
        }
        if( ch == ':')
        {
            throw string("GetTaxaFromNWStr: branch length is not supported yet");
        }
    }
    setTaxa.clear();
    std::istringstream iss(strNewickTrim);
    string strTax;
    while( iss >> strTax )
    {
        setTaxa.insert(strTax);
cout << "strTax: " << strTax << endl;
    }
}

bool GetTripleType( TreeNode *pn1,  TreeNode *pn2, TreeNode *pn3, pair<pair<TreeNode *, TreeNode *>, TreeNode *> &triple )
{
	TreeNode *pmrca12 = pn1->GetMRCA(pn2);
	TreeNode *pmrca13 = pn1->GetMRCA(pn3);
	TreeNode *pmrca23 = pn2->GetMRCA(pn3);
	// 
	int dummy;
	if( pmrca13 != pmrca12)
	{
		if(  pmrca13->IsAncesterOf(pmrca12, dummy) == true )
		{
			triple.first.first = pn1;
			triple.first.second = pn2;
			triple.second = pn3;
			return true;
		}
		else if( pmrca12->IsAncesterOf(pmrca13, dummy) == true )
		{
			triple.first.first = pn1;
			triple.first.second = pn3;
			triple.second = pn2;
			return true;
		}
		else
		{
			YW_ASSERT_INFO(false, "Impossible");
		}
	}
	//if( pmrca23 != pmrca12 &&  pmrca12->IsAncesterOf(pmrca23, dummy) == true )
	else if( pmrca23 != pmrca12 )
	{
		triple.first.first = pn1;
		triple.first.second = pn2;
		triple.second = pn3;
		return true;
	}
	// triple not found
	return false;
}

void GetAllTriplesIntLabels(PhylogenyTreeBasic *pTree, set<pair<pair<int,int>,int> > &setTriples)
{
    // get all triples in the form of ((a,b),c) where a,b,c are int-labels of the leaves
    // and a <= b
    // get all leaves
    vector<TreeNode *> listAllLeaves;
    pTree->GetAllLeafNodes(listAllLeaves);
    for(unsigned int i=0; i<listAllLeaves.size(); ++i)
    {
        for(unsigned int j=i+1; j<listAllLeaves.size(); ++j)
        {
            for(unsigned int k=j+1; k<listAllLeaves.size(); ++k)
            {
                //
                pair<pair<TreeNode *, TreeNode *>, TreeNode *> triple;
                if( GetTripleType(listAllLeaves[i], listAllLeaves[j], listAllLeaves[k], triple) )
                {
                    pair<int,int> pp(triple.first.first->GetIntLabel(), triple.first.second->GetIntLabel());
                    OrderInt(pp.first, pp.second);
                    pair<pair<int,int>,int> pp2(pp, triple.second->GetIntLabel());
                    setTriples.insert(pp2);
                }
            }
        }
    }
}

// different from Marginal tree, we allow mulfurcating trees here
// this can be convenient in some cases
bool ReadinPhyloTreesNewick( ifstream &inFile, int numLeaves, vector<PhylogenyTreeBasic *> &treePtrList, TaxaMapper *pTMapper)
{
	// NOTE: RETURN TRUE IF NO LABEL ADJUSTMENT IS DONE
	// RETURN FALSE IF WE SWITCHED LABEL BY DECREASING BY ONE
	// figure out leave num
	bool fNoChange = true;
	//int nLvs = numLeaves;
	
	// read marginal trees in newick format
	// here there is no preamble, one line per tree
	while( inFile.eof() == false )
	{
        // ensure the first char is '('; otherwise stop
        char ch;
        inFile >> ch;
        inFile.putback(ch);
        if( ch != '(' )
        {
            break;
        }
        
		string treeNewick;
		inFile >> treeNewick;
		if( treeNewick.size() == 0 )
		{
			break;
		}
//cout << "newick tree = " << treeNewick << endl;

//#if 0
		// update numleaves
		multiset<string> setLabels;
		NewickUtils :: RetrieveLabelSet( treeNewick, setLabels);
#if 0
for(multiset<string> :: iterator it22 = setLabels.begin(); it22 != setLabels.end(); ++it22)
{
cout << "Label found: " << *it22 << endl;
}
#endif
		//nLvs = setLabels.size();
//#endif
		//
		PhylogenyTreeBasic *pphTree = new PhylogenyTreeBasic;
		//if( fDup == false )
		//{
		pphTree->ConsOnNewick(treeNewick, -1, false, pTMapper);
//cout << "Done phylogenetic tree construction...\n";
//pphTree->OutputGML("tmp.gml");
		//}
		//else
		//{
		//	phTree.ConsOnNewickDupLabels(treeNewick, pTMapper);
		//}

		if( pTMapper != NULL)
		{
			pTMapper->SetInitialized(true);
		}
//string strTr;
//pphTree->ConsNewick(strTr);
//cout << "After reconstruction: strTr = " << strTr << endl;
		//see if zero is in, if not, must have 1 and decrease by 1
		set<int> lvids;
		pphTree->GetLeaveIds(lvids);
//cout << "lvids : ";
//DumpIntSet( lvids );
		int idInternal = lvids.size();
		YW_ASSERT_INFO( lvids.find(0) != lvids.end(), "Must adjust leaf label first (to start with 0)" );
		
		//	YW_ASSERT_INFO( lvids.find(1) != lvids.end(), "Wrong" );

		// decrease by one
		PhylogenyTreeIterator itorTree(*pphTree);
		itorTree.Init();
		//pphTree->InitPostorderWalk();
		while(itorTree.IsDone() == false)
		{
//				TreeNode *pn = pphTree->NextPostorderWalk( ) ;
			TreeNode *pn = itorTree.GetCurrNode() ;
			itorTree.Next();
			if( pn == NULL)
			{
				break;      // done with all nodes
			}
			if( pn->IsLeaf() == false )
			{
				pn->SetID( idInternal++ );
			}
		}

			// mark the change
		//	fNoChange = false;

		vector<int> nidsList, nparsList;
		pphTree->GetNodeParInfo(nidsList, nparsList);
		//phTree.GetNodeParInfoNew(nidsList, nparsList);
		//phTree.GetNodeParInfo(nidsList, nparsList);
		//if( nLvs <= 0 )
		//{
//string strTrNW;
//pphTree->ConsNewick(strTrNW);
//cout << "strTrNW: " << strTrNW << endl;
        treePtrList.push_back( pphTree );
//cout << "Newick format of this marginal tree: ";
//cout << tree.GetNewick() << endl;
	}
	return fNoChange;
}

// different from Marginal tree, we allow mulfurcating trees here
// this can be convenient in some cases
// YW: don't require taxa start from 0
bool ReadinPhyloTreesNewick2( ifstream &inFile, int numLeaves, vector<PhylogenyTreeBasic *> &treePtrList, TaxaMapper *pTMapper)
{
    // NOTE: RETURN TRUE IF NO LABEL ADJUSTMENT IS DONE
    // RETURN FALSE IF WE SWITCHED LABEL BY DECREASING BY ONE
    // figure out leave num
    bool fNoChange = true;
    //int nLvs = numLeaves;
    
    // read marginal trees in newick format
    // here there is no preamble, one line per tree
    while( inFile.eof() == false )
    {
        // ensure the first char is '('; otherwise stop
        char ch;
        inFile >> ch;
        inFile.putback(ch);
        if( ch != '(' )
        {
            break;
        }
        
        string treeNewick;
        inFile >> treeNewick;
        if( treeNewick.size() == 0 )
        {
            break;
        }
        //cout << "newick tree = " << treeNewick << endl;
        
        //#if 0
        // update numleaves
        multiset<string> setLabels;
        NewickUtils :: RetrieveLabelSet( treeNewick, setLabels);
#if 0
        for(multiset<string> :: iterator it22 = setLabels.begin(); it22 != setLabels.end(); ++it22)
        {
            cout << "Label found: " << *it22 << endl;
        }
#endif
        //nLvs = setLabels.size();
        //#endif
        //
        PhylogenyTreeBasic *pphTree = new PhylogenyTreeBasic;
        //if( fDup == false )
        //{
        pphTree->ConsOnNewick(treeNewick, -1, false, pTMapper);
        //cout << "Done phylogenetic tree construction...\n";
        //pphTree->OutputGML("tmp.gml");
        //}
        //else
        //{
        //	phTree.ConsOnNewickDupLabels(treeNewick, pTMapper);
        //}
        
        if( pTMapper != NULL)
        {
            pTMapper->SetInitialized(true);
        }
        //string strTr;
        //pphTree->ConsNewick(strTr);
        //cout << "After reconstruction: strTr = " << strTr << endl;
        //see if zero is in, if not, must have 1 and decrease by 1
        set<int> lvids;
        pphTree->GetLeaveIds(lvids);
        //cout << "lvids : ";
        //DumpIntSet( lvids );
        int idInternal = lvids.size();
        //YW_ASSERT_INFO( lvids.find(0) != lvids.end(), "Must adjust leaf label first (to start with 0)" );
        
        //	YW_ASSERT_INFO( lvids.find(1) != lvids.end(), "Wrong" );
        
        // decrease by one
        PhylogenyTreeIterator itorTree(*pphTree);
        itorTree.Init();
        //pphTree->InitPostorderWalk();
        while(itorTree.IsDone() == false)
        {
            //				TreeNode *pn = pphTree->NextPostorderWalk( ) ;
            TreeNode *pn = itorTree.GetCurrNode() ;
            itorTree.Next();
            if( pn == NULL)
            {
                break;      // done with all nodes
            }
            if( pn->IsLeaf() == false )
            {
                pn->SetID( idInternal++ );
            }
        }
        
        // mark the change
        //	fNoChange = false;
        
        //vector<int> nidsList, nparsList;
        //pphTree->GetNodeParInfo(nidsList, nparsList);
        //phTree.GetNodeParInfoNew(nidsList, nparsList);
        //phTree.GetNodeParInfo(nidsList, nparsList);
        //if( nLvs <= 0 )
        //{
        //string strTrNW;
        //pphTree->ConsNewick(strTrNW);
        //cout << "strTrNW: " << strTrNW << endl;
        treePtrList.push_back( pphTree );
        //cout << "Newick format of this marginal tree: ";
        //cout << tree.GetNewick() << endl;
    }
    return fNoChange;
}

// create a random tree
void InitRandomTree(PhylogenyTreeBasic &treeToInit, int numTaxa, int rndSeed )
{
    //
    if( rndSeed >= 0 )
    {
        InitRandom( rndSeed );
    }
    // create leaves first
    int idToUseNext = 0;
    vector<TreeNode *> listActiveNodes;
    for(int i=0; i<numTaxa; ++i)
    {
        //
        TreeNode *pLeaf = new TreeNode( idToUseNext++);
        // label it
        pLeaf->SetLabel( GetStringFromId( i ) );
        listActiveNodes.push_back( pLeaf );
    }
    // now create random coalescence
    while( listActiveNodes.size() > 1 )
    {
        // get two random nodes and coalesce them
        int rndpos1 = (int)( listActiveNodes.size()* GetRandFraction());
        YW_ASSERT_INFO( rndpos1 < (int)listActiveNodes.size(), "overflow");
        TreeNode *node1 = listActiveNodes[rndpos1];
        RemoveVecElementAt( listActiveNodes, rndpos1 );
        int rndpos2 = (int)( listActiveNodes.size()* GetRandFraction());
        YW_ASSERT_INFO( rndpos2 < (int)listActiveNodes.size(), "overflow");
        TreeNode *node2 = listActiveNodes[rndpos2];
        RemoveVecElementAt( listActiveNodes, rndpos2 );
        //
        TreeNode *pnodeNew = new TreeNode(idToUseNext++);
        vector<int> listEmpty;
        pnodeNew->AddChild(node1,listEmpty);
        pnodeNew->AddChild(node2,listEmpty);
        // add this node to list of active nodes
        listActiveNodes.push_back( pnodeNew );
    }
    // now here is the root
    YW_ASSERT_INFO(listActiveNodes.size() == 1, "Only one root");
    treeToInit.SetRoot( listActiveNodes[0]);
}

void CreatePhyTreeWithRootedSplits( PhylogenyTreeBasic &treeToProc, int numTaxa, const set< set<int> > &setGivenSplits )
{
    // create a phy tree with the given rooted splits
    // ASSUME: taxa starts from 0 to numTaxa-1
    // result can be a non-binary tree
    // first order them
    vector< set<set<int> > > listGivenSplits( numTaxa+1 );
    for( set<set<int> > :: const_iterator it = setGivenSplits.begin(); it != setGivenSplits.end(); ++it )
    {
        int sz = it->size();
        listGivenSplits[sz].insert(*it);
    }
    // if the whole set is not in, add it so that we have a single lin in the end
    if( listGivenSplits[numTaxa].size() == 0 )
    {
        //
        set<int> sall;
        PopulateSetWithInterval(sall, 0, numTaxa-1);
        listGivenSplits[numTaxa].insert( sall );
    }
#if 0
cout << "Set of given splits: ";
for(int i=0; i<(int)listGivenSplits.size(); ++i)
{
if( listGivenSplits[i].size() > 0 )
{
for( set<set<int> > :: iterator it = listGivenSplits[i].begin(); it != listGivenSplits[i].end(); ++it)
{
DumpIntSet( *it );
}
}
}
#endif
    
    // active list of lineages indexed by their set
    map< set<int>, TreeNode *> mapActiveLins;
    // initially all the leaf lins
    int idToUse = 0;
    for(int i=0; i<numTaxa; ++i)
    {
        TreeNode *pLeaf = new TreeNode(idToUse++);
        set<int> sint;
        sint.insert(i);
        string strLbl = GetStringFromId(i);
        pLeaf->SetLabel( strLbl );
        mapActiveLins.insert( map< set<int>, TreeNode *> :: value_type( sint, pLeaf ) );
    }
    // now scan through the entire list
    for(int k=2; k<(int)listGivenSplits.size(); ++k)
    {
        // start from 2 so that avoid trivial sets
        if( listGivenSplits[k].size() == 0 )
        {
            continue;
        }
        // for each input list, find those lins that is contained within the clusters
        for( set<set<int> > :: iterator it2 = listGivenSplits[k].begin(); it2 != listGivenSplits[k].end(); ++it2)
        {
            // each subset corresponds to a new internal node
            TreeNode *pnode = new TreeNode(idToUse++);
            
//cout << "list of active lins: ";
//for( map< set<int>, TreeNode *> :: iterator iggg = mapActiveLins.begin(); iggg != mapActiveLins.end(); ++iggg )
//{
//    DumpIntSet( iggg->first);
//}
//cout << "Considering given split: ";
//DumpIntSet( *it2 );
            // find the proper node in the previous set
            set< set<int> > setMatached;
            int szTot = 0;
            for( map< set<int>, TreeNode *> :: iterator it3= mapActiveLins.begin(); it3 != mapActiveLins.end(); ++it3 )
            {
                //
//cout <<  "treat this active lineage: ";
//DumpIntSet( it3->first );
                if( IsSetContainer( *it2, it3->first ) == true )
                {
//cout << "yes, continer!\n";
                    //
                    setMatached.insert( it3->first );
                    szTot += it3->first.size();
                    //
                    vector<int> sempty;
                    pnode->AddChild( it3->second, sempty );
                }
            }
            YW_ASSERT_INFO( szTot == (int)it2->size(), "Size: mismatch1" );
            // remove the old ones and add the newly created one
            for( set< set<int> > :: iterator it4 = setMatached.begin(); it4 != setMatached.end(); ++it4 )
            {
                mapActiveLins.erase( *it4 );
            }
            mapActiveLins.insert( map< set<int>, TreeNode *> :: value_type( *it2, pnode ) );
        }
    }
    YW_ASSERT_INFO( mapActiveLins.size() == 1, "Wrong: must have only a single lineage left" );
    treeToProc.SetRoot( mapActiveLins.begin()->second );
    
//string strNW;
//treeToProc.ConsNewick(strNW);
//cout << "Result of createtreebyrootedplits: " << strNW << endl;
//cout << "SetGivenSplits: \n";
//for(set<set<int> > :: iterator it = setGivenSplits.begin(); it != setGivenSplits.end(); ++it)
//{
//DumpIntSet( *it);
//}
//cout << "numTaxa: " << numTaxa << endl;
}

void CreatePhyTreeSubsetTaxa( PhylogenyTreeBasic &treeIn, const set<int> &setTaxa, PhylogenyTreeBasic &treeSub )
{
//cout << "CreatePhyTreeSubsetTaxa: setTaxa: ";
//DumpIntSet(setTaxa);
    //
    set<string> setLabels;
    // loop over all leaves to find those taxa labels
    vector< TreeNode *> listLeafNodes;
    treeIn.GetAllLeafNodes( listLeafNodes );
    for(auto x : listLeafNodes)
    {
        int t = x->GetIntLabel();
//cout << "label: " << t << endl;
        if( setTaxa.find(t) != setTaxa.end() )
        {
            //
            setLabels.insert( x->GetLabel() );
        }
    }
    treeIn.CreatePhyTreeFromLeavesWithLabels(setLabels, treeSub, true);
}

void DumpAllSubtreesWithTaxaSize( const vector<PhylogenyTreeBasic *> &listPtrGTrees, int numTaxonSubtree, const char *fileNameOut )
{
    ofstream outfile( fileNameOut );
    
    // dump out subtrees with certain number of taxa (if the tree contains fewer than this number, just dump out
    // the entire tree)
    for(int tr=0; tr<(int)listPtrGTrees.size(); ++tr)
    {
        //
        set<string> listLeafLabelsSet;
        vector<string> listLeafLabels, listLeafLabelsSetDistinct;
        listPtrGTrees[tr]->GetAllLeafLabeles(listLeafLabels);
        PopulateSetByVecGen( listLeafLabelsSet, listLeafLabels );
        PopulateVecBySetGen( listLeafLabelsSetDistinct, listLeafLabelsSet );
        
        //
        int numSubsetSz = numTaxonSubtree;
        if( numSubsetSz > (int) listLeafLabelsSetDistinct.size() )
        {
            numSubsetSz = listLeafLabelsSetDistinct.size();
        }
        
        // find all subsets
        vector<int> posvec;
        GetFirstCombo( numSubsetSz, (int)listLeafLabelsSetDistinct.size(), posvec );
        while(true)
        {
            set<string> setTaxaStep;
            for(int i=0; i<(int)posvec.size(); ++i)
            {
                setTaxaStep.insert( listLeafLabelsSetDistinct[ posvec[i] ] );
            }
            
            //
            PhylogenyTreeBasic *ptreeNew = new PhylogenyTreeBasic;
            listPtrGTrees[tr]->CreatePhyTreeFromLeavesWithLabels( setTaxaStep, *ptreeNew, true );
            string nwTree;
            ptreeNew->ConsNewick(nwTree);
            outfile << nwTree << endl;
            delete ptreeNew;
            
            if( GetNextCombo( numSubsetSz, (int)listLeafLabelsSetDistinct.size(), posvec ) == false )
            {
                break;
            }
        }
    }
    
    outfile.close();
}

void DumpAllSubtreesWithBoundedSize( const vector<PhylogenyTreeBasic *> &listPtrGTrees, int maxSzSubtree, int maxIdentSubtreeSz, const char *fileNameOut )
{
    // 
//cout << "DumpAllSubtreesWithBoundedSize: maxSzSubtree: " << maxSzSubtree << ", maxIdentSubtreeSz: " << maxIdentSubtreeSz << ", filenameOut: " << fileNameOut << endl;
    // dump all subtrees with at most maxSzSubtree leaves into a file (that is, breaking trees into pieces)
    // in order to avoid issues that large subtrees with identical labels, we first shrink such subtree within the size (if exists)
    // e.g. maxIdentSubtreeSz = 5 and maxSzSubtree = 10
    // YW: 12/09/15: in case of a non-binary tree, we may have multiple subtrees as siblings; if this is the case, output each pair of subtrees
    // YW: 12/10/15: don't output trees with only two siblings
    ofstream outfile( fileNameOut );
    
    // dump out subtrees with certain number of taxa (if the tree contains fewer than this number, just dump out
    // the entire tree)
    bool fTreeOut = false;
    for(int tr=0; tr<(int)listPtrGTrees.size(); ++tr)
    {
//cout << "Processing tree: " << tr << endl;
        // create a new tree where identical subtrees match what we want
        PhylogenyTreeBasic *ptreeWork = ConsPhyTreeShrinkIdentSubtrees( listPtrGTrees[tr], maxIdentSubtreeSz );
//cout << "tree working: ";
//ptreeWork->Dump();
        // find all subtrees that are no bigger than the desired ones
        set<TreeNode *> setSTRoots;
        ptreeWork->GetSubtreesWithMaxSize( setSTRoots, maxSzSubtree );
//cout << "Number of subtrees: " << setSTRoots.size() << endl;
        
        // find any missing
        //set<string> setLabelsPresent;
        //PhylogenyTreeBasic :: FindAllLabelsInSubtrees(setSTRoots, setLabelsPresent);
        //set<string> setLabelsMiss;
        //ptreeWork->GetRoot()->GetAllDistinctLeafLabeles(setLabelsMiss);
        //SubtractSetsGen(setLabelsMiss, setLabelsPresent);
        
        // list of all subtrees that are uniform
        set<TreeNode *> setSTUniform;
        for( set<TreeNode *> :: iterator it = setSTRoots.begin(); it != setSTRoots.end(); ++it )
        {
            //
            set<string> strLblsStep;
            (*it)->GetAllDistinctLeafLabeles( strLblsStep );

            if(  strLblsStep.size() == 1 )
            {
                setSTUniform.insert( *it );
            }
        }
//cout << "Number of uniform subtrees: " << setSTUniform.size() << endl;
        
        // output each subtree one by one
        PhylogenyTreeBasic *ptreeNew = new PhylogenyTreeBasic;
        
        while( setSTRoots.size() >= 1 )
        {
#if 0
cout << "Start of each iteration: tree is: ";
ptreeWork->Dump();
cout << "Set of subtrees: \n";
for(set<TreeNode *> :: iterator itt = setSTRoots.begin(); itt != setSTRoots.end(); ++itt)
{
////
(*itt)->Dump();
cout << endl;
}
#endif
            
            TreeNode *pnSTRootCurr = NULL;
            set<TreeNode *> setSTToRemove;
            
            // rule: if there is a non-uniform subtree, output it
            for( set<TreeNode*> :: iterator itg = setSTRoots.begin(); itg != setSTRoots.end(); ++itg )
            {
                //
                if( setSTUniform.find(*itg) == setSTUniform.end() )
                {
                    //
                    pnSTRootCurr = *itg;
                    break;
                }
            }
            if(  pnSTRootCurr == NULL )
            {
                // if no non-uniform subtrees are found, find a sibling pairs of subtrees and take the whole subtree to output
                // YW: need to be careful; I don't want to have left-over
                set<TreeNode *> ppSibs;
                bool fres = PhylogenyTreeBasic :: GetSiblingsNodesFrom( setSTRoots, ppSibs );
                YW_ASSERT_INFO(fres == true, "Fail to find silblings");
                pnSTRootCurr = (*ppSibs.begin())->GetParent();
                while( true )
                {
                    // find out how many subtrees covered if taking this
                    set<TreeNode *> setSTCoveredStep;
                    PhylogenyTreeBasic :: FindDescendentsOfNodeWithin(pnSTRootCurr, setSTRoots, setSTCoveredStep);
                    // if there are at least two left, use it or we have reached the root
                    if( (int)setSTCoveredStep.size()+1 <(int)setSTRoots.size() || pnSTRootCurr == ptreeWork->GetRoot() )
                    {
                        //
                        break;
                    }
                    else
                    {
                        // move up
                        pnSTRootCurr = pnSTRootCurr->GetParent();
                    }
                }
                
 
            }
            else
            {
                // if there are only one leftover and it is uniform one, output all the tree
                if( setSTRoots.size() == 2 && setSTUniform.size() > 0 )
                {
                    //
                    pnSTRootCurr = ptreeWork->GetRoot();
                }
            }
            
            // remove any subtrees that are descendent of the output subtree
            // just output it
            YW_ASSERT_INFO( pnSTRootCurr != NULL, "Cannot be NULL");
            PhylogenyTreeBasic :: FindDescendentsOfNodeWithin(pnSTRootCurr, setSTRoots, setSTToRemove);
            
//cout << "******** pnSTRootCurr: ";
//pnSTRootCurr->Dump();
            
            // if this is a single node or degree of this node is two, just output it
            if( setSTRoots.find(pnSTRootCurr) != setSTRoots.end() || pnSTRootCurr->GetChildrenNum() == 2 )
            {
//cout << "******** outputing subtree rooted at: ";
//pnSTRootCurr->Dump();
                
                ptreeNew->SetRootPlain( pnSTRootCurr );
                // if the tree has at least one intermediate node, output it
                //if( ptreeNew->GetNumInternalNodes() >= 2 )
                {
                    string nwTree;
                    ptreeNew->ConsNewick(nwTree);
                    outfile << nwTree << endl;
                    fTreeOut = true;
                }
            }
            else
            {
                YW_ASSERT_INFO( pnSTRootCurr->GetChildrenNum() >= 3, "Must be a mulfurcating node" );
                // now enumerate all pairs of children of this node
                TreeNode *pnRootNew = new TreeNode;
                ptreeNew->SetRootPlain(pnRootNew);
                vector<TreeNode *> listChildren;
                set<TreeNode *> listChildrenSet;
                pnSTRootCurr->GetAllChildren(listChildrenSet);
                PopulateVecBySetGen( listChildren, listChildrenSet );
                vector<int> posvec;
                GetFirstCombo(2, (int)listChildren.size(), posvec);
                while(true)
                {
                    vector<int> vecdummy;
                    pnRootNew->AddChild( listChildren[ posvec[0] ] , vecdummy );
                    pnRootNew->AddChild( listChildren[ posvec[1] ] , vecdummy );
                    //if( ptreeNew->GetNumInternalNodes() >= 2 )
                    {
                        string nwTree;
                        ptreeNew->ConsNewick(nwTree);
                        outfile << nwTree << endl;
                        fTreeOut = true;
                    }
                    pnRootNew->DetachAllChildren();
                    listChildren[ posvec[0] ]->SetParent( pnSTRootCurr );
                    listChildren[ posvec[1] ]->SetParent( pnSTRootCurr );
                    if( GetNextCombo(2, (int)listChildren.size(), posvec) == false )
                    {
                        break;
                    }
                }
                //
                delete pnRootNew;
            }
            
            // now detach this node from the rest of tree
            TreeNode *pnparcurr = pnSTRootCurr->GetParent();
            pnSTRootCurr->DetachSelf();
            
            if( pnSTRootCurr == ptreeWork->GetRoot() )
            {
                break;
            }
            
            delete pnSTRootCurr;
            pnSTRootCurr = NULL;
            
//cout << "Before degree-one cleainup, tree is: ";
//ptreeWork->Dump();
//exit(1);
            
            //if( pnparcurr != NULL && pnparcurr != ptreeWork->GetRoot() )
            if( pnparcurr != NULL )
            {
                ptreeWork->RemoveDegreeOneNodeAt( pnparcurr );
            }
            for( set<TreeNode *> :: iterator it = setSTToRemove.begin(); it != setSTToRemove.end(); ++it)
            {
                setSTRoots.erase(*it);
            }
        }
        ptreeNew->SetRootPlain(NULL);
        //delete ptreeNew;
//cout << "output tree deleted\n";
        
#if 0
        // create a psuedo tree just for outputing
        PhylogenyTreeBasic *ptreeNew = new PhylogenyTreeBasic;
        for( set<TreeNode *> :: iterator it = setSTRoots.begin(); it != setSTRoots.end(); ++it )
        {
            //
            ptreeNew->SetRootPlain( *it );
            
            // if there are at least two taxa in the subtree, output it
            //set<string> listLeafLabelsSet;
            //vector<string> listLeafLabels;
            //ptreeNew->GetAllLeafLabeles(listLeafLabels);
            //PopulateSetByVecGen( listLeafLabelsSet, listLeafLabels );
            //if(  listLeafLabelsSet.size() >= 2 )
            //{
                string nwTree;
                ptreeNew->ConsNewick(nwTree, false, 1.0, true);
                outfile << nwTree << endl;
                
                fTreeOut = true;
            //}
        }
        ptreeNew->SetRootPlain(NULL);
        delete ptreeNew;
cout << "output tree deleted\n";
#endif
        
        delete ptreeWork;
//cout << "Shrunk tree deleted.\n";
    }
    
    outfile.close();
//cout << "Tree outoupt finished.\n";
    YW_ASSERT_INFO( fTreeOut == true, "ERROR: no subtrees output. Your trees appear to be either very clustered into uniform subtrees or the parameters (size of subtree and identical trees size upper bounds are wrong.");
 
}

PhylogenyTreeBasic * ConsPhyTreeShrinkIdentSubtrees( PhylogenyTreeBasic *ptreeIn2, int maxIdentSubtreeSz, bool fIdConsecutive)
{
    // create a new tree
    PhylogenyTreeBasic *ptreeRes = new PhylogenyTreeBasic;
    // construct according to Newick format
    string strNW;
    ptreeIn2->ConsNewick(strNW, false, 1.0, true);
    ptreeRes->ConsOnNewick(strNW);

//cout << "ConsPhyTreeShrinkIdentSubtrees: tree in: " << strNW << endl;
    
    // create a tree with identical subtree that is no greater than the given size (i.e. if a subtree is of the same label, shrink it if needed)
    // first obtain the max identity subtrees
    set<TreeNode *> setSTRootsIdents;
    ptreeRes->GetMaxSubtrees( setSTRootsIdents );
//cout << "Number of maximiaml subtrees: " << setSTRootsIdents.size() << endl;
    
    
    // find all the leaves
    vector< set<TreeNode *> > listMaxSubtreesLeaves;
    for( set<TreeNode *> :: iterator it = setSTRootsIdents.begin(); it != setSTRootsIdents.end(); ++it)
    {
        set<TreeNode *> setLeavesUnder;
        (*it)->GetAllLeavesUnder( setLeavesUnder );
        listMaxSubtreesLeaves.push_back( setLeavesUnder );
//cout << "Sz of subtree found: " << setLeavesUnder.size() << endl;
    }
    
    // now remove nodes until the subtrees is no longer too large
    for( int i=0; i<(int)listMaxSubtreesLeaves.size(); ++i )
    {
        //
        if( (int)listMaxSubtreesLeaves[i].size() > maxIdentSubtreeSz )
        {
            vector<TreeNode *> listNodes;
            PopulateVecBySetGen( listNodes, listMaxSubtreesLeaves[i] );
            
            // remove some leaves
            for(int j=maxIdentSubtreeSz; j<(int)listMaxSubtreesLeaves[i].size(); ++j )
            {
                ptreeRes->RemoveNodeKeepChildren(  listNodes[j] );
                
//cout << "After removing a leaf: current tree: ";
//string tr;
//ptreeRes->ConsNewick(tr);
//cout << tr << endl;
            }
        }
    }
    
//cout << "ConsPhyTreeShrinkIdentSubtrees: resulting tree: ";
//string tr;
//ptreeRes->ConsNewick(tr);
//cout << tr << endl;
    
    // YW: set consecutive id?
    if( fIdConsecutive == true )
    {
        AssignConsecutiveIdsForTree(*ptreeRes);
    }
    
    return ptreeRes;
}

void ChangebackLeafLabelForTreeWithZeroBaseId( PhylogenyTreeBasic *ptree, TaxaMapper *pTMapper )
{
//cout << "Before ChangebackLeafLabelForTreeWithZeroBaseId: ";
//ptree->Dump();
    //
    YW_ASSERT_INFO(pTMapper != NULL, "Must have a mapper");
    vector< TreeNode *> listLeafNodes;
    ptree->GetAllLeafNodes( listLeafNodes);
    for(int i=0; i<(int)listLeafNodes.size(); ++i)
    {
        // get the int id
        int lbl = listLeafNodes[i]->GetIntLabel();
        string lblOrig = pTMapper->GetString(lbl);
//cout << "lbl:" << lbl << ", lblOrig: " << lblOrig << endl;;
        listLeafNodes[i]->SetLabel( lblOrig );
    }
//cout << "After ChangebackLeafLabelForTreeWithZeroBaseId: ";
//ptree->Dump();
}

bool ConvPhyloTreesToZeroBasedId( vector<PhylogenyTreeBasic *> &treePtrList, TaxaMapper *pTMapper)
{
    // the given trees are not zero-based; so convert them to be; pTMMapeer: not initialied upon entry; then
    // store the mapping between id to string
    for(int i=0; i<(int)treePtrList.size(); ++i)
    {
        vector< TreeNode *> listLeafNodes;
        treePtrList[i]->GetAllLeafNodes( listLeafNodes);
        if( pTMapper->IsInitialized() == false )
        {
            //
            for(int i=0; i<(int)listLeafNodes.size(); ++i)
            {
                // get the int id
                string lbl = listLeafNodes[i]->GetLabel();
                int idTouse = pTMapper->AddTaxaString(lbl);
                //cout << "lbl:" << lbl << ", lblOrig: " << lblOrig << endl;;
                listLeafNodes[i]->SetIntLabel( idTouse );
            }
        }
        else
        {
            //
            for(int i=0; i<(int)listLeafNodes.size(); ++i)
            {
                // get the int id
                int lbl = listLeafNodes[i]->GetIntLabel();
                string lblOrig = pTMapper->GetString(lbl);
                //cout << "lbl:" << lbl << ", lblOrig: " << lblOrig << endl;;
                listLeafNodes[i]->SetLabel( lblOrig );
            }
        }
    }
    return true;        // for now, just true
}

void ChangeLeafIntLabelOfTree( PhylogenyTreeBasic &treeToChange, const map<int,int> & mapOldIntLblToNewIntLbl, bool fSetUserLblToo )
{
#if 0
cout << "Before ChangeLeafIntLabelOfTree: ";
treeToChange.Dump();
cout << "mapOldIntLblToNewIntLbl: ";
for(map<int,int> :: const_iterator it = mapOldIntLblToNewIntLbl.begin(); it != mapOldIntLblToNewIntLbl.end(); ++it)
{
cout << "[" << it->first << "," << it->second << "] ";
}
cout << endl;
#endif
    //
    vector< TreeNode *> listLeafNodes;
    treeToChange.GetAllLeafNodes( listLeafNodes);
    for(int i=0; i<(int)listLeafNodes.size(); ++i)
    {
        // get the int id
        int lbl = listLeafNodes[i]->GetIntLabel();
        
        if( mapOldIntLblToNewIntLbl.find(lbl) == mapOldIntLblToNewIntLbl.end() )
        {
            treeToChange.Dump();
            cout << "lbl: " << lbl << endl;
            cout << "mapOldIntLblToNewIntLbl: ";
            for(map<int,int>:: const_iterator it = mapOldIntLblToNewIntLbl.begin(); it != mapOldIntLblToNewIntLbl.end(); ++it )
            {
                cout << "[" << it->first << ", " << it->second << "]   ";
            }
            cout << endl;
        }
        
        YW_ASSERT_INFO(mapOldIntLblToNewIntLbl.find(lbl) != mapOldIntLblToNewIntLbl.end(), "Fail to find the orignal label");
        int lblIntNew = (*(mapOldIntLblToNewIntLbl.find(lbl))).second;
//cout << "lbl:" << lbl << ", lblIntNew: " << lblIntNew << endl;;
        listLeafNodes[i]->SetIntLabel( lblIntNew );
        if( fSetUserLblToo )
        {
            char buf[100];
            snprintf( buf,100, "%d", lblIntNew );
            string strbuf(buf);
            listLeafNodes[i]->SetUserLabel( strbuf );
        }
#if 0
// for now, also set user label as well
char buf[100];
sprintf(buf, "%d",lblIntNew);
string strbuf(buf);
listLeafNodes[i]->SetUserLabel(strbuf);
#endif
    }
#if 0
cout << "After ChangeLeafIntLabelOfTree: ";
treeToChange.Dump();
#endif
}

void AssignConsecutiveIdsForTree(PhylogenyTreeBasic &treeToChange)
{
    //
    vector< TreeNode *> listAllNodes;
    treeToChange.GetAllNodes( listAllNodes);
    int idToUse = 0;
    for(int i=0; i<(int)listAllNodes.size(); ++i)
    {
        // leaves assigned to a distinct id first
        if( listAllNodes[i]->IsLeaf() == true )
        {
            listAllNodes[i]->SetID(idToUse++);
        }
    }
    for(int i=0; i<(int)listAllNodes.size(); ++i)
    {
        // leaves assigned to a distinct id first
        if( listAllNodes[i]->IsLeaf() == false )
        {
            listAllNodes[i]->SetID(idToUse++);
        }
    }
}

void RandTrimLeavesFromTree( PhylogenyTreeBasic *ptreeToTrim, int numLeavesRemain )
{
    // do nothing if the gene trees are small
    if( ptreeToTrim->GetNumLeaves() <= numLeavesRemain )
    {
        return;
    }
    
//cout << "RandTrimLeavesFromTree: before trimming: tree is: ";
//string strNW;
//ptreeToTrim->ConsNewick( strNW, false, 1.0, true );
//cout << strNW << endl;
    
    // for a large tree, we want to randomly trim some leaves to make the tree smaller
    // rule: never completely delete some leaf label; prefer to deleting
    // leaves that appear more frequently
    map<int, set<TreeNode *>  > mapLeafLblToNodes;
    vector<TreeNode *> listLeafNodes;
    ptreeToTrim->GetAllLeafNodes( listLeafNodes );
    for(int i=0; i<(int)listLeafNodes.size(); ++i)
    {
        int lbl = listLeafNodes[i]->GetIntLabel();
        if( mapLeafLblToNodes.find(lbl) == mapLeafLblToNodes.end() )
        {
            set<TreeNode *> ss;
            mapLeafLblToNodes.insert( map<int, set<TreeNode *>  > :: value_type(lbl, ss) );
        }
        mapLeafLblToNodes[lbl].insert( listLeafNodes[i] );
    }
    // create a list of nodes to remove
    vector< set<TreeNode *> > listNodesToRemove;
    vector<double> listNodesToRemoveSz;
    for( map<int, set<TreeNode *>  > :: iterator it = mapLeafLblToNodes.begin(); it != mapLeafLblToNodes.end(); ++it )
    {
        //
        listNodesToRemove.push_back( it->second );
        listNodesToRemoveSz.push_back(it->second.size());
    }
    // now start removing
    int numLeavesCurr = ptreeToTrim->GetNumLeaves();
    while( numLeavesCurr > numLeavesRemain  )
    {
        int indexChosen = GetWeightedRandItemIndex( listNodesToRemoveSz );
        
        if( listNodesToRemoveSz[indexChosen] < 1.01 )
        {
            // cannot delete the one with only one copy left
            continue;
        }
        YW_ASSERT_INFO( listNodesToRemove[indexChosen].size() >=2, "Wrong" );
        TreeNode *pnToRm = *(listNodesToRemove[indexChosen].begin());
        listNodesToRemove[indexChosen].erase( pnToRm );
        --numLeavesCurr;
        TreeNode *pnPar = pnToRm->GetParent();
        ptreeToTrim->RemoveNode( pnToRm );
        ptreeToTrim->RemoveDegreeOneNodeAt(pnPar);
        listNodesToRemoveSz[indexChosen] -= 1.0;
    }
    AssignConsecutiveIdsForTree(*ptreeToTrim);
//cout << "RandTrimLeavesFromTree: After trimming: tree is: ";
//string strNW2;
//ptreeToTrim->ConsNewick( strNW2, false, 1.0, true );
//cout << strNW2 << endl;
}

//*****************************************************************************
// RF distance classes: say Day's 1985 paper
//*****************************************************************************

// preprocess a tree for efficient query of clades

CladeQueryTree :: CladeQueryTree(PhylogenyTreeBasic &treeBase) : fRooted(false)
{
    Init(treeBase);
}
int CladeQueryTree :: CalcDistanceWith(PhylogenyTreeBasic &treeCompare) const
{
    if( fRooted == false)
    {
        std::set< std::set< std::pair<int,std::pair<int,int> > > > listCodedCladePairs;
        ConsConvertedCladesForTreeUnrooted(treeCompare, listCodedCladePairs);
        return CalcDistanceWithUnrooted(listCodedCladePairs);
    }
//cout << "Query tree info: ";
//this->Dump();
    // return the number of clades in treeCompare but not in the base tree
    std::vector<std::pair<int,std::pair<int,int> > > listCodedClades;
    ConsConvertedCladesForTree( treeCompare, listCodedClades );
//cout << "List of other clades: \n";
//for(unsigned int i=0; i<listCodedClades.size(); ++i)
//{
//cout << "Size: " << listCodedClades[i].first << ",  min:" << listCodedClades[i].second.first << ", max:" << listCodedClades[i].second.second << endl;
//}
    int numDiffClades = 0;
    for(unsigned int i=0; i<listCodedClades.size(); ++i)
    {
//cout << "Size: " << listCodedClades[i].first << ",  min:" << listCodedClades[i].second.first << ", max:" << listCodedClades[i].second.second << endl;
        if( IsEncodedCladeIn(listCodedClades[i]) == false )
        {
//cout << "   is not in the tree.\n";
            ++numDiffClades;
        }
    }
    return numDiffClades;
}

void CladeQueryTree :: Init(PhylogenyTreeBasic &treeBase)
{
    // creaet internal structure for tree
    // first construct leaf mapping table
    vecMappedLeaves.clear();
    vecMappedLeaves.resize(treeBase.GetNumLeaves());
    PhylogenyTreeIterator itor(treeBase);
    itor.Init();
    int mappedLeafId = 0;
    while(itor.IsDone()==false)
    {
        TreeNode *pncurr = itor.GetCurrNode();
        if( pncurr->IsLeaf() )
        {
            int lbl = pncurr->GetIntLabel();
//cout << "Visit leaf: " << lbl << endl;
            vecMappedLeaves[lbl] = mappedLeafId++;
        }
        itor.Next();
    }
//cout << "Mapped ids: ";
//DumpIntVec(this->vecMappedLeaves);
    // construct cluster table
    vecCladeAtLeaf.clear();
    vecCladeAtLeaf.resize(treeBase.GetNumLeaves());
    for(unsigned int i=0; i<vecCladeAtLeaf.size(); ++i)
    {
        vecCladeAtLeaf[i].first = -1;
        vecCladeAtLeaf[i].second = -1;
    }
    // collect tree postorder info
    vector<pair<int,int> > listPostTraveInfo;   // <node id, weight>: node id: for leaf is the original user label;
    // for internal ndoe, uniquely labeled
    int idIntNodeNext = treeBase.GetNumLeaves();
    map<TreeNode *, int> mapNodeWts;
    //int nodeIndex = 0;
    itor.Init();
    while(itor.IsDone()==false)
    {
        TreeNode *pncurr = itor.GetCurrNode();
        int wtNode = 0;
        int lbl = -1;
        if( pncurr->IsLeaf() )
        {
            lbl = pncurr->GetIntLabel();
        }
        else
        {
            lbl = idIntNodeNext++;
            wtNode = pncurr->GetChildrenNum();
            for(int j=0; j<pncurr->GetChildrenNum(); ++j)
            {
                TreeNode *pc = pncurr->GetChild(j);
                map<TreeNode *, int> :: iterator itg = mapNodeWts.find(pc);
                YW_ASSERT_INFO(itg != mapNodeWts.end(), "Fail to find 345");
                wtNode += itg->second;
            }
        }
        pair<int,int> pp(lbl, wtNode);
        listPostTraveInfo.push_back(pp);
        mapNodeWts[pncurr] = wtNode;
        itor.Next();
    }
//cout << "listPostTraveInfo: ";
//for(unsigned int i=0; i<listPostTraveInfo.size(); ++i)
//{
//cout << listPostTraveInfo[i].first << "  " << listPostTraveInfo[i].second << endl;
//}
    // now assign internal clades
    map<TreeNode *,pair<int,int> > mapAuxPS;        // <p,q> = for current node, min/max leaf id
    int lvIndex = 0;
    int pidNodeIndex = 0;       // index of postorder traversla index
    itor.Init();
    while(itor.IsDone() == false)
    {
        TreeNode *pncurr = itor.GetCurrNode();
        if( pncurr->IsLeaf() )
        {
            int lvIdCurr = lvIndex++;
            pair<int,int> pp(lvIdCurr, lvIdCurr);
            mapAuxPS[pncurr] = pp;
//cout << "leaf: " << lvIdCurr << endl;
        }
        else
        {
            // find range of nodes
            int lvMin = treeBase.GetNumLeaves();
            int lvMax = 0;
            for(int j=0; j<pncurr->GetChildrenNum(); ++j)
            {
                TreeNode *pc = pncurr->GetChild(j);
                pair<int,int> pcmm = mapAuxPS[pc];
                if(pcmm.first < lvMin)
                {
                    lvMin = pcmm.first;
                }
                if(pcmm.second > lvMax)
                {
                    lvMax = pcmm.second;
                }
            }
//cout << "internal node: min:" << lvMin << ", max:" << lvMax << endl;
            // now assign to the proper leaf
            int leafPicked = -1;
            if( pncurr->IsRoot() )
            {
                leafPicked = treeBase.GetNumLeaves()-1;
            }
            else
            {
                int nidNext = pidNodeIndex+1;
                YW_ASSERT_INFO(nidNext <(int)listPostTraveInfo.size(), "Cannot overflow");
                int wtNext = listPostTraveInfo[nidNext].second;
//cout << "wtNext:" << wtNext << endl;
                if( wtNext > 0)
                {
                    leafPicked = lvMin;
                }
                else
                {
                    leafPicked = lvMax;
                }
            }
//cout << "Picked leaf: " << leafPicked << ", pidNodeIndex:" << pidNodeIndex << endl;
            YW_ASSERT_INFO(leafPicked >=0, "Fail to find leaf");
            YW_ASSERT_INFO(vecCladeAtLeaf[leafPicked].first <0 && vecCladeAtLeaf[leafPicked].second <0, "This leaf has been taken");
            vecCladeAtLeaf[leafPicked].first = lvMin;
            vecCladeAtLeaf[leafPicked].second = lvMax;
            pair<int,int> pp(lvMin, lvMax);
            mapAuxPS[pncurr] = pp;
        }
        ++pidNodeIndex;
        itor.Next();
    }
}

int CladeQueryTree :: MapId(int idOrig) const
{
//Dump();
    // map an original id to the new id represented in the base tree
    YW_ASSERT_INFO(idOrig < (int)vecMappedLeaves.size(), "Id out of range");
    return vecMappedLeaves[idOrig];
}

void CladeQueryTree :: ConsConvertedCladesForTree(PhylogenyTreeBasic &treeCompare, std::vector<std::pair<int,std::pair<int,int> > > &listCodedClades) const
{
    // encodec clade: [num of leaves under clade, [min converted id, max converted id] ]
    listCodedClades.clear();
    map<TreeNode *, pair<int,pair<int,int> > > mapAuxPS;        // <wt, <p,q> >= for current node, wt: num of leaves under min/max leaf id
    PhylogenyTreeIterator itor(treeCompare);
    itor.Init();
    while(itor.IsDone() == false)
    {
        TreeNode *pncurr = itor.GetCurrNode();
        if( pncurr->IsLeaf() )
        {
            int lbl = pncurr->GetIntLabel();
            int lvIdCurr = MapId(lbl);
            pair<int,int> pp(lvIdCurr, lvIdCurr);
            pair<int,pair<int,int> > pp2(1, pp);
            mapAuxPS[pncurr] = pp2;
//cout << "Proc leaf: " << lbl << ", mapped id: " << lvIdCurr << endl;
        }
        else
        {
            // find range of nodes
            int lvMin = treeCompare.GetNumLeaves();
            int lvMax = 0;
            int numLvsUnder = 0;
            for(int j=0; j<pncurr->GetChildrenNum(); ++j)
            {
                TreeNode *pc = pncurr->GetChild(j);
                pair<int,pair<int,int> > pcmm = mapAuxPS[pc];
                int cmin = pcmm.second.first;
                int cmax = pcmm.second.second;
                if( cmin < lvMin)
                {
                    lvMin = cmin;
                }
                if( cmax > lvMax)
                {
                    lvMax = cmax;
                }
                numLvsUnder += pcmm.first;
            }
//cout << "sz:" << numLvsUnder << ", lvMin:" << lvMin << ", lvMax:" << lvMax << endl;
            pair<int,int> pp(lvMin, lvMax);
            pair<int,pair<int,int> > pp1(numLvsUnder, pp);
            mapAuxPS[pncurr] = pp1;
            listCodedClades.push_back(pp1);
        }
        itor.Next();
    }
}

void CladeQueryTree :: ConsConvertedCladesForTreeUnrooted(PhylogenyTreeBasic &treeCompare, std::set< std::set< std::pair<int,std::pair<int,int> > > > &listCodedCladePairs) const
{
    // encodec clade: [num of leaves under clade, [min converted id, max converted id] ]. Each clade has two representations
    // first construct like the rooted case
    // encodec clade: [num of leaves under clade, [min converted id, max converted id] ]
    listCodedCladePairs.clear();
    map<TreeNode *, pair<int,pair<int,int> > > mapAuxPS;        // <wt, <p,q> >= for current node, wt: num of leaves under min/max leaf id
    PhylogenyTreeIterator itor(treeCompare);
    itor.Init();
    while(itor.IsDone() == false)
    {
        TreeNode *pncurr = itor.GetCurrNode();
        if( pncurr->IsLeaf() )
        {
            int lbl = pncurr->GetIntLabel();
            int lvIdCurr = MapId(lbl);
            pair<int,int> pp(lvIdCurr, lvIdCurr);
            pair<int,pair<int,int> > pp2(1, pp);
            mapAuxPS[pncurr] = pp2;
            //cout << "Proc leaf: " << lbl << ", mapped id: " << lvIdCurr << endl;
        }
        else
        {
            // find range of nodes
            int lvMin = treeCompare.GetNumLeaves();
            int lvMax = 0;
            int numLvsUnder = 0;
            for(int j=0; j<pncurr->GetChildrenNum(); ++j)
            {
                TreeNode *pc = pncurr->GetChild(j);
                pair<int,pair<int,int> > pcmm = mapAuxPS[pc];
                int cmin = pcmm.second.first;
                int cmax = pcmm.second.second;
                if( cmin < lvMin)
                {
                    lvMin = cmin;
                }
                if( cmax > lvMax)
                {
                    lvMax = cmax;
                }
                numLvsUnder += pcmm.first;
            }
            //cout << "sz:" << numLvsUnder << ", lvMin:" << lvMin << ", lvMax:" << lvMax << endl;
            pair<int,int> pp(lvMin, lvMax);
            pair<int,pair<int,int> > pp1(numLvsUnder, pp);
            mapAuxPS[pncurr] = pp1;
        }
        itor.Next();
    }

    // now construct the other side's info: [k] = at this node, if we remove the k-th child of the current node, all the range
    // of the nodes in the remaining child (plus the node coming from above)
    map<TreeNode *, vector<pair<int,pair<int,int> > > > mapAuxPSOther;
    PhylogenyTreeIteratorPreOrder itorPre(treeCompare);
    itorPre.Init();
    while(itorPre.IsDone()==false)
    {
        TreeNode *pncurr = itorPre.GetCurrNode();
        if( pncurr->IsLeaf() == false)
        {
//cout << "*At node: ";
//pncurr->Dump();
//cout << endl;
            for(int i=0; i<pncurr->GetChildrenNum(); ++i)
            {
                int lvMin = treeCompare.GetNumLeaves();
                int lvMax = 0;
                int numLvsUnder = 0;
                
                for(int j=0; j<pncurr->GetChildrenNum(); ++j)
                {
                    if( i != j )
                    {
                        TreeNode *pc = pncurr->GetChild(j);
                        pair<int,pair<int,int> > pcmm = mapAuxPS[pc];
                        int cmin = pcmm.second.first;
                        int cmax = pcmm.second.second;
                        if( cmin < lvMin)
                        {
                            lvMin = cmin;
                        }
                        if( cmax > lvMax)
                        {
                            lvMax = cmax;
                        }
                        numLvsUnder += pcmm.first;
                    }
                }
                if( pncurr->IsRoot() == false)
                {
                    int cindex = pncurr->GetParent()->GetChildIndex(pncurr);
                    YW_ASSERT_INFO(cindex >=0, "Cannot be negative");
                    map<TreeNode *, vector<pair<int,pair<int,int> > > > :: iterator itg = mapAuxPSOther.find(pncurr->GetParent());
                    YW_ASSERT_INFO(itg != mapAuxPSOther.end(), "Fail to find 345");
                    YW_ASSERT_INFO(cindex <(int)itg->second.size(), "Overflow");
                    int cmin = itg->second[cindex].second.first;
                    int cmax = itg->second[cindex].second.second;
                    if( cmin < lvMin)
                    {
                        lvMin = cmin;
                    }
                    if( cmax > lvMax)
                    {
                        lvMax = cmax;
                    }
                    numLvsUnder += itg->second[cindex].first;
                }
                pair<int,int> pp(lvMin, lvMax);
                pair<int,pair<int,int> > pp1(numLvsUnder, pp);
                mapAuxPSOther[pncurr].push_back( pp1);
//cout << "Add an entry: num:" << pp1.first << ", min/max:" << pp1.second.first << "," << pp1.second.second << endl;
            }
        }
        
        itorPre.Next();
    }
    
    // now collect all pairs of clades by yet another traversal
    itor.Init();
    while(itor.IsDone()==false)
    {
        TreeNode *pncurr = itor.GetCurrNode();
        if( pncurr->IsLeaf() == false)
        {
            for(int i=0; i<pncurr->GetChildrenNum(); ++i)
            {
                //
                TreeNode *pnc = pncurr->GetChild(i);
                if( pnc->IsLeaf() == false)
                {
                    //
                    pair<int,pair<int,int> > pp = mapAuxPS[pnc];
                    pair<int,pair<int,int> > pp1 = mapAuxPSOther[pncurr][i];
                    set<pair<int,pair<int,int> > > ss;
                    ss.insert(pp);
                    ss.insert(pp1);
                    listCodedCladePairs.insert(ss);
                }
            }
        }
        
        itor.Next();
    }
}

int CladeQueryTree :: CalcDistanceWithUnrooted(const std::set< std::set< std::pair<int,std::pair<int,int> > > > &listCodedCladePairs) const
{
//this->Dump();
    int numDiffClades = 0;
    for(std::set< std::set< std::pair<int,std::pair<int,int> > > > :: const_iterator it = listCodedCladePairs.begin(); it != listCodedCladePairs.end(); ++it)
    {
        YW_ASSERT_INFO(it->size() == 2, "Must be of size 2");
//cout << "(1)Size: " << it->begin()->first << ",  min:" << it->begin()->second.first << ", max:" << it->begin()->second.second << endl;
//cout << "(2)Size: " << it->rbegin()->first << ",  min:" << it->rbegin()->second.first << ", max:" << it->rbegin()->second.second << endl;;
        if( IsEncodedCladeIn(*(it->begin())) == false && IsEncodedCladeIn(*(it->rbegin())) == false )
        {
//cout << "   is not in the tree.\n";
            ++numDiffClades;
        }
    }
    return numDiffClades;
}

bool CladeQueryTree :: IsEncodedCladeIn(const std::pair<int,std::pair<int,int> > &cladeCoded) const
{
    if( (int)cladeCoded.second.first >= vecCladeAtLeaf.size() ||  (int)cladeCoded.second.second >= vecCladeAtLeaf.size() || cladeCoded.second.first > cladeCoded.second.second )
    {
        return false;
    }
    // singleton: yes
    if( cladeCoded.first == 1 && cladeCoded.second.first==cladeCoded.second.second)
    {
        return true;
    }
    
    //YW_ASSERT_INFO((int)cladeCoded.second.first < vecCladeAtLeaf.size() &&  (int)cladeCoded.second.second < vecCladeAtLeaf.size(), "Node encoding is wrong");
    // <num of leaves in clade, <min converted id, max coverted id> >
    int lvMin = cladeCoded.second.first;
    int lvMax = cladeCoded.second.second;
    int szClade2 = lvMax- lvMin+1;
    YW_ASSERT_INFO(szClade2 >= 1, "Encode wrong");
    if( cladeCoded.first != szClade2)
    {
        return false;
    }
    // check one of the two positions
    if( this->vecCladeAtLeaf[lvMin].first == lvMin && this->vecCladeAtLeaf[lvMin].second == lvMax )
    {
        return true;
    }
    if( this->vecCladeAtLeaf[lvMax].first == lvMin && this->vecCladeAtLeaf[lvMax].second == lvMax )
    {
        return true;
    }
    return false;
}

void CladeQueryTree :: Dump() const
{
    cout << "Mapped ids: ";
    DumpIntVec(this->vecMappedLeaves);
    cout << "clades at: \n";
    for(unsigned int i=0; i<vecCladeAtLeaf.size(); ++i)
    {
        cout << vecCladeAtLeaf[i].first <<"   "  << vecCladeAtLeaf[i].second << endl;
    }
}

// ***************************************************************************
void NewickUtils :: RetrieveLabelSet( const string &strNW, multiset<string> &setLabels )
{
//cout << "RetrieveLabelSet: strNW = " << strNW << endl;
	//
	setLabels.clear();

	string strIdDirect = strNW;
	int curpos = 0;
	int lastposOut = 0;
	//char *strIdBuf = (char *)strIdDirect.c_str();
	while( curpos<(int) strNW.length() )
	{
//cout << "curpos = " << curpos << endl;
		bool fIdentifier = false;
		if( (strNW[curpos] == '(' || strNW[curpos] == ',' ) && ( curpos == (int)strNW.length()-1 || strNW[curpos+1] != '(' )     )
		{
			fIdentifier = true;
		}
//cout << "Adding it: " << strId[curpos] << endl;
		lastposOut ++;
		curpos ++;

		// should we search for id
		if( fIdentifier == true )
		{
//cout << "Now searching for identifier\n";
			// now scan to the right to find the position to read the identifier
			while( curpos<(int) strNW.length() )
			{
				if(  strNW[curpos] != ')' && strNW[curpos] != ':' && strNW[curpos] != ',' )
				{
					curpos++;
				}
				else
				{
					break;
				}
			}
			// 
			//curpos--;
			string strFoundId;
//cout << "lastposOut = " << lastposOut << ", curpos = " << curpos << endl;
			strFoundId = strNW.substr( lastposOut, curpos-lastposOut );
			setLabels.insert( strFoundId );
			lastposOut = curpos;
//cout << "One identifier found: " << strFoundId << endl;
		}
	}
}

bool NewickUtils :: FindSplitIn( const string &strNW, string &strPart1, string &strPart2)
{
	// break up the NW into two parts by the center ,
	// return false if atomic
	int posSplit = -1;
	int level = 0;
	for(int i=0; i<(int)strNW.length(); ++i)
	{
		if( strNW[i] == '(')
		{
			level ++;
		}
		else if(strNW[i] == ')' )
		{
			level --;
		}
		else if( strNW[i] == ',' )
		{
			if( level == 1 )
			{
				posSplit = i;
				break;
			}
		}
	}

	if( posSplit < 0 )
	{
		return false;
	}
	// 
	int posLeft = strNW.find('(');
	int posRight = strNW.rfind(')');
	strPart1 = strNW.substr( posLeft+1, posSplit-posLeft-1 );
	strPart2 = strNW.substr( posSplit+1, posRight-posSplit-1 );

	return true;
}

void NewickUtils :: UpdateLabells( string &strNW, const map<string,string> &mapOldLabelToNew )
{
    // change the taxa name in the old newick format to the new ones as recorded in the map
    string strNWNew;
    string strIdDirect = strNW;
	int curpos = 0;
	int lastposOut = 0;
    map<string,string> &mapOldLabelToNewRef = const_cast<map<string,string> &>(mapOldLabelToNew);
    //bool fOutputCurChar = true;
	//char *strIdBuf = (char *)strIdDirect.c_str();
	while( curpos<(int) strNW.length() )
	{
        //cout << "curpos = " << curpos << endl;
		bool fIdentifier = false;
		if( (strNW[curpos] == '(' || strNW[curpos] == ',' ) && ( curpos == (int)strNW.length()-1 || strNW[curpos+1] != '(' )     )
		{
			fIdentifier = true;
		}
        
        // add it always since this is deliminator
        strNWNew += strNW[curpos];
        
        //cout << "Adding it: " << strId[curpos] << endl;
		lastposOut ++;
		curpos ++;
        
		// should we search for id
		if( fIdentifier == true )
		{
            //cout << "Now searching for identifier\n";
			// now scan to the right to find the position to read the identifier
			while( curpos<(int) strNW.length() )
			{
				if(  strNW[curpos] != ')' && strNW[curpos] != ':' && strNW[curpos] != ',' )
				{
					curpos++;
				}
				else
				{
					break;
				}
			}
			//
			//curpos--;
			string strFoundId;
            //cout << "lastposOut = " << lastposOut << ", curpos = " << curpos << endl;
			strFoundId = strNW.substr( lastposOut, curpos-lastposOut );
            
            //
            YW_ASSERT_INFO( mapOldLabelToNew.find(strFoundId) != mapOldLabelToNew.end(), "Fail to find the id in the map");
            strNWNew.append( mapOldLabelToNewRef[strFoundId] );
            
			lastposOut = curpos;
            //cout << "One identifier found: " << strFoundId << endl;
            
            // now move back by one letter
            //--curpos;
		}
	}

//cout << "UpdateLabells: before update, newick = " << strNW << ", after update: " << strNWNew << endl;
    strNW = strNWNew;
}

string NewickUtils :: RemoveBrLenFromTree(string &strNW)
{
    //
    int curpos = 0;
    bool fSkip = false;
    string strNWNew;
	//char *strIdBuf = (char *)strIdDirect.c_str();
	while( curpos<(int) strNW.length() )
	{
        //cout << "curpos = " << curpos << endl;
		if( strNW[curpos] == ':' )
		{
			fSkip = true;
		}
        else if( strNW[curpos] == ','  || strNW[curpos] == ')' || strNW[curpos] == ';'  )
        {
            // continue skipping until reaching the separate: , or )
            fSkip = false;
        }
        
        if( fSkip == false)
        {
            strNWNew += strNW[curpos];
        }

		curpos ++;
	}
    return strNWNew;
}

void NewickUtils :: ConsolidateSinglChildChain(string &strNW)
{
    if( strNW[0] != '(')
    {
        // nothing needs to be done
        return;
    }
    
//cout << "conslidate: " << strNW << endl;
    // sometime there may be a nested chain of enclosed parenthesis
    // consolidate these; and maintain the proper branch length if there are
    string strRes = strNW;
    double lenTot = 0.0;
    bool fLen = false;
    //bool fParenthRemoved = false;
    
    while(true)
    {
//cout << "current string: " << strRes << endl;
        // stop if it become automic
        string str1, str2;
        bool fNonAtom = FindSplitIn( strRes, str1, str2  );
        
        //if( fNonAtom == false )
        //{
        //fParenthRemoved = true;
        
        //
        YW_ASSERT_INFO(strRes[0] == '(', "wrong");
        int posRight = strRes.rfind(')');
        YW_ASSERT_INFO(posRight > 0, "wrong1");
//cout << "posRight: " << posRight << endl;
        if( posRight != (int)strRes.length()-1 )
        {
            int posLen = strRes.find(':', posRight);
//cout << "posLen: " << posLen << endl;
            if( posLen > 0 )
            {
//if( lenTot > 0.0)
//{
//cout << "*HHHHH\n";
//}
                fLen = true;
                lenTot += GetLenAt( strRes, posLen+1 );
//cout << "lenTot: " << lenTot << endl;
            }
        }
        //}
        
        int len = posRight-1;
        strRes = strRes.substr(1, len);
        
        if( fNonAtom == true )
        {
            break;
        }
    }
    string strRes1;
    //if( fParenthRemoved )
    //{
    strRes1 += "(";
    //}
    strRes1 += strRes;
    //if( fParenthRemoved )
    //{
    strRes1 += ")";
    //}
    if( fLen )
    {
        strRes1 += ":" + std::to_string(lenTot);
    }
    
    strNW = strRes1;
//cout << "conslidate to " << strNW << endl;
}

double NewickUtils :: GetLenAt(const string &strNW, int posLen)
{
    //
    int posLenEnd = strNW.length()-1;
    int sepPos1 = strNW.find( ',', posLen );
    int sepPos2 = strNW.find( ')', posLen );
    if( sepPos1 > 0 && sepPos1-1 < posLenEnd )
    {
        posLenEnd = sepPos1-1;
    }
    if( sepPos2 > 0 && sepPos2-1 < posLenEnd )
    {
        posLenEnd = sepPos2-1;
    }
if( posLenEnd <= posLen)
{
//cout << "posLen: " << posLen << ", posLenEnd: " << posLenEnd << ", tree: " << strNW << endl;
}
    YW_ASSERT_INFO(posLenEnd >= posLen, "No length found");
    string lenstr = strNW.substr(posLen, posLenEnd-posLen+1);
    return atof(lenstr.c_str());
}


// ***************************************************************************

TaxaMapper :: TaxaMapper() 
{ 
	curId = 0; 
	fInit = false;
} 

// utility
bool TaxaMapper :: IsEmpty() 
{ 
	return mapStrToId.size() == 0; 
}

int TaxaMapper :: AddTaxaString(const string &str) 
{
//cout << "AddTaxaString : curId = " << curId  << " for new taxa string " << str << endl;
	if( mapStrToId.find( str ) == mapStrToId.end() )
	{
		mapStrToId.insert( map<string,int> :: value_type(str, curId) );
		mapIdToStr.insert( map<int,string> :: value_type(curId, str) );
		curId ++;
	}
	//else
	//{
	return mapStrToId[str];
	//}
}

void TaxaMapper :: AddTaxaStringWithId(int tid, const string &str)
{
    // caution: don't mix up with the previous auto-id mode
    mapStrToId.insert( map<string,int> :: value_type(str, tid) );
    mapIdToStr.insert( map<int,string> :: value_type(tid, str) );
}

int TaxaMapper :: GetId(const string &str)
{
//cout << "Num of entries in str mapper : " << mapStrToId.size() << endl;
//for( map<string,int> :: iterator it =mapStrToId.begin(); it != mapStrToId.end(); ++it )
//{
//cout << it->first << ", " << it->second << endl;
//}

	if(mapStrToId.find(str) == mapStrToId.end() )
	{
        // when the str is not pre-recorded, return negative value
        return -1;
		//cout << "This taxa: " << str << " seems to be wrong\n";
		//YW_ASSERT_INFO( false, "Fail to find the taxa" );
	}
	return mapStrToId[str];
}
bool TaxaMapper :: IsIdIn( int id)
{
	return mapIdToStr.find(id) != mapIdToStr.end();
}

string TaxaMapper :: GetString(const int id)
{
	if(mapIdToStr.find(id) == mapIdToStr.end() )
	{
        cout << "mapIdToStr: ";
        for(map<int,string> :: iterator it =mapIdToStr.begin(); it != mapIdToStr.end(); ++it)
        {
            cout << "[" << it->first << "," << it->second << "]  ";
        }
        cout << endl;
        
		cout << "This taxa id: " << id << " seems to be wrong\n";
		YW_ASSERT_INFO( false, "Fail to find the taxa" );
	}
	return mapIdToStr[id];
}

string TaxaMapper :: ConvIdStringWithOrigTaxa(const string &strId)
{
#if 0
cout << "strID: " << strId << ": Num of entries in str mapper : " << mapIdToStr.size() << endl;
for( map<int,string> :: iterator it =mapIdToStr.begin(); it != mapIdToStr.end(); ++it )
{
cout << it->first << ", " << it->second << endl;
}
#endif
	// convert a string with id (i.e. integer-based identifier) back
	// to user-specified format
	// Simple approach: find everything bebetween ( and , (or :),  and ) and convert to
    // YW: 05/02/19: also allow '#' as seperator to support mutation tree
	string res;
	string strIdDirect = strId;
	int curpos = 0;
	int lastposOut = 0;
//	char *strIdBuf = (char *)strIdDirect.c_str();
	while( curpos<(int) strId.length() )
	{
//cout << "curpos = " << curpos << ", res = " << res << endl;
		bool fIdentifier = false;
		if( (strId[curpos] == '(' || strId[curpos] == ',' || strId[curpos] == '#' ) && ( curpos == (int)strId.length()-1 || (strId[curpos+1] != '(' &&  strId[curpos+1] != '#'  ) )     )
		{
			fIdentifier = true;
		}
//cout << "Adding it: " << strId[curpos] << endl;
		res += strId[curpos];
		lastposOut ++;
		curpos ++;

		// should we search for id
		if( fIdentifier == true )
		{
//cout << "Now searching for identifier\n";
			// now scan to the right to find the position to read the identifier
			while( curpos<(int) strId.length() )
			{
				if(  strId[curpos] != ')' && strId[curpos] != ':' && strId[curpos] != ',' && strId[curpos] != '#' )
				{
					curpos++;
				}
				else
				{
					break;
				}
			}
//cout << "lastposOut: " << lastposOut << ", curpos = " << curpos << endl;
			// 
			//curpos--;
			int idnum = -1;
			string strSub = strId.substr(lastposOut, curpos-lastposOut);
			//char buftmp[100];
			//memcpy(buftmp, &strIdBuf[lastposOut], curpos-lastposOut );
			//sscanf(buftmp, "%d", &idnum);
			sscanf(strSub.c_str(), "%d", &idnum);
			string idNew = GetString(idnum);
////cout << "After searching, curpos = " << curpos << ", buftmp = " << buftmp  << ", idnum = " << idnum << ", idNew = " << idNew << endl;
//cout << "After searching, curpos = " << curpos << ", strSub = " << strSub  << ", idnum = " << idnum << ", idNew = " << idNew << endl;
			//char buf[100];
			//sprintf(buf, "%d", idNew);
			res += idNew;
			lastposOut = curpos;
		}
	}
	return res;
}

string TaxaMapper :: ExtractIdPartFromStr(const string &strIdNW)
{
    // extract id part of the string
    string strToUse = strIdNW;
    size_t posSeparator = strIdNW.find( ':' );
    
	if( posSeparator != string::npos )
	{
		strToUse = strIdNW.substr(0, (int)posSeparator  );
	}
    return strToUse;
}


int TaxaMapper :: GetIdFromStr( const string &strPart, TaxaMapper *pTMapper )
{
//cout << "GetIdFromStr: " << strPart << endl;
    
	string strToUse = strPart;
	size_t posSeparator = strPart.find( ':' );
    
	if( posSeparator != string::npos )
	{
		strToUse = strPart.substr(0, (int)posSeparator  );
	}
    
    // 05/07/15: it is also possible user add gene index (in # sign)
    size_t posSeparator2 = strToUse.find('#');
    if( posSeparator2 != string::npos )
	{
		strToUse = strToUse.substr(0, (int)posSeparator2  );
	}
//cout << "strPart: " << strPart << ",strUse: " << strToUse << endl;
    
	// get rid of 
	int res = -1;
	if( pTMapper == NULL)
	{
		sscanf( strToUse.c_str(), "%d", &res  );
//cout << "Empty mapper\n";
	}
	else
	{
		// are we reading in the first tree or not
        res = pTMapper->GetId( strToUse );
		//if( pTMapper->IsInitialized() == true )
		//{
		//	res  = pTMapper->GetId(strToUse);
//cout << "GetIdFromStr: GetId: " << strToUse << ": " << res << endl;
		//}
		//else
        if( res < 0 )
		{
            // this label is not seen before, so we add a new record
			// this is new
			res = pTMapper->AddTaxaString( strToUse );
//cout << "GetIdFromStr: New id: " << strToUse << ": " << res << endl;
		}
	}
	return res;
}

void TaxaMapper :: GetAllTaxaIds(set<int> &taxaIndices) const
{
	//
	taxaIndices.clear();
	for( map<int, string> :: const_iterator it = mapIdToStr.begin(); it != mapIdToStr.end(); ++it)
	{
		taxaIndices.insert(it->first);
	}
}

void TaxaMapper :: GetAllTaxaStrs(set<string> &setStrs) const
{
    //
    setStrs.clear();
	for( map<int, string> :: const_iterator it = mapIdToStr.begin(); it != mapIdToStr.end(); ++it)
	{
		setStrs.insert(it->second);
	}
}


void TaxaMapper :: InitToDec1Mode(int numTaxa)
{
    // assume taxa is in the format as 1, 2, 3 and so on
    // init as follows: 1 ==> 0, 2 ==> 1 and so on
    for(int taxa = 1; taxa <=numTaxa; ++taxa)
    {
        char buf[100];
        snprintf(buf,100, "%d", taxa);
        string strid = buf;
        AddTaxaString( strid );
    }
    SetInitialized(true);
}

void TaxaMapper :: Dump() const
{
    //
    cout << "curId = " << curId;
    if( fInit == true)
    {
        cout << "initialized. ";
    }
    else
    {
        cout << "not initialized yet. ";
    }
    for( map<string, int> :: const_iterator it = mapStrToId.begin(); it != mapStrToId.end(); ++it )
    {
        //
        cout << "Mapping taxa " << it->first << " to id: " << it->second << "  ";
    }
    cout << endl;
}

// ***************************************************************************
// Tree class functions
// ***************************************************************************
TreeNode :: TreeNode() :  parent(NULL), id(-1), label("-"), shape(PHY_TN_DEFAULT_SHAPE), lenBranchAbove(-1.0)
{
}

TreeNode :: TreeNode(int iid)  : parent(NULL), id(iid), label("-"), shape(PHY_TN_DEFAULT_SHAPE), lenBranchAbove(-1.0), userData(0)
{
//    id = iid;
//    cout << "Creating tree node " << iid << endl;
}

TreeNode :: ~TreeNode()
{
//cout << "Deleting tree node " << id << ", number of children: " << GetChildrenNum() << endl;
//cout << "Dump: ";
//Dump();
    // We recursively delete all its children here
    for(int i=0; i<(int)listChildren.size(); ++i)
    {
        delete listChildren[i];
    }
    listChildren.clear();
}

void TreeNode:: Dump() const
{
    //
    cout << "<node: " <<  GetLabel() << ", id=" << GetID();
    if( lenBranchAbove >= 0.0)
    {
        cout << ", length = " << lenBranchAbove;
    }
    cout << ", num of child = " << GetChildrenNum() << ">   ";
}

TreeNode * TreeNode :: Copy()
{
    // make a copy (and its descendents)
    TreeNode *pCopy = new TreeNode( GetID() );
    pCopy->SetLabel( this->GetLabel());
    pCopy->SetUserLabel( this->GetUserLabel() );
    pCopy->lenBranchAbove = this->lenBranchAbove;
    pCopy->nodeValues = this->nodeValues;
    for( int i=0; i<GetChildrenNum(); ++i )
    {
        TreeNode *pccopy = GetChild(i)->Copy();
        vector<int> listLbelsCopy;
        if( (int)this->listEdgeLabels.size() >=i+1 )
        {
            listLbelsCopy = this->listEdgeLabels[i];
        }
        pCopy->AddChild(pccopy, listLbelsCopy);
    }
    return pCopy;
}

void TreeNode :: AddChild( TreeNode *pChild, const vector<int> &labels)
{
    // This function add an edge. The edge can be labeled with a set of labels (for now, only integers)
    YW_ASSERT( pChild != NULL);

    // make sure this child is not already a children
    // not sure if really need it

    pChild->parent = this;
    listChildren.push_back( pChild );
    listEdgeLabels.push_back( labels );
}

void TreeNode :: AddEdgeLabelToChild(int cIndex, int lbl)
{
    YW_ASSERT_INFO( cIndex < GetChildrenNum(), "Overflow" );
    this->listEdgeLabels[cIndex].push_back(lbl);
}
    
void TreeNode :: RemoveChild(TreeNode *pChild)
{
	YW_ASSERT_INFO(pChild != NULL, "RemoveChild: wrong");
	pChild->parent = NULL;
    vector< TreeNode *> listChildrenNew;
    vector< vector<int> > listEdgeLabelsNew;       
	YW_ASSERT_INFO( listChildrenNew.size() == listEdgeLabelsNew.size(), "must be same size" );
	for(int i=0; i<(int) listChildren.size(); ++i)
	{
		if( listChildren[i] != pChild )
		{
			listChildrenNew.push_back( listChildren[i] );
			listEdgeLabelsNew.push_back( listEdgeLabels[i] );
		}
	}
	// update
	listChildren = listChildrenNew;
	listEdgeLabels = listEdgeLabelsNew;
}

void TreeNode :: RemoveChildren(const set<TreeNode *> &setChildren)
{
    if( setChildren.size() == 0 )
    {
        return;
    }
    for(set<TreeNode *> :: iterator it = setChildren.begin(); it != setChildren.end(); ++it)
    {
        TreeNode *pChild = *it;
        pChild->parent = NULL;
    }
    vector< TreeNode *> listChildrenNew;
    vector< vector<int> > listEdgeLabelsNew;
    YW_ASSERT_INFO( listChildrenNew.size() == listEdgeLabelsNew.size(), "must be same size" );
    for(int i=0; i<(int) listChildren.size(); ++i)
    {
        if( setChildren.find( listChildren[i] ) == setChildren.end() )
        {
            listChildrenNew.push_back( listChildren[i] );
            listEdgeLabelsNew.push_back( listEdgeLabels[i] );
        }
    }
    // update
    listChildren = listChildrenNew;
    listEdgeLabels = listEdgeLabelsNew;
}

void TreeNode :: RemoveAllChildren()
{
    // remove all children of this node
    //listChildren.clear();
    //listEdgeLabels.clear();
    while( GetChildrenNum() > 0 )
    {
        TreeNode *pc = GetChild(0);
//cout << "Removing pc = ";
//pc->Dump();
//cout << endl;
        RemoveChild(pc);
    }
//cout << "Done with removeallchildren\n";
}

void TreeNode :: DetachAllChildren()
{
    // diff from RemoveAllChildren, simply detach the children from the parent (i.e. parent no longer has record for these children)
    this->listChildren.clear();
    this->listEdgeLabels.clear();
}

void TreeNode :: DetachSelf()
{
    // detach this node from parent (but don't perform any memory release)
    TreeNode *pp = GetParent();
    
    if( pp != NULL )
    {
        //
        pp->RemoveChild(this);
    }
}

void TreeNode :: GetDescendentLabelSet( set<int> &labelSet ) 
{
    // This function accumulate the set of descendents in the label sets
    // CAUTION: assume labelset is EMPTY!!!!
    //if( IsLeaf() == true)
    //{
    string lbl = GetLabel();
//cout << "lbl = " << lbl << endl;

    if( lbl != "-" && lbl != "?" && lbl != "()" && lbl != "(?)" )
    {
        const char *buf = lbl.c_str();
        int rowIndex;
        if( buf[0] < '0' || buf[0] > '9' )
        {
            sscanf( buf+1, "%d", &rowIndex );
        }
        else
        {
            // This is a plain label, use it
            sscanf( buf, "%d", &rowIndex );
        }
//cout << "rowIndex = " << rowIndex << endl;
        labelSet.insert( rowIndex );
    }
    else if( nodeValues.size() >= 1 )
    {
            // simply insert a single value here
            //labelSet.insert( nodeValues[0] );
    }

#if 0
        // set every label into the set
        for(int i=0; i<nodeValues.size(); ++i)
        {
            if( nodeValues[i] >= 0 )
            {
                labelSet.insert( nodeValues[i] );
            }
        }
#endif
    //}
    //else
    if( IsLeaf() == false)
    {
        for(int i=0; i<GetChildrenNum(); ++i)
        {
            GetChild(i)->GetDescendentLabelSet( labelSet );
        }
    }
}

bool TreeNode :: IsAncesterOf(TreeNode *pAssumedDescend, int &branchIndex)
{
    // This function check to see if pAssumedDescend is descedent of the current node
    // If so, we also find the branch index that comes to this node
    if( pAssumedDescend == NULL)
    {
        return false;
    }
    if( pAssumedDescend == this)
    {
        branchIndex = -1;
        return true;
    }

    TreeNode *pCurrent = pAssumedDescend;
    TreeNode *pParent = pAssumedDescend->parent;

    while(pParent != NULL)
    {
        if(pParent == this)
        {
            // Find out which branch leads to it
            branchIndex = -1;
            for(int i=0; i<(int)listChildren.size();++i)
            {
                if(listChildren[i] == pCurrent)
                {
                    branchIndex = i;
                }
            }
            YW_ASSERT( branchIndex >= 0);
            // Tell the good news
            return true;
        }
        pCurrent = pParent;
        pParent = pParent->parent;
    }
    

    return false;
}

void TreeNode :: GetAllDescendents(set<TreeNode *> &setDescendents)
{
	// Note: include itself
	setDescendents.insert( this );
    for(int i=0; i<(int)listChildren.size();++i)
    {
		listChildren[i]->GetAllDescendents( setDescendents );
	}
}

void TreeNode :: GetAllLeavesUnder(set<TreeNode *> &setDescendents)
{
	// Note: include itself
    if( this->IsLeaf() == true )
    {
        setDescendents.insert( this );
    }
    for(int i=0; i<(int)listChildren.size();++i)
    {
		listChildren[i]->GetAllLeavesUnder( setDescendents );
	}
}

void TreeNode :: GetAllLeavesIdUnder(set<int> &setDescendents)
{
    set<TreeNode *> ss;
    GetAllLeavesUnder(ss);
    setDescendents.clear();
    for(set<TreeNode *> :: iterator it = ss.begin(); it != ss.end(); ++it)
    {
        setDescendents.insert( (*it)->GetID() );
    }
}

void TreeNode :: GetAllDescendIntLbls( set<int> &setIntLbs )
{
    //
    if( this->IsLeaf() == true )
    {
        setIntLbs.insert( this->GetIntLabel() );
    }
    else
    {
        for(int i=0; i<(int)listChildren.size();++i)
        {
            listChildren[i]->GetAllDescendIntLbls( setIntLbs );
        }
    }
}

void TreeNode :: GetAllLeafLabeles(vector<string> &listLeafLabels)
{
	//
	if(IsLeaf() == true)
	{
		listLeafLabels.push_back(GetLabel());
	}
	else
	{
		for(int i=0; i<(int)listChildren.size();++i)
		{
			listChildren[i]->GetAllLeafLabeles( listLeafLabels );
		}
	}
}
void TreeNode :: GetAllLeafIntLabeles( vector<int> &listLeafLabels )
{
    //
    if(IsLeaf() == true)
	{
		listLeafLabels.push_back(GetIntLabel());
	}
	else
	{
		for(int i=0; i<(int)listChildren.size();++i)
		{
			listChildren[i]->GetAllLeafIntLabeles( listLeafLabels );
		}
	}
}

void TreeNode :: GetAllDistinctLeafLabeles(set<string> &setLeafLabels)
{
    //
    vector<string> listLeafLabels;
    GetAllLeafLabeles( listLeafLabels );
    PopulateSetByVecGen( setLeafLabels, listLeafLabels);    
}


string TreeNode :: GetShapeLabel(const set<int> &idTerms, map<int,int> &mapNodeLabel) const
{
//cout << "idTerms = ";
//DumpIntSet( idTerms );
	string res;

	// return a shape label:
	// at present, shape label is like ((),(())). That is, no leaf labels
	// just the type of topology. Note if we have (S1,S2), then S1 <= S2
	if( idTerms.find(GetID() ) != idTerms.end() )
	{
		int idNum = 1;
		if(mapNodeLabel.find(GetID() ) != mapNodeLabel.end() )
		{
			idNum = mapNodeLabel[ GetID() ];
		}
		char buf[100];
		snprintf(buf,100, "%d", idNum);
		res = buf;
		//string str1 = "A";
		//return str1;
	}
	//else
	//	{
	//		string strEmpty;
	//		res = strEmpty;
	//	}
	//}
	else
	{
		// otherwise get its descendent
		vector<string> listLabels; 
		for(int i=0; i<(int)listChildren.size();++i)
		{
			listLabels.push_back( listChildren[i]->GetShapeLabel( idTerms, mapNodeLabel ) ) ;
		}
		// now sort it
		for(int i=0;i<(int)listLabels.size();++i)
		{
			for(int j=i+1; j<(int)listLabels.size();++j)
			{
				// swap if needed
				if( listLabels[i] > listLabels[j] )
				{
					string tmp = listLabels[i];
					listLabels[i] = listLabels[j];
					listLabels[j] = tmp;
				}
			}
		}

		// how many are not empty?
		int numNonEmpty = 0;
		for( int i=0; i<(int)listLabels.size(); ++i )
		{
			if( listLabels[i].length() > 0 )
			{
				numNonEmpty ++;
			}
		}

		// add it
		bool fStart = false;
		for( vector<string> :: iterator it = listLabels.begin(); it != listLabels.end(); ++it )
		{
			if( it->length() > 0 )
			{
				if( fStart == false)
				{
					if(  numNonEmpty > 1 )
					{
						// add a header
						res = "(";
					}
				}
				else
				{
					res += ",";
				}
				res += *it;

				fStart = true;
			}
		}
		if( fStart == true  && numNonEmpty > 1)
		//if( fStart == true  )
		{
			res += ")";
		}
	}
//cout << "res label for this node: " << res << endl;
	return res;
}


// differeent from above, this one will apply label to the string label
string TreeNode :: GetShapeLabel(const set<int> &idTerms, bool fSort) const
{
//cout << "idTerms = ";
//DumpIntSet( idTerms );
	string res;

	// return a shape label:
	// at present, shape label is like ((),(())). That is, no leaf labels
	// just the type of topology. Note if we have (S1,S2), then S1 <= S2
	if( idTerms.find(GetID() ) != idTerms.end() )
	{
		//int idNum = 1;
        if( fSort == true)
        {
            res = "1";
        }
        else
        {
            char buf[100];
            snprintf(buf,100, "%d", GetID() );
            res = buf;
        }
	}

	else
	{
		// otherwise get its descendent
		vector<string> listLabels; 
		for(int i=0; i<(int)listChildren.size();++i)
		{
			listLabels.push_back( listChildren[i]->GetShapeLabel( idTerms, fSort ) ) ;
		}
		// now sort it
        if( fSort == true )
        {
            for(int i=0;i<(int)listLabels.size();++i)
            {
                for(int j=i+1; j<(int)listLabels.size();++j)
                {
                    // swap if needed
                    if( listLabels[i] > listLabels[j] )
                    {
                        string tmp = listLabels[i];
                        listLabels[i] = listLabels[j];
                        listLabels[j] = tmp;
                    }
                }
            }
        }

		// how many are not empty?
        int numNonEmpty = 0;   //, numEmpty = 0;
		for( int i=0; i<(int)listLabels.size(); ++i )
		{
			if( listLabels[i].length() > 0 )
			{
				numNonEmpty ++;
			}
			//else
			//{
			//	numEmpty ++;
			//}
		}

		// add it
		bool fStart = false;
		//bool fFirst = true;
        bool fParenth = false;
		//bool fSpaceAdded = false;
		for( vector<string> :: iterator it = listLabels.begin(); it != listLabels.end(); ++it )
		{
            // YW: only add "(" if there are more than 1 non-empty below
			if( fStart == false && it->length()> 0 )
			{
                // YW: just add a "("
				//if(  (numNonEmpty >= 1 && numEmpty > 0 ) || numNonEmpty >= 2  )
				//{
                // add a header
                if( numNonEmpty > 1 )
                {
                    res = "(";
                    fParenth = true;
                }
                res += *it;
                fStart = true;
				//}
			}
			else if(  fStart == true )
			{
                // YW: only add "," if there is something
				if( it->length()>0)
				{
					res += ",";
				}
				//fFirst = false;
				if(  it->length() > 0 )
				{

					res += *it;
					//fStart = true;
				}
                // YW: donot add anything if the branch is empty
#if 0
				else
				{
					// for empty branches, put a mark to it
					// when there is something under it (that is shrink the entire subtree of unknown to a symbol -
					if(numNonEmpty >= 1 && fSpaceAdded == false)
					{
						// 
						res += ",-";
						fSpaceAdded = true;
					}
				}
#endif
			}
		}
		//if( fStart == true  && numNonEmpty >= 1)
		if( fParenth == true  )
		{
			res += ")";
		}
	}
//cout << "res label for this node: " << res << endl;
	return res;
}

string TreeNode:: GetShapeLabelNodeBrNum( map<TreeNode *, pair<int,int> > &mapNodeNumBrannches, vector<int> &listOrderedLeaves)
{
    // format: <num of underlying branches, event id>, negative for internal nodes
    // the ordered leaves: correspond to their order of appearing in the output newick shape string
    // this can be useful when you want to know how to match the leaves when some sort of comparision is needed
    // get shape label. Different from above, the input is: <treenode, #ofbranches out of this node>
    // convention: if #br < 0, it means all branches have descendents
    listOrderedLeaves.clear();
    if( this->IsLeaf() == true)
    {
        YW_ASSERT_INFO( mapNodeNumBrannches.find(this) != mapNodeNumBrannches.end(), "Leaf: not in map" );
//cout << "Find one leaf: " << mapNodeNumBrannches[this].second << endl;
        listOrderedLeaves.push_back( mapNodeNumBrannches[this].second );
        return string("()");
    }
    else
    {
        YW_ASSERT_INFO(mapNodeNumBrannches.find(this) != mapNodeNumBrannches.end(), "Fail to find222");
        //const TreeNode *pn = const_cast<const TreeNode *>( this );
        int numBrWOChildRecur = mapNodeNumBrannches[this].first;
//cout << "numBrWOChildRecur = " << numBrWOChildRecur << endl;
        multiset<string> setDescStrings;
        map<string, set< vector<int> > > mapStringToVecLeaves;
        for(int i=0; i<(int)GetChildrenNum(); ++i)
        {
            //
            TreeNode *pnchild = GetChild(i);
            //
            if( mapNodeNumBrannches.find(pnchild) != mapNodeNumBrannches.end() )
            {
                //
                vector<int> listOrderedLeavesStep;
                string str = pnchild->GetShapeLabelNodeBrNum(mapNodeNumBrannches, listOrderedLeavesStep);
                setDescStrings.insert(str);
                if( mapStringToVecLeaves.find( str) == mapStringToVecLeaves.end() )
                {
                    //
                    set<vector<int> > ssint;
                    mapStringToVecLeaves.insert( map<string, set<vector<int> > > :: value_type(str, ssint) );
                }
                mapStringToVecLeaves[str].insert( listOrderedLeavesStep );
                
                //
                --numBrWOChildRecur;
            }
        }
        // add the remaiing by just filling the item
        //vector<int> listLvIds;
        for(int i=0; i<numBrWOChildRecur; ++i)
        {
            string strLv = "()";
            setDescStrings.insert(strLv);
            
            //
            if( mapStringToVecLeaves.find( strLv) == mapStringToVecLeaves.end() )
            {
                //
                set<vector<int> > ssint;
                mapStringToVecLeaves.insert( map<string, set<vector<int> > > :: value_type(strLv, ssint) );
            }
            vector<int> vec1;
            vec1.push_back( mapNodeNumBrannches[this].second );
            mapStringToVecLeaves[strLv].insert( vec1 );
        }
//cout << "setdescstrings: ";
//for(multiset<string> :: iterator itgg = setDescStrings.begin(); itgg != setDescStrings.end(); ++itgg)
//{
//cout << *itgg << "   ";
//}
//cout << endl;
        // now creat the contacation
        YW_ASSERT_INFO(setDescStrings.size() > 1, "Can not be empty2");
        string res = "(";
        for(multiset<string> :: iterator it = setDescStrings.begin(); it !=setDescStrings.end(); ++it)
        {
            if( it != setDescStrings.begin() )
            {
                res += ",";
            }
            res += *it;
        }
        res += ")";
        
        // now assemble the list of ordered nodes
        for( map<string, set<vector<int> > > :: iterator itg = mapStringToVecLeaves.begin(); itg != mapStringToVecLeaves.end(); ++itg  )
        {
            for( set<vector<int> > :: iterator itg2 = itg->second.begin(); itg2 != itg->second.end(); ++itg2 )
            {
//cout << "In GetShapeLabelNodeBrNum: find a vector of sites: ";
//DumpIntVec(*itg2);
                ConcatIntVec( listOrderedLeaves, *itg2 );
            }
        }
        
        return res;
    }
}

int TreeNode :: GetLevel() const
{
	// choose a not efficient but simple coding
	int res = 0;
	for(int i=0; i<(int)listChildren.size();++i)
	{
		int lvDesc = listChildren[i]->GetLevel( );
		if( lvDesc + 1 > res )
		{
			res = lvDesc + 1;
		}
	}
	return res;
}

void TreeNode :: GetEdgeLabelsToChild( TreeNode *pChild, vector<int> &lbls )
{
	YW_ASSERT_INFO(listChildren.size() == listEdgeLabels.size(), "Child num and edge label num do not match");
	lbls.clear();
	for(int i=0; i<(int)listChildren.size();++i)
	{
		if(listChildren[i] == pChild  )
		{
			GetEdgeLabelsAtBranch(i, lbls);
		}
	}
	//YW_ASSERT_INFO(false, "GetEdgeLabelsToChild :: Fail to find such child");
}

TreeNode * TreeNode :: GetMRCA(TreeNode *pOther)
{
	TreeNode *pRes = this;
	int dummy;
	while( pRes != NULL && pRes->IsAncesterOf( pOther, dummy ) ==  false )
	{
		pRes = pRes->GetParent();
	}
	YW_ASSERT_INFO(pRes != NULL, "Fail to find MRCA");
	return pRes;
}

double TreeNode :: GetDistToAncesNode(TreeNode *pAncNode)
{
    // get the total dist from this node to its ancestor
    double distTot = 0.0;
    TreeNode *pnCurr = this;
    while(pnCurr != pAncNode && pnCurr != NULL )
    {
        distTot += pnCurr->GetLength();
        pnCurr = pnCurr->GetParent();
    }
    return distTot;
}

int TreeNode :: GetNumEdgesToAncestor(TreeNode *pAssumedAncestor)
{
    // get # of edges betwene this node to its ancestor
    // return -1 if the ancestor is not true ancestor
    int res = 0;
    TreeNode *pRes = this;
	while( pRes != NULL && pRes != pAssumedAncestor )
	{
        ++res;
		pRes = pRes->GetParent();
	}
	if(pRes == NULL)
    {
        res = -1;
    }
    
    return res;
}

void TreeNode :: GetSiblings( vector<TreeNode *> &listSibs )
{
	// siblings are parent's children (except itself)
	listSibs.clear();
	if( this->GetParent() != NULL )
	{
		//
		for(int i=0; i<this->GetParent()->GetChildrenNum(); ++i)
		{
			TreeNode *pn = this->GetParent()->GetChild(i);
			if( pn != this)
			{
				listSibs.push_back( pn );
			}
		}
	}

}

void TreeNode :: Order()
{
	// do nothing if leaf
	if( IsLeaf() == true )
	{
		return;
	}
	// first order the leaves
	for(int i=0; i<(int)listChildren.size();++i)
	{
		listChildren[i]->Order();
	}

	// 
	vector<multiset<string> > listDescLeaves;
	for(int i=0; i<(int)listChildren.size();++i)
	{
		vector<string> vecLeafStrings;
		listChildren[i]->GetAllLeafLabeles(vecLeafStrings);
		multiset<string> setLeafStrings;
		for(int j=0; j<(int)vecLeafStrings.size(); ++j)
		{
			setLeafStrings.insert(vecLeafStrings[j]);
		}
		listDescLeaves.push_back(setLeafStrings);
	}
	// 
	YW_ASSERT_INFO(listEdgeLabels.size() == listChildren.size(), "Same size must be");
	for(int i=0; i<(int)listChildren.size();++i)
	{
		for(int j=i+1; j<(int)listChildren.size();++j)
		{
			// 
			if( listDescLeaves[i] > listDescLeaves[j] )
			{
				// exhcnage everything
				TreeNode *ptmp = listChildren[i];
				listChildren[i] = listChildren[j];
				listChildren[j] = ptmp;

				vector<int> vtmp = listEdgeLabels[i];
				listEdgeLabels[i] = listEdgeLabels[j];
				listEdgeLabels[j] = vtmp;

				// 
				multiset<string> stmp = listDescLeaves[i];
				listDescLeaves[i] = listDescLeaves[j];
				listDescLeaves[j] = stmp;
			}
		}
	}
}

int TreeNode :: GetIntLabel() const
{
	int res = -1;
	sscanf(label.c_str(), "%d", &res );
	return res;
}

void TreeNode :: SetIntLabel(int lbl)
{
    //
    char buf[1024];
    snprintf(buf,1024, "%d", lbl);
    label = buf;
}

bool TreeNode :: IsMulfurcate()
{
	if( IsLeaf() == true)
	{
		return false;
	}
	else
	{
		if( GetChildrenNum() > 2)
		{
			return true;
		}
		for(int ii=0; ii<GetChildrenNum(); ++ii)
		{
			if( GetChild(ii)->IsMulfurcate() == true )
			{
				return true;
			}
		}

		return false;
	}
}

TreeNode * TreeNode :: GetRoot() const
{
    TreeNode *pself = const_cast<TreeNode *>(this);
    TreeNode *proot = pself;
    while( proot->GetParent() != NULL )
    {
        proot = proot->GetParent();
    }
    YW_ASSERT_INFO(proot != NULL, "Root is null");
    return proot;
}

void TreeNode :: GetAllAncestors(set<TreeNode *> &listAncestors)
{
    if( GetParent() != NULL )
    {
        listAncestors.insert(GetParent() );
        GetParent()->GetAllAncestors(listAncestors);
    }
}

void TreeNode :: GetAllChildren(set<TreeNode *> &setChildren) const
{
    //
    //TreeNode *pthis = const_cast<TreeNode *>(this);
    //PopulateSetByVecGen( setChildren, pthis->listChildren );
    setChildren.clear();
    for(int i=0; i<GetChildrenNum(); ++i)
    {
        setChildren.insert( listChildren[i] );
    }
}

int TreeNode :: GetChildIndex(TreeNode *pchild) const
{
    // get the index of this particular child; if not found, the error
    TreeNode *pself = const_cast<TreeNode *>(this);
    int res = -1;
    for(int i=0; i<(int)listChildren.size(); ++i)
    {
        if( pself->GetChild(i) == pchild )
        {
            res = i;
            break;
        }
    }
    YW_ASSERT_INFO(res >=0, "Fail to find666");
    return res;
}

void TreeNode :: RemoveLabels()
{
    // remove all edge labels (i.e. make them empty)
    int numLLs = listEdgeLabels.size();
    listEdgeLabels.clear();
    listEdgeLabels.resize( numLLs );
    
    // then reurrisve do it
    for(int i=0; i<GetChildrenNum(); ++i)
    {
        GetChild(i)->RemoveLabels();
    }
}

void TreeNode :: RemoveLabelsPar()
{
    // remove the parent to this node's label
    TreeNode *ppar = GetParent();
    if( ppar == NULL )
    {
        return;
    }
    int childIndex = ppar->GetChildIndex(this);
    YW_ASSERT_INFO( childIndex <(int) ppar->listEdgeLabels.size(), "Overflow" );
    ppar->listEdgeLabels[childIndex].clear();
}

void TreeNode :: IncEdgeLabelsBy(int offset, bool fSub)
{
    //
    for(int i=0; i<(int)listEdgeLabels.size(); ++i)
    {
        for( int j=0; j<listEdgeLabels[i].size(); ++j )
        {
            listEdgeLabels[i][j] += offset;
        }
    }
    if( fSub )
    {
        for(int i=0; i<(int)listChildren.size(); ++i)
        {
            listChildren[i]->IncEdgeLabelsBy(offset, fSub);
        }
    }
}

void TreeNode :: Binarize(int &idToUseNext)
{
    // recursively make the tree binary
    // if this node has more than 2 children, create a new internal node
    if( GetChildrenNum() > 2 )
    {
        //
        TreeNode *pnode = new TreeNode(idToUseNext++);
        for(int i=1; i<GetChildrenNum(); ++i)
        {
            vector<int> ss;
            pnode->AddChild( GetChild(i), ss );
        }
        TreeNode *pn1 = GetChild(0);
        this->listChildren.clear();
        this->listChildren.push_back( pn1 );
        vector<int> ss;
        AddChild( pnode, ss );
    }
    
    for( int i=0; i<GetChildrenNum(); ++i )
    {
        //
        GetChild(i)->Binarize( idToUseNext );
    }
}

int TreeNode :: GetMaxIdWithinSubtree( ) const
{
    //
    int res = GetID();
    TreeNode *pthis = const_cast<TreeNode *> (this);
    for( int i=0; i<GetChildrenNum(); ++i)
    {
        TreeNode *pnc = pthis-> GetChild(i) ;
        int nc = pnc->GetMaxIdWithinSubtree();
        if( nc > res  )
        {
            //
            res = nc;
        }
    }
    return res;
}

int TreeNode :: GetNumNodesUnder(bool fInternalOnly, bool fAddNonBinary) const
{
    // fInternalOnly: true if only count internal node
    // include itself if this is an internal node
    // fAddNonBinary: true if an internal node is considered to have multiple (hidden) nodes
    int res = 0;
    if( fInternalOnly == false || IsLeaf() == false )
    {
        res = 1;
    }
    // recursively check all children
    TreeNode *pn = const_cast<TreeNode *>(this);
    for(int i=0; i<GetChildrenNum(); ++i)
    {
        res += pn->GetChild(i)->GetNumNodesUnder(fInternalOnly, fAddNonBinary);
    }
    return res;
}

TreeNode * TreeNode :: RefineAt( set<TreeNode *> &subsetChildrenClade )
{
    // create a new clade below this node which contains the children as passed in
    // return the newly created internal node
    if( subsetChildrenClade.size() <= 1 || (int)subsetChildrenClade.size() >= GetChildrenNum() )
    {
        // nothing to refine
        return NULL;
    }
    // remove the child first
    RemoveChildren(subsetChildrenClade);

    // create a new child
    TreeNode *pnNew = new TreeNode;
    // add child
    vector<int> vecDummy;
    for(set<TreeNode *> :: iterator it = subsetChildrenClade.begin(); it != subsetChildrenClade.end(); ++it )
    {
        TreeNode *pc = *it;
        pnNew->AddChild(pc, vecDummy);        // ignore edge labels for now
    }
    AddChild(pnNew, vecDummy);
    return pnNew;
}

// ***************************************************************************
// Utilites functions
// ***************************************************************************

void PhylogenyTreeIteratorBacktrack :: Init()
{
    while( stackNodesToExplore.empty() == false)
    {
        stackNodesToExplore.pop();
    }
//cout << "Nnow stack empty.\n";
    // Now recurisvely store the order of the walk
	TreeNode *rootNode = phyTree.GetRoot();
    if( rootNode != NULL)
    {
		stackNodesToExplore.push(rootNode);
    }
}

void PhylogenyTreeIteratorBacktrack :: Next()
{
    if( stackNodesToExplore.empty() == true)
    {
        return;
    }
    TreeNode *pn = stackNodesToExplore.top();
	// push its descendent in
    stackNodesToExplore.pop();
    for(int i=0; i<(int)pn->GetChildrenNum(); ++i)
	{
		//
		stackNodesToExplore.push( pn->GetChild(i) );
	}
}
void PhylogenyTreeIteratorBacktrack :: Back()
{
    if( stackNodesToExplore.empty() == true)
    {
        return;
    }
	// simply get rid of the current node
    stackNodesToExplore.pop();
}

bool PhylogenyTreeIteratorBacktrack :: IsDone()
{
	return stackNodesToExplore.empty();
}

TreeNode *PhylogenyTreeIteratorBacktrack :: GetCurrNode()
{
	if( IsDone() == false)
	{
		return stackNodesToExplore.top();
	}
	else
	{
		return NULL;
	}
}

///////////////////////////////////////////////////////////////////
void PhylogenyTreeIterator :: Init()
{
    while( stackPostorder.empty() == false)
    {
        stackPostorder.pop();
    }
//cout << "Nnow stack empty.\n";
    // Now recurisvely store the order of the walk
	TreeNode *rootNode = phyTree.GetRoot();
    if( rootNode != NULL)
    {
        phyTree.PostOrderPushStack( rootNode,  stackPostorder);
    }
}

void PhylogenyTreeIterator :: Next()
{
    if( stackPostorder.empty() == true)
    {
        return;
    }
    //TreeNode *pn = stackPostorder.top();
    stackPostorder.pop();
}

bool PhylogenyTreeIterator :: IsDone()
{
	return stackPostorder.empty();
}

TreeNode *PhylogenyTreeIterator :: GetCurrNode()
{
	if( IsDone() == false)
	{
		return stackPostorder.top();
	}
	else
	{
		return NULL;
	}
}


///////////////////////////////////////////////////////////////////
void PhylogenyTreeIteratorPreOrder :: Init()
{
    while( stackPreorder.empty() == false)
    {
        stackPreorder.pop();
    }
    //cout << "Nnow stack empty.\n";
    // Now recurisvely store the order of the walk
    TreeNode *pRoot = phyTree.GetRoot();
    if( pRoot != NULL)
    {
        phyTree.PreOrderPushStack( pRoot,  stackPreorder);
    }
}

void PhylogenyTreeIteratorPreOrder :: Next()
{
    if( stackPreorder.empty() == true)
    {
        return;
    }
    //TreeNode *pn = stackPostorder.top();
    stackPreorder.pop();
}

bool PhylogenyTreeIteratorPreOrder :: IsDone()
{
    return stackPreorder.empty();
}

TreeNode *PhylogenyTreeIteratorPreOrder :: GetCurrNode()
{
    if( IsDone() == false)
    {
        return stackPreorder.top();
    }
    else
    {
        return NULL;
    }
}



// ***************************************************************************
// Main functions
// ***************************************************************************

PhylogenyTreeBasic :: PhylogenyTreeBasic() :  rootNode(NULL), numLeaves(-1)
{
}

PhylogenyTreeBasic :: ~PhylogenyTreeBasic()
{
//cout << "Deleting tree: ";
//Dump();
    
    // Should delete the tree
    if( rootNode != NULL)
    {
        delete rootNode;
        rootNode = NULL;
    }
}

PhylogenyTreeBasic * PhylogenyTreeBasic :: Copy()
{
    PhylogenyTreeBasic *pCopy = new PhylogenyTreeBasic;
    pCopy->numLeaves = pCopy->numLeaves;
    pCopy->SetRoot( this->GetRoot()->Copy()  );
    return pCopy;
}

void PhylogenyTreeBasic :: PostOrderPushStack( TreeNode *treeNode,  stack<TreeNode *> &stackPostorder)
{
    stackPostorder.push( treeNode);
//cout << "Pusing node " << treeNode->GetLabel() << endl;

    for(int i=0; i<(int)treeNode->listChildren.size(); ++i)
    {
        PostOrderPushStack( treeNode->listChildren[i],  stackPostorder);
    }
}

void PhylogenyTreeBasic :: PreOrderPushStack( TreeNode *treeNode,  stack<TreeNode *> &stackPreorder)
{
    for(int i=0; i<(int)treeNode->listChildren.size(); ++i)
    {
        PreOrderPushStack( treeNode->listChildren[i],  stackPreorder);
    }
    stackPreorder.push(treeNode);
    //cout << "Pusing node " << treeNode->GetLabel() << endl;
}

void PhylogenyTreeBasic :: ConsOnNewick( const string &nwString, int numLeaves, bool fBottomUp, TaxaMapper *pTMapper )
{
    // Here we try to reconstruct from a newick string here
    // This function creates the tree by creating and linking tree nodes
    // Make sure the tree is empty
    if( rootNode != NULL)
    {
        delete rootNode;
        rootNode = NULL;
    }

    // we perform this by recursively
    int invId = 1000000;
	if( numLeaves > 0)
	{
		// here we assume leaf id starts from 0, will check it
		invId = numLeaves ;
	}
	int leafId = 0;
	rootNode = ConsOnNewickSubtree( nwString, leafId, invId, numLeaves, fBottomUp, pTMapper );
}

void PhylogenyTreeBasic :: ConsOnNewickDupLabels( const string &nwString, TaxaMapper *pTMapper  )
{
    // Here we try to reconstruct from a newick string here
    // This function creates the tree by creating and linking tree nodes
    // Make sure the tree is empty
    if( rootNode != NULL)
    {
        delete rootNode;
        rootNode = NULL;
    }

    // we perform this by recursively
	int numLeaves = GetNewickNumLeaves(nwString);
	// we start counting leaves from 0 
    int invId = numLeaves;
	int leafId = 0;
//cout << "Num of leaves = " << numLeaves << endl;
	rootNode = ConsOnNewickSubtreeDupLabels( nwString, invId, leafId, pTMapper );
}

// ********************************************************************************
// Utitlieis for construcing edge label trees

static int GetEdgeLabelPosFrom(const string &strMutTreeCur, int posCur)
{
    //
    int posCurGNTPF = posCur;
    while( posCurGNTPF < (int)strMutTreeCur.length()  )
    {
//printf "getNextTaxaPosFrom: %d: curr ch: %s\n", posCurGNTPF, substr(strMutTreeCur,posCurGNTPF,1);
        if( strMutTreeCur[posCurGNTPF] == '#'  )
        {
            break;
        }
        ++posCurGNTPF;
    }
    if(posCurGNTPF >= (int)strMutTreeCur.length() )
    {
        posCurGNTPF=-1;
    }
    return posCurGNTPF;
}

static int getNextTaxaPosFromLevelUp(const string &strMutTreeCur, int posCur)
{
    int posCurGNTPF = posCur;
    int level=0;
    bool fUpperOnly = false;
    while( posCurGNTPF < (int)strMutTreeCur.length()   )
    {
        char chGNTPF=strMutTreeCur[posCurGNTPF];
        if( chGNTPF == '#' && ((level>=0 && fUpperOnly==false ) || level>0) )
        {
            break;
        }
        if( chGNTPF =='('  )
        {
            --level;
        }
        else if( chGNTPF==')' )
        {
            ++level;
        }
        else if(chGNTPF == ',')
        {
            fUpperOnly = true;
        }
        
        ++posCurGNTPF;
    }
    if(posCurGNTPF >=  (int)strMutTreeCur.length()  )
    {
        posCurGNTPF=-1;
    }
    return posCurGNTPF;
}

static string getTaxaAt(const string &strMutTreeCur, int posCur)
{
    int posGTA=posCur;
    if(strMutTreeCur[posCur] == '#')
    {
        posGTA=posCur+1;
    }
    //  now find where it ends
    int posGTA2=posGTA;
    while(posGTA2<(int)strMutTreeCur.length())
    {
        char chGTA= strMutTreeCur[posGTA2];
        if(chGTA=='#' || chGTA==',' || chGTA==')' )
        {
            break;
        }
        ++posGTA2;
    }
    if(posGTA2>(int)strMutTreeCur.length() )
    {
        posGTA2=(int)strMutTreeCur.length()-1;
    }
    return strMutTreeCur.substr( posGTA, posGTA2-posGTA );
}

void PhylogenyTreeBasic :: ConsOnNewickEdgeLabelTree(const string &nwString)
{
    // view each edge label as taxon; a stand-alone edge label is the leaf;
    // edge label may or may not have a leading seperator (# in this implementation);
    // e.g. ((#1,#2#3)#4)  this give four node, one for each edge label
    if( rootNode != NULL)
    {
        delete rootNode;
        rootNode = NULL;
    }
    // find all edge labels and how they are related
    map<string, string> mapEdgeLabelPar;
    int posEdgeLbl = 0;
    while( posEdgeLbl < (int)nwString.length() )
    {
        //
        posEdgeLbl = GetEdgeLabelPosFrom(nwString, posEdgeLbl);
        if(posEdgeLbl < 0 )
        {
            break;
        }
        string strTaxon = getTaxaAt(nwString, posEdgeLbl);
        // find its parent
        int posEdgeLblPar = getNextTaxaPosFromLevelUp( nwString, posEdgeLbl+1 );
        string strPar;
        if(posEdgeLblPar >= 0)
        {
            //
            strPar = getTaxaAt(nwString, posEdgeLblPar);
        }
        mapEdgeLabelPar[strTaxon] = strPar;
//cout << "Taxon: " << strTaxon << " is child of " << strPar << endl;
        ++posEdgeLbl;
    }
    // now create nodes
    int nidNext=1;
    this->rootNode = new TreeNode(nidNext++);
    string strLblRoot="-";
    int posRootLbl = -1;
    std::size_t pos1 = nwString.find_last_of(')');
    std::size_t pos2 = nwString.find_last_of('#');
    if( pos1 != string::npos && pos2 != string::npos  )
    {
        posRootLbl = max(pos1,pos2);
    }
    else if(pos1 != string::npos)
    {
        posRootLbl = pos1;
    }
    else if(pos2 != string::npos)
    {
        posRootLbl = pos2;
    }
    if(posRootLbl >= 0 )
    {
        strLblRoot = getTaxaAt(nwString, posRootLbl);
    }

//cout << "root label: " << strLblRoot << endl;
    // now create all descendents
    map<string, TreeNode *> mapNodes;
    mapNodes[strLblRoot] = this->rootNode;
    while(true)
    {
        // find direct descendents
        TreeNode *pnPar = NULL;
        string strChildUse;
        for(map<string,string> :: iterator it = mapEdgeLabelPar.begin(); it != mapEdgeLabelPar.end(); ++it )
        {
            string strChild = it->first;
            string strPar = it->second;
            if( mapNodes.find(strChild) == mapNodes.end() && mapNodes.find(strPar) != mapNodes.end() )
            {
                pnPar = mapNodes[strPar];
                strChildUse = strChild;
            }
        }
        if(pnPar == NULL )
        {
            break;
        }
        TreeNode *pnode = new TreeNode(nidNext++);
        pnode->SetLabel(strChildUse);
        vector<int> listLblsDummy;
        pnPar->AddChild( pnode, listLblsDummy );
        
        mapNodes[strChildUse] = pnode;
    }
    
    if(strLblRoot.length()==0)
    {
        strLblRoot = "-";
    }
    this->rootNode->SetLabel(strLblRoot);
}

void PhylogenyTreeBasic :: InitPostorderWalk( )
{
//cout << "InitPostorderWalk() entry\n";
    // when walk, return the value of the node if any
    // Clearup the previous storage if any
    while( stackPostorder.empty() == false)
    {
        stackPostorder.pop();
    }
//cout << "Nnow stack empty.\n";
    // Now recurisvely store the order of the walk
    if( rootNode != NULL)
    {
        PostOrderPushStack( rootNode,  stackPostorder);
    }
}

TreeNode *PhylogenyTreeBasic :: NextPostorderWalk( )
{
    // Return false, when nothing to go any more
    if( stackPostorder.empty() == true)
    {
        return NULL;
    }
    TreeNode *pn = stackPostorder.top();
    stackPostorder.pop();

//    node = pn;
#if 0
    if( pn->nodeValues.size() > 0 )
    {
        // There is valid node value stored here
        nodeValue = pn->nodeValues[0];
    }
    else
    {
        nodeValue = -1;     // no node value is stored here
    }
#endif
    return pn;
}

void PhylogenyTreeBasic :: OutputGML ( const char *inFileName )
{
	// Now output a file in GML format
	// First create a new name
	string name = inFileName;
//cout << "num edges = " << listEdges.size() << endl;

	DEBUG("FileName=");
	DEBUG(name);
	DEBUG("\n");
	// Now open file to write out
	ofstream outFile( name.c_str() );

	// First output some header info
	outFile << "graph [\n"; 
	outFile << "comment ";
	OutputQuotedString(outFile, "Automatically generated by Graphing tool");
	outFile << "\ndirected  1\n";
	outFile << "id  1\n";
	outFile << "label ";
	OutputQuotedString ( outFile, "Phylogeny Tree....\n");

	// Now output all the vertices
//	int i;
	stack<TreeNode *> nodesStack;
    if( rootNode != NULL)
    {
        nodesStack.push( rootNode );
    }
//cout << "a.1.1\n";
	while(  nodesStack.empty() == false )
	{
        TreeNode *pn = nodesStack.top();
        nodesStack.pop();

		outFile << "node [\n";

		outFile << "id " <<  pn->id  << endl;
		outFile << "label ";
 		string nameToUse = " ";
        if( pn->GetLabel()  != "-" )
        {
          nameToUse = pn->GetLabel();
        }
#if 0
        else
        {
            // we take the nonde value here
            char buf[100];
            if( pn->nodeValues.size() > 0 )
            {
                sprintf(buf, "(%d)", pn->nodeValues[0] );        // CAUTION, here we assume each leaf has exactly 1 label
                nameToUse = buf;
            }
            else
            {
                // if no nodes value is set, still use label
         //       nameToUse = pn->GetLabel();

                // YW: TBD change
                nameToUse.empty();
            }
        }
#endif
        const char *name = nameToUse.c_str();

// 		char name[100];
//       if( pn->IsLeaf() == false)
//        {
//		    name[0] = 'v'; 
//		    sprintf(&name[1], "%d", pn->id);
//        }
//        else
//        {
            // For leaf, we simply output their value (row number)
//            sprintf(name, "%d", pn->nodeValues[0] );        // CAUTION, here we assume each leaf has exactly 1 label
//        }
        OutputQuotedString (outFile,  name  ); 
		outFile << endl;

        // See if we need special shape here
        if( pn->GetShape() == PHY_TN_RECTANGLE)
        {
            outFile << "vgj [ \n shape  ";
            OutputQuotedString( outFile, "Rectangle");
    		outFile << "\n]\n";
        }
        else
        {
		    outFile << "defaultAtrribute   1\n";
        }
        
		outFile << "]\n";

        // Now try to get more nodes
        for(int i=0; i<(int)pn->listChildren.size(); ++i)
        {
            nodesStack.push( pn->listChildren[i] );
        }
//cout << "a.1.2\n";
	}
//cout << "a.1.3\n";

	// Now output all the edges, by again starting from root and output all nodes
    YW_ASSERT( nodesStack.empty() == true );
    if( rootNode != NULL)
    {
        nodesStack.push( rootNode );
    }
	while(  nodesStack.empty() == false )
	{
        TreeNode *pn = nodesStack.top();
        nodesStack.pop();
        
        for(int i=0; i<(int)pn->listChildren.size(); ++i)
        {
        
//cout << "Output an edge \n"; 
			outFile << "edge [\n";
			outFile << "source " << pn->id << endl; 
			outFile << "target  " << pn->listChildren[i]->id << endl; 
			outFile << "label " ;
            if( pn->listEdgeLabels[i].size() >0 )
            {
                string lblName;
		        char name[100];
//		        name[0] = 'e'; 
                for(int iel =0; iel<(int)pn->listEdgeLabels[i].size(); ++iel )
                {
		            snprintf(name,100, "e%d  ", pn->listEdgeLabels[i][iel]  );
                    lblName += name;
                }
			    OutputQuotedString( outFile,  lblName.c_str()  );
            }
            else
            {
			    OutputQuotedString( outFile,  ""  );
            }
			outFile << "\n";
			outFile << "]\n";
    
            // Store next one to stack
            nodesStack.push( pn->listChildren[i] );
		}
	}


	// Finally quite after closing file
	outFile << "\n]\n";
	outFile.close();
}

void PhylogenyTreeBasic :: OutputGMLNoLabel(const char *inFileName )
{
    //
    // Now output a file in GML format
    // First create a new name
    string name = inFileName;
    //cout << "num edges = " << listEdges.size() << endl;
    
    DEBUG("FileName=");
    DEBUG(name);
    DEBUG("\n");
    // Now open file to write out
    ofstream outFile( name.c_str() );
    
    // First output some header info
    outFile << "graph [\n";
    outFile << "comment ";
    OutputQuotedString(outFile, "Automatically generated by Graphing tool");
    outFile << "\ndirected  1\n";
    outFile << "id  1\n";
    outFile << "label ";
    OutputQuotedString ( outFile, "Phylogeny Tree....\n");
    
    // Now output all the vertices
    //	int i;
    stack<TreeNode *> nodesStack;
    if( rootNode != NULL)
    {
        nodesStack.push( rootNode );
    }
    //cout << "a.1.1\n";
    while(  nodesStack.empty() == false )
    {
        TreeNode *pn = nodesStack.top();
        nodesStack.pop();
        
        outFile << "node [\n";
        
        outFile << "id " <<  pn->id  << endl;
        outFile << "label ";
        string nameToUse = " ";
        const char *name = nameToUse.c_str();
        
        // 		char name[100];
        //       if( pn->IsLeaf() == false)
        //        {
        //		    name[0] = 'v';
        //		    sprintf(&name[1], "%d", pn->id);
        //        }
        //        else
        //        {
        // For leaf, we simply output their value (row number)
        //            sprintf(name, "%d", pn->nodeValues[0] );        // CAUTION, here we assume each leaf has exactly 1 label
        //        }
        OutputQuotedString (outFile,  name  );
        outFile << endl;
        
        // See if we need special shape here
        if( pn->GetShape() == PHY_TN_RECTANGLE)
        {
            outFile << "vgj [ \n shape  ";
            OutputQuotedString( outFile, "Rectangle");
            outFile << "\n]\n";
        }
        else
        {
            outFile << "defaultAtrribute   1\n";
        }
        
        outFile << "]\n";
        
        // Now try to get more nodes
        for(int i=0; i<(int)pn->listChildren.size(); ++i)
        {
            nodesStack.push( pn->listChildren[i] );
        }
        //cout << "a.1.2\n";
    }
    //cout << "a.1.3\n";
    
    // Now output all the edges, by again starting from root and output all nodes
    YW_ASSERT( nodesStack.empty() == true );
    if( rootNode != NULL)
    {
        nodesStack.push( rootNode );
    }
    while(  nodesStack.empty() == false )
    {
        TreeNode *pn = nodesStack.top();
        nodesStack.pop();
        
        for(int i=0; i<(int)pn->listChildren.size(); ++i)
        {
            
            //cout << "Output an edge \n";
            outFile << "edge [\n";
            outFile << "source " << pn->id << endl;
            outFile << "target  " << pn->listChildren[i]->id << endl;
            outFile << "label " ;
            if( pn->listEdgeLabels[i].size() >0 )
            {
                string lblName;
                char name[100];
                //		        name[0] = 'e';
                for(int iel =0; iel<(int)pn->listEdgeLabels[i].size(); ++iel )
                {
                    snprintf(name,100, "e%d  ", pn->listEdgeLabels[i][iel]  );
                    lblName += name;
                }
                OutputQuotedString( outFile,  lblName.c_str()  );
            }
            else
            {
                OutputQuotedString( outFile,  ""  );
            }
            outFile << "\n";
            outFile << "]\n";
            
            // Store next one to stack
            nodesStack.push( pn->listChildren[i] );
        }
    }
    
    
    // Finally quite after closing file
    outFile << "\n]\n";
    outFile.close();
}

// construct a newick string for this tree
void PhylogenyTreeBasic :: ConsNewick( string &strNewick, bool wGridLen, double gridWidth, bool fUseCurLbl  )
{
    strNewick.empty();

    // work from this node
	YW_ASSERT_INFO( rootNode != NULL, "Root is not set" );
    strNewick =  ConsNewickTreeNode( rootNode, wGridLen, gridWidth, fUseCurLbl, false );
}

void PhylogenyTreeBasic :: ConsNewickSorted( string &strNewick, bool wGridLen, double gridWidth, bool fUseCurLbl  )
{
    strNewick.empty();
    
    // work from this node
	YW_ASSERT_INFO( rootNode != NULL, "Root is not set" );
    strNewick =  ConsNewickTreeNode( rootNode, wGridLen, gridWidth, fUseCurLbl, true );
}

void PhylogenyTreeBasic :: ConsNewickEdgeLabel( string &strNewick  )
{
    strNewick.empty();
    
    // work from this node
    YW_ASSERT_INFO( rootNode != NULL, "Root is not set" );
    strNewick =  ConsNewickTreeNode( rootNode, false, 1.0, true, true, true );
}

string PhylogenyTreeBasic :: ConsNewickTreeNode( TreeNode *pNode, bool wGridLen, double gridWidth, bool fUseCurLbl, bool fSort, bool fEdgeLbel )
{
//cout << "--------------------------------In ConsNewickTreeNode: I am here\n";
	string resNodeStr;
    // Is this node a leaf? If so, we output the label of it
    if( pNode->IsLeaf() == true )
    {
        // Add this label if this label is not there
        string tmpstr = pNode->GetUserLabel();
        if( fUseCurLbl == true )
        {
            tmpstr = pNode->GetLabel();
        }
		resNodeStr = tmpstr;
    }
    else
    {
        string tmpstr = pNode->GetLabel();
        YW_ASSERT_INFO(pNode->listChildren.size() >=1, "Must have some children here.");

        // When there is only one child and no self-label
        if( tmpstr.size() <=2 &&  pNode->listChildren.size() == 1 )
        {
            resNodeStr =  ConsNewickTreeNode( pNode->listChildren[0], wGridLen, gridWidth, fUseCurLbl, fSort, fEdgeLbel  );
        }
		else
		{

			// Otherwise, we simply collect all sub strings here, and sepearate by a ,
			string comboStrName = "(";

			bool fAddSep = false;
			// does this node has a label by itself? if so, output it
			if( tmpstr.size() > 2 )
			{
				comboStrName += tmpstr.substr( 1, tmpstr.size()-2   );
				//comboStrName += ",";

				// all others should be added sep.
				fAddSep = true;
			}


			// handle its children
            if( fSort == false )
            {
                for(unsigned int i=0; i<pNode->listChildren.size(); ++i)
                {
                    string stepRes = ConsNewickTreeNode( pNode->listChildren[i], wGridLen, gridWidth, fUseCurLbl, fSort, fEdgeLbel  );

                    if( stepRes.size() > 0 )
                    {
                        if( fAddSep == true )
                        {
                            comboStrName += ",";
                        }

                        comboStrName += stepRes;

                        // from now on, add sep 
                        fAddSep = true;

                        //if( i+1 < pNode->listChildren.size() )
                        //{
                        //    comboStrName += ",";
                        //}
                    }
                }
            }
            else
            {
                // sort the labels from children
                multiset<string> strsChildren;
                for(unsigned int i=0; i<pNode->listChildren.size(); ++i)
                {
                    string stepRes = ConsNewickTreeNode( pNode->listChildren[i], wGridLen, gridWidth, fUseCurLbl, fSort, fEdgeLbel );
                    if( stepRes.size() > 0 )
                    {
                        strsChildren.insert( stepRes );
                    }
                }
                for( multiset<string> :: iterator it = strsChildren.begin(); it != strsChildren.end(); ++it )
                {
                    //
                    if( fAddSep == true )
                    {
                        comboStrName += ",";
                    }
                    
                    comboStrName += *it;
                    
                    // from now on, add sep
                    fAddSep = true;
                }
            }
			comboStrName += ")";
	//cout << "comboStrName = " << comboStrName << endl;
			resNodeStr = comboStrName;
		}
    }

	// now see if we need to add length info
	// 
	if(wGridLen == true)
	{
		// 
		TreeNode *pNodePar = pNode->GetParent();
		if( pNodePar != NULL)
		{
			double len = gridWidth*( pNodePar->GetLevel() -  pNode->GetLevel() );
//cout << "**************************PhylogenyTreeBasic::len = " << len << endl;
			char buf[100];
			snprintf(buf,100, ":%f", len);
			resNodeStr += buf;
		}
	}
    else if( pNode->GetLength() >= 0.0 )
    {
#if 0
        // if length is set, add it
        resNodeStr += ":";
        resNodeStr += ConvToString(pNode->GetLength() );
#endif
    }
    
    if( fEdgeLbel )
    {
        TreeNode *pParNode = pNode->GetParent();
        if( pParNode != NULL )
        {
            int cIndex = pParNode->GetChildIndex(pNode);
            
            // add edge label in the format: s1s2s3....
            string strEdgeLbel;
            vector<int> listEdgeLabels;
            pParNode->GetEdgeLabelsAtBranch(cIndex, listEdgeLabels);
            
//cout << "cIndex: " << cIndex <<", listEdgeLabels: ";
//DumpIntVec(listEdgeLabels);
            
            for( int i=0; i<(int)listEdgeLabels.size(); ++i  )
            {
                char buf[10000];
                snprintf(buf,10000, "#%d", listEdgeLabels[i]);
                strEdgeLbel += buf;
            }
            if( strEdgeLbel.length() > 0 )
            {
                resNodeStr += ":";
                resNodeStr += strEdgeLbel;
            }
        }
    }
    
	return resNodeStr;

}



// This function adds a new tree node, and return it. Also set the parent node to the pareamter
TreeNode *PhylogenyTreeBasic :: AddTreeNode( TreeNode *parNode, int id )
{
    if( id < 0)
    {
        id = GetNumVertices();
    }

    TreeNode *pnode = new TreeNode(id);
    pnode->AddNodeValue( id );

    // Should delete the tree
    if(  parNode == NULL)
    {
        YW_ASSERT_INFO(rootNode == NULL, "Can not add a node with no parent if the tree is not empty");
        rootNode = pnode;
        return pnode;
    }

    // Otherwise, set the parent
    SEQUENCE emptySeq;
    parNode->AddChild( pnode,  emptySeq);
    return pnode;
}

int PhylogenyTreeBasic :: GetNumVertices() const
{
    int res = 0;
    stack<TreeNode *> stackNodes;
    if( rootNode != NULL )
    {
        stackNodes.push( rootNode );
    }
    while( stackNodes.empty() == false )
    {
        TreeNode *pcurr = stackNodes.top();
        stackNodes.pop();
        ++res;
        // Now enque its children
        for(int i=0; i<(int)pcurr->listChildren.size(); ++i)
        {
            stackNodes.push( pcurr->listChildren[i]  );
        }
    }
    return res;
}



//int PhylogenyTreeBasic :: GetIdFromStr( const string &strPart, TaxaMapper *pTMapper )
//{
//cout << "GetIdFromStr: " << strPart << endl; 
//	string strToUse = strPart;
//	size_t posSeparator = strPart.find( ':' );
//	if( posSeparator != string::npos )
//	{
//		strToUse = strPart.substr(0, (int)posSeparator  );
//	}
//	// get rid of 
//	int res = -1;
//	if( pTMapper == NULL)
//	{
//		sscanf( strToUse.c_str(), "%d", &res  );
//cout << "Empty mapper\n";
//	}
//	else
//	{
//		// are we reading in the first tree or not
//		if( pTMapper->IsInitialized() == true )
//		{
//			res  = pTMapper->GetId(strToUse);
//cout << "GetIdFromStr: GetId: " << strToUse << ": " << res << endl;
//		}
//		else
//		{
//			// this is new
//			res = pTMapper->AddTaxaString( strToUse );
//cout << "GetIdFromStr: New id: " << strToUse << ": " << res << endl;
//		}
//	}
//	return res;
//}


TreeNode * PhylogenyTreeBasic :: ConsOnNewickSubtree( const string & nwStringPart, int &leafId, int &invId, int numLeaves, bool fBottomUp, TaxaMapper *pTMapper )
{
//cout << "Entry nwStringPart = "<< nwStringPart << endl;
    
    TreeNode *pres = NULL;
    int posLenBegin = -1;
    

    // this function builds recursively subtrees for this part of string
    // First, is this string a leaf or not
    if( nwStringPart[0] != '('  )
    {
        //TreeNode *pLeaf = new TreeNode( nodeId  );
        //// also set its label this way
        //pLeaf->AddNodeValue( nodeId );


		// 7/27/10 YW: for now, we take this convention: 
		// tree node id = label  if no mapper is passed
		// Why? This case is by default for internal use only
		// while mapper is used for external (user) specified
        // Yes, this is a leaf
        int nodeId = TaxaMapper :: GetIdFromStr(nwStringPart, pTMapper);
		//	sscanf( nwStringPart.c_str(), "%d", &nodeId  );
       
		if( numLeaves > 0)
		{
			if( nodeId >= numLeaves )
			{
				cout << "Wrong: nodeId = " << nodeId << ", numLeaves = " << numLeaves << endl;
			}
			YW_ASSERT_INFO( nodeId < numLeaves, "We assume in phylogeny tree, leaf id starts from 0" );
		}
//cout << "node id = " << nodeId << endl;

		int idtouse = leafId;
		if( pTMapper == NULL )
		{
			// in this case take the same as node id
			idtouse = nodeId;
		}
		else
		{
			// update leafid since we are using it
			leafId ++;
		}

        TreeNode *pLeaf = new TreeNode( idtouse  );
        // also set its label this way
        pLeaf->AddNodeValue( idtouse );
		//leafId ++;


		// get rid of any part after : if there is length info
		//string strLeafLabel = nwStringPart;
		//if( strLa )
		//{
		//}
		string strLbl = GetStringFromId(nodeId);
        pLeaf->SetLabel( strLbl );
        
        string strLblUser = TaxaMapper :: ExtractIdPartFromStr( nwStringPart );
        pLeaf->SetUserLabel( strLblUser );
        
//cout << "ConsOnNewickSubtree: set leaf label: " << strLbl << endl;
        //return pLeaf;
        pres = pLeaf;
        
        size_t posLenSep = nwStringPart.find(':');
        if( posLenSep != string::npos )
        {
            //
            posLenBegin = posLenSep+1;
        }
    }
    else
    {
        // This is not a leaf
        // so we create underlying level for it
		int idToUse = 1000;
		if( fBottomUp == false )
		{
			idToUse = invId ++;
		}
        TreeNode *pInternal = new TreeNode( idToUse );
        int lastpos = 1;
        int curpos = 0;
        int parnet = 0; // (: +1, ) -1
        while( true )
        {
//cout << "curpos = " << curpos << endl;

            if( curpos >= (int) nwStringPart.size() )
            {
                // we are done
                break;
            }


            // keep balance
            if( nwStringPart[curpos] == '(' ) 
            {
                parnet ++;
            }
            else if( nwStringPart[curpos] == ')'  )
            {
                parnet --;

                // when parnet = 0, we know we end
                if( parnet == 0 )
                {
                    // now adding the last piece
                    // create a new node
                    int strl = curpos-lastpos;
                    string subs = nwStringPart.substr( lastpos, strl );
//    cout << "last subs = " << subs << endl; 
                    TreeNode *pChild = ConsOnNewickSubtree( subs, leafId, invId, numLeaves, fBottomUp, pTMapper );

                    // also append it as child
                    vector<int> empytLabels;
                    pInternal->AddChild( pChild, empytLabels );

                    // aslo update lastpos
                    lastpos = curpos+1;
                }

            }
            else if( nwStringPart[curpos] == ','  )
            {
                // Yes, this is a sepeartor, but we only start to process it when the
                // balance of parenetnis is right
                if( parnet == 1 )
                {
                    // create a new node
                    int strl = curpos-lastpos;
                    string subs = nwStringPart.substr( lastpos, strl );
//    cout << "subs = " << subs << endl; 
                    TreeNode *pChild = ConsOnNewickSubtree( subs, leafId, invId, numLeaves, fBottomUp, pTMapper );

                    // also append it as child
                    vector<int> empytLabels;
                    pInternal->AddChild( pChild, empytLabels );

                    // aslo update lastpos
                    lastpos = curpos+1;
                }
           }
            else if( nwStringPart[curpos] == ':' )
            {
                // keep track of length
                if( parnet == 0 )
                {
                    posLenBegin = curpos+1;
                }
            }


            // now move to next pos
            curpos ++;
        }

		// if we go bottom up labeling the node, we should re-label the node here
		if( fBottomUp == true )
		{
			pInternal->SetID( invId++ );
		}
        //return pInternal;
        pres = pInternal;
    }
    
    //
    if( posLenBegin >= 0 )
    {
        // also read in length
        size_t posRightExt = nwStringPart.find( ')', posLenBegin );
        // YW: dont know if we need rightPos. TBD
        //int rightPos = (int)nwStringPart.size()-1;
        //if( posRightExt != string::npos)
        //{
        //    rightPos = posRightExt-1;
        //}
        string subs = nwStringPart.substr( posLenBegin, posRightExt-posLenBegin+1 );
        double len = StrToDouble( subs );
        pres->SetLength(len);
    }
    return pres;
}

TreeNode * PhylogenyTreeBasic :: ConsOnNewickSubtreeDupLabels( const string & nwStringPart, int &invId, int &leafId, TaxaMapper *pTMapper )
{
//cout << "Entry nwStringPart = "<< nwStringPart << endl;

    // this function builds recursively subtrees for this part of string
    // First, is this string a leaf or not
    if( nwStringPart[0] != '('  )
    {
		// ensure no internal has every been set yet
		//YW_ASSERT_INFO( invId < 0, "invId should not be set when leaf is being processed" );

        // Yes, this is a leaf
        int nodeId = leafId;
		leafId ++;
		int leafLabel = TaxaMapper :: GetIdFromStr(nwStringPart, pTMapper);
        //sscanf( nwStringPart.c_str(), "%d", &leafLabel  );

//cout << "leaf id = " << nodeId << endl;
        TreeNode *pLeaf = new TreeNode( nodeId  );
        // also set its label this way
        pLeaf->AddNodeValue( nodeId );

		// get rid of any part after : if there is length info
		//string strLeafLabel = nwStringPart;
		//if( strLa )
		//{
		//}
		char buf[1000];
		snprintf(buf, 1000, "%d", leafLabel);
		string strLabel = buf;
        pLeaf->SetLabel( strLabel  );
        
        string strLabelUser = TaxaMapper :: ExtractIdPartFromStr( nwStringPart );
        pLeaf->SetUserLabel( strLabelUser );
        
//cout << "ConsOnNewickSubtree: set leaf label: " << strLabel << endl;
        return pLeaf;
    }
    else
    {

        // This is not a leaf
        // so we create underlying level for it
		int idToUse = invId;
        TreeNode *pInternal = new TreeNode( idToUse );
        int lastpos = 1;
        int curpos = 0;
        int parnet = 0; // (: +1, ) -1
        while( true )
        {
//cout << "curpos = " << curpos << endl;

            if( curpos >= (int) nwStringPart.size() )
            {
                // we are done
                break;
            }


            // keep balance
            if( nwStringPart[curpos] == '(' ) 
            {
                parnet ++;
            }
            else if( nwStringPart[curpos] == ')'  )
            {
                parnet --;

                // when parnet = 0, we know we end
                if( parnet == 0 )
                {
                    // now adding the last piece
                    // create a new node
                    int strl = curpos-lastpos;
                    string subs = nwStringPart.substr( lastpos, strl );
//    cout << "last subs = " << subs << endl; 
                    TreeNode *pChild = ConsOnNewickSubtreeDupLabels( subs, invId, leafId, pTMapper );

                    // also append it as child
                    vector<int> empytLabels;
                    pInternal->AddChild( pChild, empytLabels );

                    // aslo update lastpos
                    lastpos = curpos+1;
                }

            }
            else if( nwStringPart[curpos] == ','  )
            {
                // Yes, this is a sepeartor, but we only start to process it when the
                // balance of parenetnis is right
                if( parnet == 1 )
                {
                    // create a new node
                    int strl = curpos-lastpos;
                    string subs = nwStringPart.substr( lastpos, strl );
//    cout << "subs = " << subs << endl; 
                    TreeNode *pChild = ConsOnNewickSubtreeDupLabels( subs, invId, leafId, pTMapper );

                    // also append it as child
                    vector<int> empytLabels;
                    pInternal->AddChild( pChild, empytLabels );

                    // aslo update lastpos
                    lastpos = curpos+1;
                }
           }


            // now move to next pos
            curpos ++;
        }

		// if we go bottom up labeling the node, we should re-label the node here
		//if(invId < 0 )
		//{
		//	invId = leafId;
		//}

		pInternal->SetID( invId++ );
//cout << "Set internal node to " << pInternal->GetID() << endl;
        return pInternal;
    }
}




// Get nodes info
// 7/27/10: we want to get node label (NOT id!)
void PhylogenyTreeBasic :: GetNodeParInfo( vector<int> &nodeIds, vector<int> &parPos )
{
//cout << "GetNodeParInfo: \n";
	// simply put consecutive node ids but keep track of node parent positions
	// ensure we get the correct node mapping between id and pointer to node
	map<TreeNode *,int> mapNodeIds;

	// id is simply consecutive
	int numTotVerts = GetNumVertices();
	nodeIds.resize(numTotVerts);
	for(int i=0; i<numTotVerts; ++i)
	{
		nodeIds[i] = i;
	}
	parPos.resize(numTotVerts);
	for(int i=0; i<numTotVerts; ++i)
	{
		parPos[i] = -1;
	}

	// IMPORTANT: assume binary tree, otherwise all bets are off!!!!
	//int numLeaves = ( numTotVerts+1 )/2;
	int numLeaves = GetNumLeaves();
//cout << "numLeaves: " << numLeaves << endl;
	// do traversal
	int curNodeNum = 0;
	//InitPostorderWalk();
	PhylogenyTreeIterator itorTree(*this);
	itorTree.Init();
	while(itorTree.IsDone() == false)
	{
		TreeNode *pn = itorTree.GetCurrNode();
		itorTree.Next();
        //TreeNode *pn = NextPostorderWalk( ) ;
        if( pn == NULL)
        {
//cout << "No node here. Stop.\n";
            break;      // done with all nodes
        }

		// 
		if( pn->IsLeaf() == true  )
		{
			// skip it for now
			continue;
		}

		// 
		int nonleafInd = numLeaves + curNodeNum;
		curNodeNum++;
		// remember it
		mapNodeIds.insert( map<TreeNode *,int> :: value_type( pn, nonleafInd ) );
		// now set its descendents to this index, either leaf or non-leaf
		// if it is non-leaf, do a lookup of the stored id. Leaf: just go by its id
		for(int jj=0; jj<pn->GetChildrenNum(); ++jj)
		{
			TreeNode *pnjj = pn->GetChild(jj);
			int pnjjid;
			int pnjjlabel = -1;
			if( pnjj->IsLeaf() == true )
			{
				pnjjid = pnjj->GetID();
				// assume id is distinct, while label can be duplicate
				pnjjlabel = pnjj->GetIntLabel();
//cout << "pnjjid = " << pnjjid << ", pnjjlabel: " << pnjjlabel << ", numLeaves: " << numLeaves << endl;
				YW_ASSERT_INFO( pnjjid >=0 && pnjjid < numLeaves, "Leaf id: out of range" );
			}
			else
			{
				YW_ASSERT_INFO( mapNodeIds.find( pnjj ) != mapNodeIds.end(), "Fail to find the node"  );
				pnjjid = mapNodeIds[pnjj];
			}
			parPos[pnjjid] = nonleafInd;
			// this says whether we change the label of the node
			// this is needed when there are duplicate labels in the tree
			if( pnjjlabel >= 0)
			{
				nodeIds[pnjjid] = pnjjlabel;
			}
		}
	}

// print out
//cout << "original tree:  ";
//string strTree;
//ConsNewick(strTree);
//cout << strTree << endl;
//cout << "Parent position : ";
//DumpIntVec( parPos );
}

void PhylogenyTreeBasic :: GetNodeParInfoNew( vector<int> &nodeIds, vector<int> &parPos )
{
//cout << "In GetNodeParInfoNew: tree is: ";
//this->Dump();
	// the previous version has various of problems, but it is being used by some programs
	// so I decide to add a new function
	// Note this one assume all nodes are labeled consecutively
	// simply put consecutive node ids but keep track of node parent positions
	// ensure we get the correct node mapping between id and pointer to node
	//map<TreeNode *,int> mapNodeIds;

	// id is simply consecutive
	int numTotVerts = GetNumVertices();
	//nodeIds.resize(numTotVerts);
	//for(int i=0; i<numTotVerts; ++i)
	//{
	//	nodeIds[i] = i;
	//}
	//parPos.resize(numTotVerts);
	//for(int i=0; i<numTotVerts; ++i)
	//{
	//	parPos[i] = -1;
	//}

	// IMPORTANT: assume binary tree, otherwise all bets are off!!!!
	//int numLeaves = ( numTotVerts+1 )/2;
	int numLeaves = GetNumLeaves();
//cout << "Numleaves = " << numLeaves << endl;
	// do traversal
	//int curNodeNum = 0;
	//InitPostorderWalk();
	PhylogenyTreeIterator itorTree(*this);
	itorTree.Init();
	while(itorTree.IsDone() == false )
	{
		TreeNode *pn = itorTree.GetCurrNode();
		itorTree.Next();
        //TreeNode *pn = NextPostorderWalk( ) ;
        if( pn == NULL)
        {
//cout << "No node here. Stop.\n";
            break;      // done with all nodes
        }

		// 
		int curNodeId = pn->GetID();
//cout << "curNodeId: " << curNodeId << endl;
		YW_ASSERT_INFO(curNodeId < numTotVerts, "curNodeId exceeds limit (the node ids must be consecutive from 0)");
		if( pn->IsLeaf() == true  )
		{
			// skip it for now
			YW_ASSERT_INFO( curNodeId < numLeaves, "The tree violates assumption that tree leaf id start from 0" );
		}

		// add a record
		nodeIds.push_back( pn->GetID() );
		TreeNode *pnPar = pn->GetParent();
		if( pnPar == NULL)
		{
			parPos.push_back( -1 );
		}
		else
		{
			// simply its id
			parPos.push_back( pnPar->GetID() );
		}

		//	continue;
		//}
#if 0
		// 
		//int nonleafInd = numLeaves + curNodeNum;
		int nonleafInd = curNodeId;
		//curNodeNum++;
		// remember it
		mapNodeIds.insert( map<TreeNode *,int> :: value_type( pn, curNodeId ) );
		// now set its descendents to this index, either leaf or non-leaf
		// if it is non-leaf, do a lookup of the stored id. Leaf: just go by its id
		for(int jj=0; jj<pn->GetChildrenNum(); ++jj)
		{
			TreeNode *pnjj = pn->GetChild(jj);
			int pnjjid;
			if( pnjj->IsLeaf() == true )
			{
				pnjjid = pnjj->GetID();
				YW_ASSERT_INFO( pnjjid >=0 && pnjjid < numLeaves, "Leaf id: out of range" );
			}
			else
			{
				YW_ASSERT_INFO( mapNodeIds.find( pnjj ) != mapNodeIds.end(), "Fail to find the node"  );
				pnjjid = mapNodeIds[pnjj];
			}
			parPos[pnjjid] = nonleafInd;
#endif
		//}
	}

// print out
//cout << "original tree:  ";
//string strTree;
//ConsNewick(strTree);
//cout << strTree << endl;
//cout << "Parent position : ";
//DumpIntVec( parPos );
}

//
bool PhylogenyTreeBasic :: ConsOnParPosList( const vector<int> &parPos, int numLeaves, bool fBottupUpLabel  )
{
	// 
	string strNewick;
	if( ConvParPosToNewick(parPos, strNewick) == false  )
	{
		return false;
	}
//cout << "Newick string = " << strNewick << endl;
	ConsOnNewick(strNewick, numLeaves, fBottupUpLabel);
	return true;
}

bool PhylogenyTreeBasic :: ConvParPosToNewick( const vector<int> &parPos, string &strNewick )
{
	// convert par position representation to newick
	// we always assume the last item is -1
	YW_ASSERT_INFO( parPos[parPos.size()-1] == -1, "Must be -1 for the last value in parPos" );
	ConvParPosToNewickSubtree( parPos.size()-1, parPos, strNewick );
	return true;
}

void PhylogenyTreeBasic :: ConvParPosToNewickSubtree( int nodeInd, const vector<int> &parPos, string &strNewick )
{
	// this function generate under a single node (leaf or non-leaf), the newick under the subtree
	vector<int> listUnderNodeInds;
	for(int i=0; i<(int)parPos.size(); ++i)
	{
		if( parPos[i] == nodeInd )
		{
			listUnderNodeInds.push_back( i );
		}
	}
	// leaf if empty
	if( listUnderNodeInds.size() == 0 )
	{
		char buf[100];
		snprintf( buf, 100, "%d", nodeInd );
		strNewick = buf;
		return;
	}
	YW_ASSERT_INFO(listUnderNodeInds.size() == 2, "Only binary trees are supported for now");

	// now get newick for the two part and merge it
	string strFirst, strSecond;
	ConvParPosToNewickSubtree( listUnderNodeInds[0], parPos, strFirst );
	ConvParPosToNewickSubtree( listUnderNodeInds[1], parPos, strSecond );
	strNewick = "(";
	strNewick += strFirst;
	strNewick += ",";
	strNewick += strSecond;
	strNewick += ")";
}


void PhylogenyTreeBasic ::  GetLeaveIds( set<int> &lvids )
{
	lvids.clear();

	PhylogenyTreeIterator itorTree(*this);
	itorTree.Init();
	while(itorTree.IsDone() == false )
	{
		TreeNode *pn = itorTree.GetCurrNode();
		itorTree.Next();
		if( pn == NULL)
		{
			break;      // done with all nodes
		}
		if( pn->IsLeaf() == true )
		{
			lvids.insert(  pn->GetID()  );
		}
	}
}
void PhylogenyTreeBasic :: GetLeafIntLabels(set<int> &setIntLabels)
{
    vector<TreeNode *> listLeafNodes;
    GetAllLeafNodes( listLeafNodes );
    setIntLabels.clear();
    for(int i=0; i<(int)listLeafNodes.size(); ++i)
    {
        setIntLabels.insert( listLeafNodes[i]->GetIntLabel() );
    }
}
    

void PhylogenyTreeBasic:: GetLeavesIdsWithLabel(  const string &label, set<int> &lvids   )
{
	lvids.clear();
	PhylogenyTreeIterator itorTree(*this);
	itorTree.Init();
	while(itorTree.IsDone() == false )
	{
		TreeNode *pn = itorTree.GetCurrNode();
//cout << "GetLeavesIdsWithLabel: ";
//cout << pn->GetLabel() << endl;
		itorTree.Next();
		if( pn == NULL)
		{
			break;      // done with all nodes
		}
		if( pn->GetLabel() == label )
		{
			lvids.insert(  pn->GetID()  );
		}
	}
}
    
void  PhylogenyTreeBasic :: GetLeavesWithLabels( const set<string> &setLabels, set<TreeNode *> &setLvNodes )
{
    //
    setLvNodes.clear();
    PhylogenyTreeIterator itorTree(*this);
    itorTree.Init();
    while(itorTree.IsDone() == false )
    {
        TreeNode *pn = itorTree.GetCurrNode();
        //cout << "GetLeavesIdsWithLabel: ";
        //cout << pn->GetLabel() << endl;
        itorTree.Next();
        if( pn == NULL)
        {
            break;      // done with all nodes
        }
        if(  setLabels.find( pn->GetLabel() ) != setLabels.end() )
        {
            setLvNodes.insert(  pn  );
        }
    }
}

void PhylogenyTreeBasic :: UpdateIntLabel( const vector<int> &listLabels)
{
	// by assumption, id is from 0 to the following
	PhylogenyTreeIterator itorTree(*this);
	itorTree.Init();
	while(itorTree.IsDone() == false )
	{
		TreeNode *pn = itorTree.GetCurrNode();
		itorTree.Next();
		if( pn == NULL)
		{
			break;      // done with all nodes
		}
//cout << "node id = " << pn->GetID() << endl;

		YW_ASSERT_INFO( pn->GetID() < (int) listLabels.size(), "Tree id: over limit" );
		int lblInt = listLabels[pn->GetID()];
		char strbuf[100];
		snprintf(strbuf, 100, "%d", lblInt);
		string lblNew = strbuf;
		pn->SetLabel(lblNew);
	}
}

void PhylogenyTreeBasic :: Reroot(TreeNode *pRootDesc)
{
	YW_ASSERT_INFO(pRootDesc != NULL, "Can not take NULL pointer");
	// if the node is set ot be root, nothing to be done
	if( pRootDesc == rootNode )
	{
		return;
	}
//cout << "pass1\n";
	// create a new node
	//vector<int> dummyLbls;
	TreeNode *pRootNew = new TreeNode(rootNode->GetID() );
	TreeNode *pRootOtherDesc = pRootDesc->GetParent();
	YW_ASSERT_INFO(pRootOtherDesc != NULL, "TBD");
	vector<int> lblsNew;	
	// for now, concerntrate the labels without SPLITTING
	pRootOtherDesc->GetEdgeLabelsToChild(pRootDesc, lblsNew);
	pRootOtherDesc->RemoveChild(pRootDesc);
	pRootNew->AddChild( pRootDesc, lblsNew );
//cout << "pass2\n";
	// 
	TreeNode *pCurNode = pRootOtherDesc;
	TreeNode *pCurNodePar = pRootNew;
	while(true)
	{
		// setup the ancestral relationship
		YW_ASSERT_INFO( pCurNode != NULL && pCurNodePar != NULL, "Something wrong" );
//cout << "BEFORE CHANGING...\n";
//cout << "pCurNode: label =" << pCurNode->GetLabel() << ", ID = " << pCurNode->GetID() << ", num of children " << pCurNode->GetChildrenNum() << endl;
//for( int pp=0; pp< pCurNode->GetChildrenNum(); ++pp )
//{
//cout << "** Child: " << pCurNode->GetChild(pp)->GetID() << endl;
//}
//cout << "pCurNodePar: label =" << pCurNodePar->GetLabel() << ", ID = " << pCurNodePar->GetID()  << ", num of children " << pCurNodePar->GetChildrenNum()  << endl;
//for( int pp=0; pp< pCurNodePar->GetChildrenNum(); ++pp )
//{
//cout << "** Child: " << pCurNodePar->GetChild(pp)->GetID() << endl;
//}
		vector<int> lblsNew;	
		pCurNode->GetEdgeLabelsToChild(pCurNodePar, lblsNew);
		TreeNode *pNodeNext = pCurNode->GetParent();
		pCurNode->RemoveChild( pCurNodePar );
		//pCurNode->SetParent(pCurNodePar);
		pCurNodePar->AddChild(pCurNode, lblsNew);


#if 0
		vector<TreeNode *> listParChildren;
		for(int c=0; c<(int)pCurNode->GetChildrenNum(); ++c  )
		{
			//if( pCurNode->GetChild(c) != pCurNode )
			//{
			listParChildren.push_back( pCurNode->GetChild(c) ) ;
			//}
		}
		for(int c=0; c<(int)listParChildren.size(); ++c  )
		{
			//if( pCurNode->GetChild(c) != pCurNode )
			//{
			pCurNode->RemoveChild( listParChildren[c] ) ;
			//}
		}
		// add these to the descendent of the new par
		for( int c=0; c<(int)listParChildren.size(); ++c )
		{
			vector<int> emptyLbls;
			pCurNodePar->AddChild(listParChildren[c], emptyLbls);
		}
#endif

//cout << "AFTER CHANGING...\n";
//cout << "pCurNode: label =" << pCurNode->GetLabel() << ", ID = " << pCurNode->GetID() << ", num of children " << pCurNode->GetChildrenNum() << endl;
//for( int pp=0; pp< pCurNode->GetChildrenNum(); ++pp )
//{
//cout << "** Child: " << pCurNode->GetChild(pp)->GetID() << endl;
//}
//cout << "pCurNodePar: label =" << pCurNodePar->GetLabel() << ", ID = " << pCurNodePar->GetID()  << ", num of children " << pCurNodePar->GetChildrenNum()  << endl;
//for( int pp=0; pp< pCurNodePar->GetChildrenNum(); ++pp )
//{
//cout << "** Child: " << pCurNodePar->GetChild(pp)->GetID() << endl;
//}

		// find the other descendents of the par
		if(pNodeNext == NULL)
		{
			vector<TreeNode *> listParChildren;
			for(int c=0; c<(int)pCurNode->GetChildrenNum(); ++c  )
			{
				//if( pCurNode->GetChild(c) != pCurNode )
				//{
				listParChildren.push_back( pCurNode->GetChild(c) ) ;
				//}
			}
			for(int c=0; c<(int)listParChildren.size(); ++c  )
			{
				//if( pCurNode->GetChild(c) != pCurNode )
				//{
				pCurNode->RemoveChild( listParChildren[c] ) ;
				//}
			}
			// add these to the descendent of the new par
			for( int c=0; c<(int)listParChildren.size(); ++c )
			{
				vector<int> lblsNew;	
				pCurNode->GetEdgeLabelsToChild(listParChildren[c], lblsNew);

				//vector<int> emptyLbls;
				pCurNodePar->AddChild(listParChildren[c], lblsNew);
			}
			pCurNodePar->RemoveChild( pCurNode );

//cout << "FINALLY...\n";
//cout << "pCurNode: label =" << pCurNode->GetLabel() << ", ID = " << pCurNode->GetID() << ", num of children " << pCurNode->GetChildrenNum() << endl;
//for( int pp=0; pp< pCurNode->GetChildrenNum(); ++pp )
//{
//cout << "** Child: " << pCurNode->GetChild(pp)->GetID() << endl;
//}
//cout << "pCurNodePar: label =" << pCurNodePar->GetLabel() << ", ID = " << pCurNodePar->GetID()  << ", num of children " << pCurNodePar->GetChildrenNum()  << endl;
//for( int pp=0; pp< pCurNodePar->GetChildrenNum(); ++pp )
//{
//cout << "** Child: " << pCurNodePar->GetChild(pp)->GetID() << endl;
//}
			// done. pCurNode is the root, we should by-pass this node and assign
			// their children to pCurNodePar
			break;
		}
		// 
		pCurNodePar = pCurNode;
		pCurNode = pNodeNext;
	}


	// finally get rid of the original root
	delete rootNode;
	rootNode = pRootNew;
}
    
void PhylogenyTreeBasic :: Reroot2(TreeNode *pRootNew)
{
    // different from previous, this node pRootNew would be the new root of the tree after change
    // YW: for now, do nothing to leaf label (TBD)
    YW_ASSERT_INFO(pRootNew != NULL, "Can not take NULL pointer");
    // if the node is set ot be root, nothing to be done
    if( pRootNew == rootNode )
    {
        return;
    }
    //cout << "pass1\n";
    // create a new node
    //vector<int> dummyLbls;
    TreeNode *pRootNewPar = pRootNew->GetParent();
    YW_ASSERT_INFO(pRootNewPar != NULL, "TBD");
    
    // reverse direction of all parents above
    TreeNode *pnParCurr = pRootNewPar;
    TreeNode *pnChildCurr = pRootNew;
    while( pnParCurr != NULL )
    {
        TreeNode *pnParCurrPar = pnParCurr->GetParent();
        
        // detach
        TreeNode *pcpOrig = pnChildCurr->GetParent();
        pnParCurr->RemoveChild(pnChildCurr);
        pnChildCurr->SetParent(pcpOrig);
        //pnParCurr->SetParent(NULL);
        
        if( pnParCurr->IsRoot() == false || pnParCurr->GetChildrenNum() > 1)
        {
            // keep the parent (which is the child of the new root)
            vector<int> lblsNew;
            // for now, concerntrate the labels without SPLITTING
            pnParCurr->GetEdgeLabelsToChild(pnChildCurr, lblsNew);
            pnChildCurr->AddChild(pnParCurr, lblsNew);
            //pnParCurr->SetParent(pnParCurr);
        }
        else
        {
            // if root, remove this root if there the root is degree 2
            TreeNode *pnc = pnParCurr->GetChild(0);
            vector<int> lblsNew;
            // for now, concerntrate the labels without SPLITTING
            pnParCurr->GetEdgeLabelsToChild(pnc, lblsNew);
            pnChildCurr->AddChild( pnc,  lblsNew);
            //pnc->SetParent(pnChildCurr);
            pnParCurr->DetachAllChildren();
            delete pnParCurr;
        }
        pnChildCurr = pnParCurr;
        pnParCurr = pnParCurrPar;
    }
    
    
    /*
    // detach
    pRootNewPar->RemoveChild(pRootNew);
    pRootNew->SetParent(NULL);
    if( pRootNewPar->GetChildrenNum() >= 2)
    {
        // keep the parent (which is the child of the new root)
        vector<int> lblsNew;
        // for now, concerntrate the labels without SPLITTING
        pRootNewPar->GetEdgeLabelsToChild(pRootNew, lblsNew);
        pRootNew->AddChild(pRootNewPar, lblsNew);
        pRootNewPar->SetParent(pRootNew);
    }
    else
    {
        // remove the parent
        TreeNode *pnc = pRootNewPar->GetChild(0);
        vector<int> lblsNew;
        // for now, concerntrate the labels without SPLITTING
        pRootNewPar->GetEdgeLabelsToChild(pnc, lblsNew);
        pRootNew->AddChild( pnc,  lblsNew);
        pnc->SetParent(pRootNew);
        pRootNewPar->DetachAllChildren();
        delete pRootNewPar;
    }*/
    
    // finally get rid of the original root
    pRootNew->SetParent(NULL);
    this->rootNode = pRootNew;
}

int PhylogenyTreeBasic :: GetNumLeaves()  
{
	if( numLeaves > 0 )
	{
		return numLeaves;
	}
	set<int> lvids; 
	GetLeaveIds(lvids); 
	numLeaves = lvids.size(); 
	return numLeaves;
}
    
int PhylogenyTreeBasic :: GetNumInternalNodes()
{
    //
    vector< TreeNode *> listAllNodes;
    GetAllNodes( listAllNodes );
    int res = 0;
    for(int i=0; i<(int)listAllNodes.size(); ++i)
    {
        if( listAllNodes[i]->IsLeaf() == false )
        {
            //
            ++res;
        }
    }
    return res;
}

void PhylogenyTreeBasic :: GetAllLeafNodes( vector< TreeNode *> &listLeafNodes) const
{
	listLeafNodes.clear();

    PhylogenyTreeBasic &refSelf = const_cast<PhylogenyTreeBasic &>(*this);
	PhylogenyTreeIterator itorTree(refSelf);
	itorTree.Init();
	while(itorTree.IsDone() == false )
	{
		TreeNode *pn = itorTree.GetCurrNode();
		itorTree.Next();
		if( pn == NULL)
		{
			break;      // done with all nodes
		}
		if( pn->IsLeaf() == true )
		{
			listLeafNodes.push_back( pn );
		}
	}
}

void PhylogenyTreeBasic :: GetAllNodes( vector< TreeNode *> &listLeafNodes) const
{
    listLeafNodes.clear();
    
    PhylogenyTreeBasic &refSelf = const_cast<PhylogenyTreeBasic &>(*this);
    PhylogenyTreeIterator itorTree(refSelf);
    itorTree.Init();
    while(itorTree.IsDone() == false )
    {
        TreeNode *pn = itorTree.GetCurrNode();
        itorTree.Next();
        if( pn == NULL)
        {
            break;      // done with all nodes
        }
        listLeafNodes.push_back( pn );
    }
}
    
// remove all leaf nodes without taxa ids
void PhylogenyTreeBasic :: CleanNonLabeledLeaves()
{
//cout << "CleanNonLabeledLeaves:\n";
	// mark all nodes that are on the path from a labeled leaf node to root
	set<TreeNode *> setNodesNonredundent;

	vector< TreeNode *> listLeafNodes;
	GetAllLeafNodes(listLeafNodes);
	for( int ii=0; ii<(int)listLeafNodes.size(); ++ii  )
	{
//cout << "Leaflabel: " << listLeafNodes[ii]->GetLabel() << endl;
		if( listLeafNodes[ii]->GetLabel().empty() == true || listLeafNodes[ii]->GetLabel() == "-" )
		{
			// 
//cout << "This leaf is REDUNDENT\n";
			continue;
		}

		TreeNode *pncurr = listLeafNodes[ii];
		while(pncurr != NULL && setNodesNonredundent.find( pncurr) == setNodesNonredundent.end() )
		{

			// 
			setNodesNonredundent.insert(pncurr);

			//
			pncurr = pncurr->GetParent();
		}
	}

	// now clean it by removing each node that does not appear in that
	PhylogenyTreeIterator itorTree(*this);
	itorTree.Init();
	vector<TreeNode *> listNodesToClean;
	while(itorTree.IsDone() == false )
	{
		TreeNode *pn = itorTree.GetCurrNode();
		itorTree.Next();
		if( pn == NULL)
		{
			break;      // done with all nodes
		}
//cout << "node id = " << pn->GetID() << endl;

		//
		if( setNodesNonredundent.find( pn) == setNodesNonredundent.end() )
		{
			// remove it
			listNodesToClean.push_back(pn);
		}
	}
	// now clean
	for(int ii=0; ii<(int)listNodesToClean.size(); ++ii)
	{
//cout << "Remove one node\n";
		RemoveNode( listNodesToClean[ii] );
	}

}

void PhylogenyTreeBasic :: RemoveNode( TreeNode *pn )
{
	// remove the node (but does not do anything to its descendent if it has; that is, we assume the node has no children)
	YW_ASSERT_INFO( pn->IsLeaf() == true, "Wrong: it still have children" );
	TreeNode *pnpar = pn->GetParent();
	if( pnpar != NULL )
	{
		pnpar->RemoveChild( pn );
	}
	delete pn;
}
    
void PhylogenyTreeBasic :: RemoveNodeKeepChildren( TreeNode *pn )
{
    YW_ASSERT_INFO(pn!=NULL, "null");
//cout << "RemoveNodeKeepChildren: pn: ";
//pn->Dump();
    
    // remove node (and move all its children to be the nodes of the grand par
    // YW: cannot remove the root this way
    YW_ASSERT_INFO(pn != GetRoot(), "Cannot remove root this way");
    TreeNode *pnpar = pn->GetParent();
    YW_ASSERT_INFO(pnpar != NULL, "Wrong3");
    pnpar->RemoveChild(pn);
    
    for(int i=0; i<pn->GetChildrenNum(); ++i)
    {
        vector<int> emptyLbls;
        pnpar->AddChild( pn->GetChild(i), emptyLbls );
    }
    pn->DetachAllChildren();
    delete pn;
    
    // remove newly created degree one node
    RemoveDegreeOneNodeAt( pnpar );
}
void PhylogenyTreeBasic :: RemoveDegreeOneNodeAt( TreeNode *pn )
{
    //return;
//cout << "removing degree one node: ";
//pn->Dump();
//cout << "Current tree: ";
//this->Dump();
//exit(1);
    // remove this node if it is a degree-1 node
    int numChildren = pn->GetChildrenNum();
    if( numChildren <= 0 )
    {
        cout << "Number of children: " << numChildren << endl;
        pn->Dump();
        cout << "Current tree: ";
        this->Dump();
    }
    YW_ASSERT_INFO(numChildren >=1, "Num of children: at least 1");
    if( numChildren == 1 )
    {
        // if root, then delete it and re-set the root
        if( pn == GetRoot() )
        {
//cout << "The degree one node is root!\n";
            TreeNode *pnchild = pn->GetChild(0);
            YW_ASSERT_INFO(pnchild != NULL, "pnchild: null");
//cout << "pnchild: ";
//pnchild->Dump();
            pnchild->DetachSelf();
//cout << "After detach: root: ";
//pn->Dump();
            //pn->DetachAllChildren();
            pnchild->SetParent(NULL);
            delete pn;
            SetRootPlain(pnchild);
        }
        else
        {
            // then invoke the removekeepchild
            RemoveNodeKeepChildren( pn );
        }
    }
//cout << "Done: RemoveDegreeOneNodeAt. Tree is now: ";
//this->Dump();
}
    
void PhylogenyTreeBasic :: RemoveDegreeOneNodes()
{
    //
    vector< TreeNode * > listNodesAll;
    this->GetAllNodes(listNodesAll);
    for(int i=0; i<(int)listNodesAll.size(); ++i)
    {
        if( listNodesAll[i]->IsLeaf() == false )
        {
            RemoveDegreeOneNodeAt(listNodesAll[i]);
        }
    }
}
    
void PhylogenyTreeBasic :: RemoveDegreeOneNodes2()
{
    //
    bool fCleaned = true;
    while(fCleaned)
    {
        fCleaned = false;
        vector< TreeNode * > listNodesAll;
        this->GetAllNodes(listNodesAll);
        for(int i=0; i<(int)listNodesAll.size(); ++i)
        {
            if( listNodesAll[i]->IsLeaf() == false && listNodesAll[i]->GetChildrenNum() == 1 )
            {
                RemoveDegreeOneNodeAt(listNodesAll[i]);
                fCleaned = true;
                break;
            }
        }
    }
}
    
void PhylogenyTreeBasic :: RemoveDescendentsFrom(set<TreeNode *> &setTreeNodes)
{
    // only keep those whose ancestor is ot in the set given
    set<TreeNode *> setTreeNodeNew;
    for( set<TreeNode *> :: iterator it = setTreeNodes.begin(); it != setTreeNodes.end(); ++it )
    {
        // check whether any of its parent is in the list
        bool fKeep = true;
        TreeNode *ppar = (*it)->GetParent();
        while( ppar != NULL )
        {
            if( setTreeNodes.find(ppar) != setTreeNodes.end() )
            {
                fKeep = false;
                break;
            }
            ppar = ppar->GetParent();
        }
        if( fKeep == true)
        {
            setTreeNodeNew.insert(*it);
        }
    }
    setTreeNodes = setTreeNodeNew;
}

// given a set of clusters (subsets of tree taxa), construct the corresponding phylo trees
// YW: need to allow mulfurcating trees
void PhylogenyTreeBasic :: ConsPhyTreeFromClusters( const set< set<int> > &setClusters )
{
//cout << "ConsPhyTreeFromClusters :: Cluseters: \n";
//for( set< set<int> > :: const_iterator it = setClusters.begin(); it != setClusters.end(); ++it )
//{
//DumpIntSet( *it );
//}
	// assume all leaves are given as singleton taxon. So first collect those singleton subsets
	set< set<int> > setSubsetsActive;
	TreeNode *nodeLast = NULL;
	map< set<int>, TreeNode *> mapClusterToNode;
	for( set< set<int> > :: const_iterator it = setClusters.begin(); it != setClusters.end(); ++it )
	{
		if( it->size() == 1)
		{
			// add in setClusters
			setSubsetsActive.insert( *it );
			// also create nodes
			TreeNode *pnode = new TreeNode( *(it->begin() ) );
			char buf[100];
			snprintf(buf, 100, "%d", *(it->begin()) );
			string sbuf = buf;
			pnode->SetLabel( sbuf );
			nodeLast = pnode;
			mapClusterToNode.insert( map< set<int>, TreeNode *> :: value_type(*it, pnode) );
		}
	}
	// setup num of leaves now
	this->numLeaves = mapClusterToNode.size();

	// need to allow mulfurcating trees
	// approach: for each cluster, maintain a pointer that points to the cluster that is its parent
	// then, each time, loop through to find all parents
	map< set<int>, set<int> > mapClustrToPar;
	// try to see whether we can create new nodes
	for( set< set<int> > :: iterator it1 = setClusters.begin(); it1 != setClusters.end(); ++it1 )
	{
		set< set<int> > :: iterator it2 = setClusters.begin();
		++it2;
		for(; it2 !=setClusters.end(); ++it2 )
		{
			//
			set<int> sLarger = *it1;
			set<int> sSmaller = *it2;
			if( sLarger.size() < sSmaller.size() )
			{
				sLarger = *it2;
				sSmaller = *it1;
			}
			// can these two coalesce into a single cluster known
			if(  sLarger.size() > sSmaller.size() && IsSetContainer(sLarger, sSmaller) == true)
			{
				if( mapClustrToPar.find( sSmaller ) == mapClustrToPar.end() || mapClustrToPar[sSmaller].size() > sLarger.size() )
				{
					mapClustrToPar.erase(sSmaller);
					mapClustrToPar.insert( map< set<int>, set<int> > :: value_type(sSmaller, sLarger) ) ;
				}
			}
		}
	}

	// loop until there is only a single subset
	while( setSubsetsActive.size() > 1 )
	{
		set< set<int> > setSubsetsActiveNext = setSubsetsActive;
//cout << "Current active sets: \n";
//for( set< set<int> > :: const_iterator it = setSubsetsActiveNext.begin(); it != setSubsetsActiveNext.end(); ++it )
//{
//DumpIntSet( *it );
//}
		// try to find several clusters that have the same parent cluster
		// try to see whether we can create new nodes
		map<set<int>, set< set<int> > > mapClusterCoal;
		for( set< set<int> > :: iterator it1 = setSubsetsActive.begin(); it1 != setSubsetsActive.end(); ++it1 )
		{
			// get parent
			YW_ASSERT_INFO( mapClustrToPar.find(*it1) != mapClustrToPar.end(), "Cluster: not found" );
			if( mapClusterCoal.find(mapClustrToPar[*it1] ) == mapClusterCoal.end() )
			{
				set< set<int> > sempty;
				mapClusterCoal.insert( map<set<int>, set< set<int> > > :: value_type(mapClustrToPar[*it1], sempty) );
			}
//cout << "Having child cluster: ";
//DumpIntSet( mapClustrToPar[*it1] );
//cout << ", for child ";
//DumpIntSet(*it1);
			mapClusterCoal[ mapClustrToPar[*it1] ].insert(*it1);
		}
	

		// now process each record
		for( map<set<int>, set< set<int> > > :: iterator it2 = mapClusterCoal.begin(); it2 != mapClusterCoal.end(); ++it2)
		{
			//YW_ASSERT_INFO( it2->second.size() > 1, "Must have at least two coalescing" );
//cout << "Set parent: ";
//DumpIntSet(it2->first);
			set<int> sunion;
			for( set< set<int> > :: iterator it3=it2->second.begin(); it3 != it2->second.end(); ++it3 )
			{
//cout << "Set child: ";
//DumpIntSet(*it3);
				// can these two coalesce into a single cluster known
				UnionSets(sunion, *it3);
			}
//cout << "sunion = ";
//DumpIntSet( sunion );
			// ensure these do coal into some meaningful cluster
			if( setClusters.find(sunion) == setClusters.end() )
			{
//cout << "This set not complete\n";
				// this cluster not done yet
				continue;
			}
			
			// create this new node
			TreeNode *pnode = new TreeNode;
			nodeLast = pnode;
			for( set< set<int> > :: iterator it3=it2->second.begin(); it3 != it2->second.end(); ++it3 )
			{
//cout << "Processing first subset: ";
//DumpIntSet( *it1 );
//cout << "Processing second subset: ";
//DumpIntSet( *it2 );
				// these two add up to an input cluster and so create a new node for it
				YW_ASSERT_INFO( mapClusterToNode.find(*it3) != mapClusterToNode.end(), "Fail1" );
				vector<int> emptyLabels;
				pnode->AddChild( mapClusterToNode[*it3], emptyLabels );
				setSubsetsActiveNext.erase( *it3 );
			}
			mapClusterToNode.insert( map< set<int>, TreeNode *> :: value_type(sunion, pnode) );
			setSubsetsActiveNext.insert( sunion );
//cout << "Creating node: " << endl;
		}
		// must make progress
		YW_ASSERT_INFO( setSubsetsActive != setSubsetsActiveNext, "Did not make progress" );
		setSubsetsActive = setSubsetsActiveNext;
	}
	YW_ASSERT_INFO( nodeLast != NULL, "nodeLast: NULL" );
	SetRoot( nodeLast );
}

// find the set of clades in the subtree specified by the given leaf nodes
void PhylogenyTreeBasic :: FindCladeOfSubsetLeaves( const set<TreeNode *> &setLeaves, set< set<TreeNode *> > &setSubtreeClades  )
{
    // caution: do not check whether these are true leaves
    TreeNode *pRoot = this->GetRoot();
    set<TreeNode *> setAllNodes;
    pRoot->GetAllDescendents(setAllNodes);
    
    //
    for( set<TreeNode *> :: iterator it = setAllNodes.begin(); it != setAllNodes.end(); ++it )
    {
        //
        set<TreeNode *> setLeavesUnder;
        (*it)->GetAllLeavesUnder( setLeavesUnder );
        set<TreeNode *> setLeavesSS;
        JoinSetsGen( setLeavesUnder, setLeaves, setLeavesSS );
        if( setLeavesSS.size() > 0 )
        {
            setSubtreeClades.insert( setLeavesSS );
        }
    }
}
void PhylogenyTreeBasic :: FindMaxSubtreesForTaxa( const set<int> &setTaxa, set<TreeNode *> &maxSTRoots )
{
    // find the leaves with the taxa first
    set<TreeNode *> setLeavesChosen;
    vector< TreeNode *> listLeafNodes;
    GetAllLeafNodes( listLeafNodes);
    for(unsigned int i=0; i<listLeafNodes.size(); ++i)
    {
        int tid = listLeafNodes[i]->GetIntLabel();
        if( setTaxa.find(tid) != setTaxa.end() )
        {
            setLeavesChosen.insert(listLeafNodes[i]);
        }
    }
    // group them to find subtrees
    map< TreeNode *, set<TreeNode *> > setSubtreeClades;
    FindSubsetLeavesRootedAt( setLeavesChosen, setSubtreeClades  );
    
    // find maximal subtrees
    maxSTRoots.clear();
    for(auto x: setSubtreeClades)
    {
        TreeNode *px = x.first;
        // store the root if none of the other root is ancestraal to it
        bool fMax = true;
        for(auto y: setSubtreeClades)
        {
            TreeNode *py = y.first;
            int dumbi = 0;
            if( py != px && py->IsAncesterOf(px, dumbi) )
            {
                fMax = false;
                break;
            }
        }
        
        if(fMax)
        {
            maxSTRoots.insert(px);
        }
    }
}
    
//void PhylogenyTreeBasic :: FindSubsetLeavesRootedAt( const set<TreeNode *> &setLeaves, map< TreeNode *, set<TreeNode *> > &setSubtreeClades  )
//{
//    // caution: do not check whether these are true leaves; different from previous version, this one stors the subtree root
//    setSubtreeClades.clear();
//    set<TreeNode *> setLeavesRemain = setLeaves;
////    PhylogenyTreeIterator itorTree(*this);
//    itorTree.Init();
//
//    //
//    while( itorTree.IsDone()==false )
//    {
//        //
//        TreeNode *pncurr = itorTree.GetCurrNode();
//        set<TreeNode *> setLeavesUnder;
//        pncurr->GetAllLeavesUnder( setLeavesUnder );
//        set<TreeNode *> setLeavesSS;
//        JoinSetsGen( setLeavesUnder, setLeavesRemain, setLeavesSS );
//        if( setLeavesSS.size()>0 )
//        {
//            setSubtreeClades[pncurr] =  setLeavesSS;
//            SubtractSetsGen(setLeavesRemain, setLeavesSS );
//        }
//        itorTree.Next();
//    }
//}
    
// find the set of clades in the subtree specified by the given leaf nodes
void PhylogenyTreeBasic :: FindCladeOfSubsetLeavesExact( const set<TreeNode *> &setLeaves, set< set<TreeNode *> > &setSubtreeClades  )
{
    // caution: do not check whether these are true leaves
    TreeNode *pRoot = this->GetRoot();
    set<TreeNode *> setAllNodes;
    pRoot->GetAllDescendents(setAllNodes);
        
    //
    for( set<TreeNode *> :: iterator it = setAllNodes.begin(); it != setAllNodes.end(); ++it )
    {
        //
        set<TreeNode *> setLeavesUnder;
        (*it)->GetAllLeavesUnder( setLeavesUnder );
        set<TreeNode *> setLeavesSS;
        JoinSetsGen( setLeavesUnder, setLeaves, setLeavesSS );
        if( setLeavesSS == setLeavesUnder )
        {
            setSubtreeClades.insert( setLeavesSS );
        }
    }
}
    
void PhylogenyTreeBasic :: FindSubsetLeavesRootedAt( const set<TreeNode *> &setLeaves, map< TreeNode *, set<TreeNode *> > &setSubtreeClades  )
{
#if 0
cout << "FindSubsetLeavesRootedAt: setLeaves: ";
for(set<TreeNode *> :: const_iterator it = setLeaves.begin(); it != setLeaves.end(); ++it)
{
(*it)->Dump();
}
cout << endl;
#endif
    // caution: do not check whether these are true leaves; different from previous version, this one stors the subtree root
    // i.e. find all clades (that all leaves in the specified leaves) that is attached to a parent node
    setSubtreeClades.clear();
    set<TreeNode *> setLeavesRemain = setLeaves;
    PhylogenyTreeIteratorPreOrder itorTree(*this);
    itorTree.Init();
    
    //
    while( itorTree.IsDone()==false )
    {
        //
        TreeNode *pncurr = itorTree.GetCurrNode();
        // first test if this lin is wholey contained
        set<TreeNode *> setLeavesUnder0;
        pncurr->GetAllLeavesUnder(setLeavesUnder0);
        if( IsSetContainerGen(setLeavesRemain, setLeavesUnder0) )
        {
            setSubtreeClades[pncurr].insert(pncurr);
            SubtractSetsGen(setLeavesRemain, setLeavesUnder0);
#if 0
cout << "Adding whole subtree: ";
pncurr->Dump();
cout << endl;
#endif
        }
        else if( pncurr->GetChildrenNum() > 2)
        {
            // find if it is contained in more than two branches
            int numBranchesContained = 0;
            for(int i=0; i<pncurr->GetChildrenNum(); ++i)
            {
                TreeNode *pnc = pncurr->GetChild(i);
                set<TreeNode *> setLeavesUnder;
                pnc->GetAllLeavesUnder( setLeavesUnder );
                //cout << "Under node ";
                //pnc->Dump();
                //cout << " setLeaves: ";
                //for(set<TreeNode *> :: const_iterator it = setLeavesUnder.begin(); it != setLeavesUnder.end(); ++it)
                //{
                //    (*it)->Dump();
                //}
                //cout << endl;
                // see if it is in the setLeaves
                if( IsSetContainerGen(setLeavesRemain, setLeavesUnder) )
                {
                    ++numBranchesContained;
                }
            }
            
            if( numBranchesContained >= 2 && (pncurr != GetRoot() || numBranchesContained <=pncurr->GetChildrenNum()-2))
            {
            
                for(int i=0; i<pncurr->GetChildrenNum(); ++i)
                {
                    TreeNode *pnc = pncurr->GetChild(i);
                    set<TreeNode *> setLeavesUnder;
                    pnc->GetAllLeavesUnder( setLeavesUnder );
        //cout << "Under node ";
        //pnc->Dump();
        //cout << " setLeaves: ";
        //for(set<TreeNode *> :: const_iterator it = setLeavesUnder.begin(); it != setLeavesUnder.end(); ++it)
        //{
        //    (*it)->Dump();
        //}
        //cout << endl;
                    // see if it is in the setLeaves
                    if( IsSetContainerGen(setLeavesRemain, setLeavesUnder) )
                    {
                        setSubtreeClades[pncurr].insert(pnc);
                        SubtractSetsGen(setLeavesRemain, setLeavesUnder);
#if 0
cout << "Adding one branch ";
pnc->Dump();
cout << " under parent: ";
pncurr->Dump();
cout << endl;
#endif
                    }
                }
            }
        }
        if( setLeavesRemain.size() == 0 )
        {
            break;
        }
        
        itorTree.Next();
    }
}
    
void PhylogenyTreeBasic :: GroupLeavesToSubtrees( const set<TreeNode *> &setLeaves,  const set<set<TreeNode *> > &cladeNodesToProc, set< set<TreeNode *> > &setSubtreeClades  )
{
    // group the leaves into subtrees (i.e. the subtrees contains exactly those appear in the leaves
    // YW: note this is not the most realistic way (say you have one noisy leaf sepearting two otherwise fully connected catepillar tree,
    // then the result willl be a lot more trees to use). But this servers as a starting point
    // YW: here, we are given some subset out of some pre-specified leaf set, and some subsets (clades) over these leaves; 
    // we want to find the set of maximal clades containing partition these leaves
    //TreeNode *pRoot = this->GetRoot();
    //set<TreeNode *> setAllNodes;
    //pRoot->GetAllDescendents(setAllNodes);
    
    // order based on the size
    map<int, set<set<TreeNode *> > > mapSubtreeSz;
    //for( set<TreeNode *> :: iterator it = setAllNodes.begin(); it != setAllNodes.end(); ++it)
    for( set<set<TreeNode *> > :: const_iterator it = cladeNodesToProc.begin(); it != cladeNodesToProc.end(); ++it )
    {
        // 
        //set<TreeNode *> setLeavesUnder;
        //(*it)->GetAllLeavesUnder( setLeavesUnder );
        if( mapSubtreeSz.find( it->size() ) == mapSubtreeSz.end() )
        {
            set<set<TreeNode *> > ss;
            mapSubtreeSz.insert( map<int, set<set<TreeNode *> > > :: value_type(it->size(), ss) );
        }
        mapSubtreeSz[it->size()].insert( *it );
    }
    
    // reverse order
    set<TreeNode *> setNodesProc = setLeaves;
    for( map<int, set<set<TreeNode *> > > :: reverse_iterator rit = mapSubtreeSz.rbegin(); rit != mapSubtreeSz.rend(); ++rit )
    {
        //
        for( set<set<TreeNode *> > :: iterator itg = rit->second.begin(); itg != rit->second.end(); ++itg )
        {
            //
            set<TreeNode *> setLeavesSS;
            JoinSetsGen( *itg, setNodesProc, setLeavesSS );
            if(  setLeavesSS.size() == itg->size() )
            {
                // find a good match here, use it
                setSubtreeClades.insert(*itg);
                SubtractSetsGen( setNodesProc, *itg );
            }
        }
        if( setNodesProc.size() == 0 )
        {
            break;
        }
    }
    YW_ASSERT_INFO( setNodesProc.size() == 0, "Fail to classify all subtrees" );
}
    
void PhylogenyTreeBasic :: GroupLeavesToSubtreesSamePar( const set<TreeNode *> &setLeaves,  const set<set<TreeNode *> > &cladeNodesToProc, set< set<TreeNode *> > &setSubtreeClades  )
{
    // group leaves that form subtrees w/ same parents. Difference from above: for two subtrees that share the same parent
    // but could be other branches, put the together
    GroupLeavesToSubtrees( setLeaves, cladeNodesToProc, setSubtreeClades );
    // now see whether we can combine subtrees s.t. the combined one is still contined in some parent
    map< set<TreeNode *>, set<TreeNode *> > mapSubtreesToPar;
    for( set< set<TreeNode *> > :: iterator it = setSubtreeClades.begin(); it != setSubtreeClades.end(); ++it )
    {
        for( set<set<TreeNode *> > :: iterator itg = cladeNodesToProc.begin(); itg != cladeNodesToProc.end(); ++itg)
        {
            //
            if( *itg != *it && itg->size() > it->size() && (  mapSubtreesToPar.find(*it) == mapSubtreesToPar.end() || mapSubtreesToPar[*it].size() > itg->size() ) )
            {
                //
                set<TreeNode *> sint;
                JoinSetsGen(*itg, *it, sint);
                if( sint.size() == it->size() )
                {
                    //
                    if( mapSubtreesToPar.find( *it) == mapSubtreesToPar.end() )
                    {
                        mapSubtreesToPar.insert( map< set<TreeNode *>, set<TreeNode *> > :: value_type(*it, *itg) );
                    }
                    else
                    {
                        mapSubtreesToPar[*it] = *itg;
                    }
                }
            }
        }
    }
    map< set<TreeNode *>, set<TreeNode *> > mapRevParToSubtrees;
    for( map< set<TreeNode *>, set<TreeNode *> > :: iterator it = mapSubtreesToPar.begin(); it != mapSubtreesToPar.end(); ++it )
    {
        //
        if( mapRevParToSubtrees.find(it->second) == mapRevParToSubtrees.end() )
        {
            mapRevParToSubtrees.insert( map< set<TreeNode *>, set<TreeNode *> > :: value_type(it->second, it->first) );
        }
        else
        {
            UnionSetsGen( mapRevParToSubtrees[it->second], it->first );
        }
    }
    setSubtreeClades.clear();
    for(map< set<TreeNode *>, set<TreeNode *> > :: iterator it = mapRevParToSubtrees.begin(); it != mapRevParToSubtrees.end(); ++it )
    {
        setSubtreeClades.insert( it->second );
    }
}

    
void PhylogenyTreeBasic :: GetAllClades(set<set<int> > &setClades)
{
    //
    setClades.clear();
    // now clean it by removing each node that does not appear in that
	PhylogenyTreeIterator itorTree(*this);
	itorTree.Init();
	while(itorTree.IsDone() == false )
	{
		TreeNode *pn = itorTree.GetCurrNode();
		itorTree.Next();
		if( pn == NULL)
		{
			break;      // done with all nodes
		}
        //cout << "node id = " << pn->GetID() << endl;
        set<TreeNode *> setDescendents;
        pn->GetAllLeavesUnder(setDescendents);
        set<int> sint;
        for(set<TreeNode *> :: iterator itg=setDescendents.begin(); itg != setDescendents.end(); ++itg)
        {
            sint.insert( (*itg)->GetIntLabel() );
        }
        setClades.insert( sint );
        
	}
}
void PhylogenyTreeBasic :: GetAllCladesNodes(map<TreeNode *, set<int> > &setClades)
{
    //
    setClades.clear();
    // now clean it by removing each node that does not appear in that
    PhylogenyTreeIterator itorTree(*this);
    itorTree.Init();
    while(itorTree.IsDone() == false )
    {
        TreeNode *pn = itorTree.GetCurrNode();
        itorTree.Next();
        if( pn == NULL)
        {
            break;      // done with all nodes
        }
        //cout << "node id = " << pn->GetID() << endl;
        set<TreeNode *> setDescendents;
        pn->GetAllLeavesUnder(setDescendents);
        set<int> sint;
        for(set<TreeNode *> :: iterator itg=setDescendents.begin(); itg != setDescendents.end(); ++itg)
        {
            sint.insert( (*itg)->GetIntLabel() );
        }
        setClades[pn] = sint;
    }
}
void PhylogenyTreeBasic :: GetAllCladesNodes2(map<TreeNode *, set<int> > &setClades)
{
    //
    // now clean it by removing each node that does not appear in that
    PhylogenyTreeIterator itorTree(*this);
    itorTree.Init();
    while(itorTree.IsDone() == false )
    {
        TreeNode *pn = itorTree.GetCurrNode();
        itorTree.Next();
        set<int> sint;
        if( pn == NULL)
        {
            break;      // done with all nodes
        }
        if( pn->IsLeaf() )
        {
            sint.insert(pn->GetIntLabel());
        }
        else
        {
            // union all children
            for(int nc=0; nc<pn->GetChildrenNum(); ++nc)
            {
                TreeNode *pnc = pn->GetChild(nc);
                map<TreeNode *, set<int> > :: iterator it23 = setClades.find(pnc);
                YW_ASSERT_INFO(it23 != setClades.end(), "Cannot find child");
                UnionSets(sint, it23->second);
            }
        }
        setClades[pn] = sint;
    }
}
    
void PhylogenyTreeBasic :: GetAllCladesInt(set<set<int> > &setClades, int lvIdIn)
{
    // ASSUME: all leaf ids from 0 to NUM-LEAVES-1
    int numLvs = GetNumLeaves();
    
    setClades.clear();
    map<TreeNode *, set<int> > mapNodeClade;
    // now clean it by removing each node that does not appear in that
    PhylogenyTreeIterator itorTree(*this);
    itorTree.Init();
    while(itorTree.IsDone() == false )
    {
        TreeNode *pn = itorTree.GetCurrNode();
        itorTree.Next();
        if( pn == NULL)
        {
            break;      // done with all nodes
        }
        if( pn->IsRoot() )
        {
            continue;
        }
        
        if( pn->IsLeaf() )
        {
            set<int> sint;
            sint.insert( pn->GetIntLabel() );
            mapNodeClade[pn] = sint;
        }
        else
        {
            //cout << "node id = " << pn->GetID() << endl;
            set<int> ssInt;
            for(int i=0; i<pn->GetChildrenNum(); ++i)
            {
                TreeNode *pc = pn->GetChild(i);
                map<TreeNode *, set<int> > :: iterator it = mapNodeClade.find(pc);
                YW_ASSERT_INFO(it!=mapNodeClade.end(), "didn't get the child");
                UnionSets(ssInt, it->second);
            }
            mapNodeClade[pn] = ssInt;
            if( lvIdIn >=0 && ssInt.find(lvIdIn)==ssInt.end() )
            {
                // use complment
                set<int> ssIntNew;
                for(int j=0; j<numLvs; ++j)
                {
                    if( ssInt.find(j) == ssInt.end() )
                    {
                        ssIntNew.insert(j);
                    }
                };
                setClades.insert(ssIntNew);
            }
            else
            {
                setClades.insert(ssInt);
            }
        }
    }
}
    
void PhylogenyTreeBasic :: GetAllSiblings(set<set<set<int> > > &setSiblingsSets)
{
    //
    setSiblingsSets.clear();
    // now clean it by removing each node that does not appear in that
    PhylogenyTreeIterator itorTree(*this);
    itorTree.Init();
    while(itorTree.IsDone() == false )
    {
        TreeNode *pn = itorTree.GetCurrNode();
        itorTree.Next();
        if( pn == NULL)
        {
            break;      // done with all nodes
        }
        if( pn->IsLeaf() == false)
        {
            //cout << "node id = " << pn->GetID() << endl;
            set<TreeNode *> setChildren;
            pn->GetAllChildren(setChildren);
            set<set<int> > ssChild;
            for(set<TreeNode *>::iterator it = setChildren.begin(); it != setChildren.end(); ++it)
            {
                TreeNode *pc = *it;
                set<TreeNode *> setDescendents;
                pc->GetAllLeavesUnder(setDescendents);
                set<int> sint;
                for(set<TreeNode *> :: iterator itg=setDescendents.begin(); itg != setDescendents.end(); ++itg)
                {
                    sint.insert( (*itg)->GetIntLabel() );
                }
                ssChild.insert(sint);
            }
            setSiblingsSets.insert( ssChild );
        }
    }
}
    
void PhylogenyTreeBasic :: GetAllCladesList(vector<set<int> > &listClades)
{
    listClades.clear();
    // now clean it by removing each node that does not appear in that
    PhylogenyTreeIterator itorTree(*this);
    itorTree.Init();
    while(itorTree.IsDone() == false )
    {
        TreeNode *pn = itorTree.GetCurrNode();
        itorTree.Next();
        if( pn == NULL)
        {
            break;      // done with all nodes
        }
        //cout << "node id = " << pn->GetID() << endl;
        set<TreeNode *> setDescendents;
        pn->GetAllLeavesUnder(setDescendents);
        set<int> sint;
        for(set<TreeNode *> :: iterator itg=setDescendents.begin(); itg != setDescendents.end(); ++itg)
        {
            sint.insert( (*itg)->GetIntLabel() );
        }
        listClades.push_back( sint );
        
    }
}

// different from the above, (1) we allow duplicate int-labels (and thus multiset)
// (2) group clades by common parents
void PhylogenyTreeBasic :: GetAllCladeGroupsIntLabel( multiset< multiset< multiset<int> > > & setCladeGroupsDupLabels, multiset<int> &rootClade )
{
    // group all clades by parent nodes (i.e. clades with same parent are in one class)
    // root clade: the one with all leaves
    map<TreeNode *, multiset< multiset<int> > >  mapCladeGroupsForNode;
    
    //
    setCladeGroupsDupLabels.clear();
    rootClade.clear();
    // now clean it by removing each node that does not appear in that
    PhylogenyTreeIterator itorTree(*this);
    itorTree.Init();
    while(itorTree.IsDone() == false )
    {
        TreeNode *pn = itorTree.GetCurrNode();
        itorTree.Next();
        if( pn == NULL)
        {
            break;      // done with all nodes
        }
        //cout << "node id = " << pn->GetID() << endl;
        set<TreeNode *> setDescendents;
        pn->GetAllLeavesUnder(setDescendents);
        multiset<int> sint;
        for(set<TreeNode *> :: iterator itg=setDescendents.begin(); itg != setDescendents.end(); ++itg)
        {
            sint.insert( (*itg)->GetIntLabel() );
        }
        TreeNode *pnPar = pn->GetParent();
        if( pnPar == NULL)
        {
            // this is the root clade
            rootClade = sint;
        }
        else
        {
            if( mapCladeGroupsForNode.find(pnPar) == mapCladeGroupsForNode.end() )
            {
                multiset< multiset<int> > mms;
                mapCladeGroupsForNode.insert( map<TreeNode *, multiset< multiset<int> > > :: value_type(pnPar, mms) );
            }
            mapCladeGroupsForNode[pnPar].insert( sint );
        }
    }
    YW_ASSERT_INFO( rootClade.size() > 0, "Fail to collect root clade" );
    for( map<TreeNode *, multiset< multiset<int> > > :: iterator it = mapCladeGroupsForNode.begin(); it != mapCladeGroupsForNode.end(); ++it )
    {
        //
        setCladeGroupsDupLabels.insert( it->second );
    }
}
    
    
void PhylogenyTreeBasic :: GetAllCladesById(set<set<int> > &setClades)
{
    //
    setClades.clear();
    // now clean it by removing each node that does not appear in that
    PhylogenyTreeIterator itorTree(*this);
    itorTree.Init();
    while(itorTree.IsDone() == false )
    {
        TreeNode *pn = itorTree.GetCurrNode();
        itorTree.Next();
        if( pn == NULL)
        {
            break;      // done with all nodes
        }
        //cout << "node id = " << pn->GetID() << endl;
        set<TreeNode *> setDescendents;
        pn->GetAllLeavesUnder(setDescendents);
        set<int> sint;
        for(set<TreeNode *> :: iterator itg=setDescendents.begin(); itg != setDescendents.end(); ++itg)
        {
            sint.insert( (*itg)->GetID() );
        }
        setClades.insert( sint );
        
    }
}

    
void PhylogenyTreeBasic :: GetAllCladeNodess(set<set<TreeNode *> > &setClades)
{
    //
    setClades.clear();
    // now clean it by removing each node that does not appear in that
    PhylogenyTreeIterator itorTree(*this);
    itorTree.Init();
    while(itorTree.IsDone() == false )
    {
        TreeNode *pn = itorTree.GetCurrNode();
        itorTree.Next();
        if( pn == NULL)
        {
            break;      // done with all nodes
        }
        //cout << "node id = " << pn->GetID() << endl;
        set<TreeNode *> setDescendents;
        pn->GetAllLeavesUnder(setDescendents);
        
        setClades.insert( setDescendents );
        
    }
}
    
TreeNode * PhylogenyTreeBasic :: GetSubtreeRootForLeaves( const set<TreeNode *> &setLvNodes )
{
    PhylogenyTreeIterator itorTree(*this);
    itorTree.Init();
    while(itorTree.IsDone() == false )
    {
        TreeNode *pn = itorTree.GetCurrNode();
        itorTree.Next();
        if( pn == NULL)
        {
            break;      // done with all nodes
        }
        //cout << "node id = " << pn->GetID() << endl;
        set<TreeNode *> setDescendents;
        pn->GetAllLeavesUnder(setDescendents);
        
        if( setLvNodes ==  setDescendents )
        {
            return pn;
        }
        
    }
    return NULL;
    
}


void PhylogenyTreeBasic :: GroupNodesWithCommonPars( const set<TreeNode *> &setNodes, map<TreeNode *, set<TreeNode *> >  &mapNodesWithSamePar )
{
    //
    mapNodesWithSamePar.clear();
    for( set<TreeNode *> :: const_iterator it = setNodes.begin(); it != setNodes.end(); ++it )
    {
        //
        TreeNode *ppar = (*it)->GetParent();
        if( mapNodesWithSamePar.find( ppar) == mapNodesWithSamePar.end() )
        {
            set<TreeNode *> ss;
            mapNodesWithSamePar.insert( map<TreeNode *, set<TreeNode *> > :: value_type(ppar, ss) );
        }
        mapNodesWithSamePar[ppar].insert( *it );
    }
}
    
void PhylogenyTreeBasic :: RemoveEdgeLabels()
{
    //
    this->rootNode->RemoveLabels();
}

void PhylogenyTreeBasic :: RemoveEdgeLabelsToLeaves()
{
    // get all leaves
    vector<TreeNode *> vecLeaves;
    GetAllLeafNodes( vecLeaves );
    for(int i=0; i<(int)vecLeaves.size(); ++i)
    {
        vecLeaves[i]->RemoveLabelsPar();
    }
}
    
void PhylogenyTreeBasic :: IncEdgeLabelsBy(int offset)
{
    // inc edge label of this node (and subtree if needed)
    this->rootNode->IncEdgeLabelsBy(offset, true);
}
    
string PhylogenyTreeBasic :: GetShapeLabelNodeBrNum( map<TreeNode *, pair<int,int> > &mapNodeNumBrannches, vector<int> &listOrderedLeaves)
{
    // format: <num of underlying branches, event id>, negative for internal nodes
    map<TreeNode *,pair<int,int> > mapNodeNumBrannchesUse = mapNodeNumBrannches;
    // given: num of branches at each node,
    // return shape label as empty Newick format
    // for this, first need to find out all nodes that all descendents have appeared in the tree
    set<TreeNode *> setAncesNotGiven;
    for( map<TreeNode *,pair<int,int> > :: iterator it = mapNodeNumBrannches.begin(); it != mapNodeNumBrannches.end(); ++it )
    {
        set<TreeNode *> setAllAnces;
        it->first->GetAllAncestors(setAllAnces);
        for( set<TreeNode *> :: iterator itg = setAllAnces.begin(); itg != setAllAnces.end(); ++itg)
        {
            if( mapNodeNumBrannches.find(*itg) == mapNodeNumBrannches.end() )
            {
                //
                pair<int,int> pp(-1,-1);
                mapNodeNumBrannchesUse.insert( map<TreeNode*,pair<int,int> > :: value_type(*itg,pp) );
            }
        }
    }
    // now call the root to find the label
    return this->rootNode->GetShapeLabelNodeBrNum(mapNodeNumBrannchesUse, listOrderedLeaves);
}
    
void PhylogenyTreeBasic :: MakeSubtreeUnrefined(TreeNode *pSubtree)
{
    // make this subtree unrefined (i.e. each leaf points to the root
    // CAUTION: all edge labels are LOST!!!!
    set<TreeNode *> setAllLeavesUnder;
    pSubtree->GetAllLeavesUnder( setAllLeavesUnder );
//cout << "setAllLeavesUnder: ";
//for( set<TreeNode *> :: iterator it = setAllLeavesUnder.begin(); it != setAllLeavesUnder.end(); ++it)
//{
//(*it)->Dump();
//}
//cout << endl;
    set<TreeNode *> setAllDescUnder;
    pSubtree->GetAllDescendents( setAllDescUnder );
//cout << "setAllDescUnder: ";
//for( set<TreeNode *> :: iterator it = setAllDescUnder.begin(); it != setAllDescUnder.end(); ++it)
//{
//(*it)->Dump();
//}
//cout << endl;
    
    // detach all leaves from their parent
    for( set<TreeNode *> :: iterator it = setAllLeavesUnder.begin(); it != setAllLeavesUnder.end(); ++it )
    {
        //
        TreeNode *ppar = (*it)->GetParent();
        ppar->RemoveChild(*it);
    }
    
    pSubtree->RemoveAllChildren();

    // remove all descendent except the leaves
    for( set<TreeNode *> :: iterator it = setAllDescUnder.begin(); it != setAllDescUnder.end(); ++it)
    {
        // need to be careful b/c node deletion is recurisvely
        if( setAllLeavesUnder.find(*it) == setAllLeavesUnder.end() && (*it) != pSubtree && ( (*it)->GetParent() == pSubtree ) )
        {
//cout << "Delete this node: ";
//(*it)->Dump();
            delete *it;
        }
    }
    // then add the leaves directly under the subtree root
    for( set<TreeNode *> :: iterator it = setAllLeavesUnder.begin(); it != setAllLeavesUnder.end(); ++it )
    {
        vector<int> lblEmpty;
        pSubtree->AddChild( *it, lblEmpty );
    }
//string strTree;
//ConsNewick(strTree);
//cout << "After MakeSubtreeUnrefiined: tree is " << strTree << endl;
}
    
void PhylogenyTreeBasic :: Binarize()
{
    // make the tree binary
    int idToUseNext = this->rootNode->GetMaxIdWithinSubtree() + 1;
    this->rootNode->Binarize( idToUseNext );
//string strTree;
//ConsNewick(strTree);
//cout << "After binarization: tree is " << strTree << endl;
}
    
void PhylogenyTreeBasic :: RefineByNumMuts()
{
    // make the tree binary based on the number of sites (mutations) in the sense of ultrametric tree
    // first collect the height of each node. Height: max number of sites from the node to some leaf below. To do this, collect num of sites alogn the branch into each node first
    map<TreeNode *, int> mapNodeNumMuts;
    mapNodeNumMuts[ GetRoot() ] = 0;
    PhylogenyTreeIterator itor(*this);
    itor.Init();
    while( itor.IsDone() == false)
    {
        TreeNode *pn = itor.GetCurrNode();
        for(int i=0; i<pn->GetChildrenNum(); ++i)
        {
            TreeNode *pc = pn->GetChild(i);
            vector<int> listLbl;
            pn->GetEdgeLabelsAtBranch(i, listLbl);
            mapNodeNumMuts[ pc ] = listLbl.size();
        }
        itor.Next();
    }
    // get heights
    map<TreeNode *, int> mapNodeHts;
    itor.Init();
    while( itor.IsDone() == false)
    {
        TreeNode *pn = itor.GetCurrNode();
        int ht = 0;
        if( pn->IsLeaf() == false )
        {
            for(int i=0; i<pn->GetChildrenNum(); ++i)
            {
                TreeNode *pc = pn->GetChild(i);
                int numMutsEdge = mapNodeNumMuts[pc];
                int htstep = mapNodeHts[pc] + numMutsEdge;
                if( htstep > ht )
                {
                    ht = htstep;
                }
            }
        }
        mapNodeHts[pn] = ht;
        itor.Next();
    }
    
    // Now, refine each non-binary node based on the heights
    vector<TreeNode *> listNodesRef;
    itor.Init();
    while( itor.IsDone() == false)
    {
        TreeNode *pn = itor.GetCurrNode();
        if( pn->GetChildrenNum() >= 3 )
        {
            listNodesRef.push_back( pn );
        }
        itor.Next();
    }
    
    int idToUseNext = this->rootNode->GetMaxIdWithinSubtree() + 1;
    for(unsigned int i=0; i<listNodesRef.size(); ++i)
    {
        // group nodes with the same number of
        TreeNode *pncurr = listNodesRef[i];
        map<int, set<TreeNode *> > mapHtChildNodes;
        for(int c=0; c<pncurr->GetChildrenNum(); ++c)
        {
            //
            TreeNode *pnchild = pncurr->GetChild(c);
            map<TreeNode *,int> :: iterator ittg = mapNodeNumMuts.find(pnchild);
            YW_ASSERT_INFO( ittg != mapNodeNumMuts.end(), "Fail to fiind 223" );
            int htc = mapNodeHts[pnchild] + ittg->second;
            mapHtChildNodes[htc].insert( pnchild );
        }
        
        // do nothing if there is a single class
        if( mapHtChildNodes.size() <= 1 )
        {
            continue;
        }
        
        // now place all the nodes with the same height into one class
        // so that it forms the
        TreeNode *pnAddedLast = NULL;
        set<TreeNode *> setChildrenProc;
        for( map<int, set<TreeNode *> > :: iterator ittc = mapHtChildNodes.begin(); ittc != mapHtChildNodes.end(); ++ittc )
        {
            if( nextItem(ittc) != mapHtChildNodes.end() )
            {
                UnionSetsGen( setChildrenProc, ittc->second );
            }
            
            // create a new node if this is not the first one (which is singleton) and the last one in the list
            if( (ittc != mapHtChildNodes.begin() || ittc->second.size() >= 2 ) && nextItem(ittc) != mapHtChildNodes.end() )
            {
                //
                TreeNode *pnode = new TreeNode(idToUseNext++);
                vector<int> ss;
                for( set<TreeNode *> :: iterator ittb = ittc->second.begin(); ittb != ittc->second.end(); ++ittb  )
                {
                    pnode->AddChild( *ittb, ss );
                }
                YW_ASSERT_INFO( pnAddedLast != NULL || ittc == mapHtChildNodes.begin(), "WRONG!"  );
                if( pnAddedLast != NULL )
                {
                    pnode->AddChild(pnAddedLast, ss);
                }
                pnAddedLast = pnode;
            }
            if( ittc == mapHtChildNodes.begin() && ittc->second.size() == 1 )
            {
                // if there is only one added
                pnAddedLast = *( ittc->second.begin() );
            }
        }
        
        // setup the children for the last level
        pncurr->RemoveChildren( setChildrenProc );
        YW_ASSERT_INFO( pnAddedLast!=NULL, "Added last: null" );
        vector<int> ss;
        pncurr->AddChild( pnAddedLast, ss );
    }
}
    
void PhylogenyTreeBasic :: CreatePhyTreeFromLeavesWithLabels( const set<string> &setLeafLabels, PhylogenyTreeBasic &treeSubsetLeaves, bool fUseOldTaxonName)
{
    // given a set of leaf labels, construct another phylogenetic tree that is extracted
    // from the current tree by only taking those leaves with one of the given labels
    // YW: caution: all taxa names are mapped to 0,1,2,... according to their order in list if fUseOldTaxonName=false
    // otherwise, keep the original flag
    set<int> setSubsetLeaves;
    map<int, string> mapOrigIdToOrigStrLbl;
    int idToUseFirst=0;
    for( set<string> :: const_iterator it = setLeafLabels.begin(); it != setLeafLabels.end(); ++it)
    {
        string lblcur = *it;
        set<int> setSubsetLeavesStep;
        GetLeavesIdsWithLabel( lblcur, setSubsetLeavesStep );
//cout << "CreatePhyTreeFromLeavesWithLabels: lblcur: " << lblcur <<" setSubsetLeavesStep: ";
//DumpIntSet(setSubsetLeavesStep);
        UnionSets( setSubsetLeaves, setSubsetLeavesStep );
        
        string lblToUse = lblcur;
        if( fUseOldTaxonName == false )
        {
            char buf[100];
            snprintf(buf, 100, "%d", idToUseFirst++);
            lblToUse = buf;
        }
        for( set<int> :: iterator it2 = setSubsetLeavesStep.begin(); it2 != setSubsetLeavesStep.end(); ++it2 )
        {
            //mapOrigIdToOrigStrLbl.insert( map<int,string> :: value_type(*it2, lblcur) );
            mapOrigIdToOrigStrLbl.insert( map<int,string> :: value_type(*it2, lblToUse) );
//cout << "mapOrigIdToOrigStrLbl: " << *it2 << ", lblToUse: " << lblToUse << endl;
        }
    }
    
    // get all clades first
    set<set<int> > setClades;
    GetAllCladesById( setClades );
//cout << "All clades: \n";
//for(set<set<int> > :: iterator it = setClades.begin(); it != setClades.end(); ++it)
//{
//DumpIntSet(*it);
//}
    
    // map the remaining id to 0,1,2....
    map<int,int> mapIdToContinue;
    map<int, string> mapContIdToOrigStr;
    int idToUse = 0;
    for(set<int> :: iterator it = setSubsetLeaves.begin(); it != setSubsetLeaves.end(); ++it)
    {
        YW_ASSERT_INFO(mapOrigIdToOrigStrLbl.find(*it) != mapOrigIdToOrigStrLbl.end(), "Fail" );
        mapContIdToOrigStr.insert( map<int,string> :: value_type(idToUse, mapOrigIdToOrigStrLbl[*it] ) );
//cout << "mapContIdToOrigStr: idtouse: " << idToUse << ", string orig: " << mapOrigIdToOrigStrLbl[*it] << endl;
        mapIdToContinue.insert( map<int,int> :: value_type( *it, idToUse++ ) );
    }
    
    
    set<set<int> > setCladesSub;
    // now extract those with only those given
    for( set<set<int> > :: iterator it = setClades.begin(); it != setClades.end(); ++it )
    {
        set<int> sintstep;
        JoinSets(*it, setSubsetLeaves, sintstep);
        if( sintstep.size() > 0 )
        {
            // convert to continuios id first
            set<int> sintstep2;
            MapIntSetTo(sintstep, mapIdToContinue, sintstep2);
            
            setCladesSub.insert( sintstep2 );
            
//cout << "Adding a clade: ";
//DumpIntSet( sintstep2);
//cout << "for orig clade: ";
//DumpIntSet(sintstep);
        }
    }
    
    // now build a tree with these labels
    CreatePhyTreeWithRootedSplits( treeSubsetLeaves, setSubsetLeaves.size(), setCladesSub);
    
    // now map the leaves of the new tree to the original ids
    treeSubsetLeaves.AssignLeafLabels( mapContIdToOrigStr );
    
//cout << "This is the phylogenetic tree constructed from subset of leaves: "
//this->OutputGML("tree1.gml");
//treeSubsetLeaves.OutputGML("t1.gml");
//exit(1);
}
    
void PhylogenyTreeBasic :: AssignLeafLabels( const map<int,string> &mapLeafLbls )
{
    // assign labels stored in the map (format: node id to lbl)
    vector< TreeNode *> listLeafNodes;
    GetAllLeafNodes( listLeafNodes);
    for(int i=0; i<(int)listLeafNodes.size(); ++i)
    {
        int idn = listLeafNodes[i]->GetID();
        map<int,string> :: const_iterator itg = mapLeafLbls.find(idn);
        YW_ASSERT_INFO(itg != mapLeafLbls.end(), "Fail");
        string strLblNew = itg->second;
        listLeafNodes[i]->SetLabel( strLblNew );
        listLeafNodes[i]->SetUserLabel(strLblNew);
    }
}
void PhylogenyTreeBasic :: ReassignLeafLabels( const map<string, string> &mapLeafLbls )
{
    vector< TreeNode *> listLeafNodes;
    GetAllLeafNodes( listLeafNodes);
    for(int i=0; i<(int)listLeafNodes.size(); ++i)
    {
        string str = listLeafNodes[i]->GetLabel();
//cout << "leaf label curr: " << str << endl;
        map<string,string> :: const_iterator itg = mapLeafLbls.find(str);
        
        if( itg == mapLeafLbls.end() )
        {
            // TBD. YW: for now. Need to look at later...
            continue;
        }
        
        YW_ASSERT_INFO(itg != mapLeafLbls.end(), "Fail");
        string strLblNew = itg->second;
        listLeafNodes[i]->SetLabel( strLblNew );
        listLeafNodes[i]->SetUserLabel(strLblNew);
    }
}
    
void PhylogenyTreeBasic :: SetUserLabelToCurrLabels()
{
    vector< TreeNode *> listLeafNodes;
    GetAllLeafNodes( listLeafNodes);
    for(int i=0; i<(int)listLeafNodes.size(); ++i)
    {
        listLeafNodes[i]->SetUserLabel( listLeafNodes[i]->GetLabel() );
    }
}
    
void PhylogenyTreeBasic :: SetLabelsToCurrUserLabels()
{
    vector< TreeNode *> listLeafNodes;
    GetAllLeafNodes( listLeafNodes);
    for(int i=0; i<(int)listLeafNodes.size(); ++i)
    {
        listLeafNodes[i]->SetLabel( listLeafNodes[i]->GetUserLabel() );
    }
}
    
    
int PhylogenyTreeBasic :: GetMaxDegree() const
{
    int res = 0;
    
    PhylogenyTreeBasic &thisTree = const_cast<PhylogenyTreeBasic &>(*this);
    PhylogenyTreeIterator itor(thisTree);
    itor.Init();
    while(itor.IsDone() == false )
    {
        TreeNode *pn = itor.GetCurrNode();

        int degThis = pn->GetChildrenNum();
        if( degThis > res )
        {
            res = degThis;
        }
        
        itor.Next();
    }
    return res;
}
    
void PhylogenyTreeBasic :: Dump() const
{
    // dump all nodes
    PhylogenyTreeBasic &thisTree = const_cast<PhylogenyTreeBasic &>(*this);
    PhylogenyTreeIterator itor(thisTree);
    itor.Init();
    while(itor.IsDone() == false )
    {
        TreeNode *pn = itor.GetCurrNode();
        pn->Dump();
        cout << endl;
        itor.Next();
    }
}
    
void PhylogenyTreeBasic :: GetSubtreesWithMaxSize(set<TreeNode *> &setSTRoots, int maxSzSubtree) const
{
#if 0
    // YW: this piece of code is not used
    set<TreeNode *> setSTRootsStep;
    set<string> setLblsEmpty;
    GetSubtreesWithMaxSizeExcludeTaxa( setSTRootsStep, maxSzSubtree, setLblsEmpty );
    
    // find out any missing taxa
    set<string> setLblsCovered;
    for(set<TreeNode *> :: iterator it = setSTRootsStep.begin(); it != setSTRootsStep.end(); ++it )
    {
        set<string> setLblsCoveredStep;
        (*it)->GetAllDistinctLeafLabeles(setLblsCoveredStep);
        UnionSetsGen( setLblsCovered, setLblsCoveredStep );
        
cout << "setLblsCoveredStep: ";
for(set<string> :: iterator it = setLblsCoveredStep.begin(); it != setLblsCoveredStep.end(); ++it)
{
cout << *it << "  ";
}
cout << endl;
    }
    set<string> setLblsExc;
    this->GetRoot()->GetAllDistinctLeafLabeles( setLblsExc );
    SubtractSetsGen( setLblsExc, setLblsCovered );
cout << "setLblsExc: ";
for(set<string> :: iterator it = setLblsExc.begin(); it != setLblsExc.end(); ++it)
{
cout << *it << "  ";
}
cout << endl;
    
    // now do it again so to allow those with these "free" taxa
    GetSubtreesWithMaxSizeExcludeTaxa( setSTRoots, maxSzSubtree, setLblsExc);
#endif
    
//#if 0
    // retrieve roots of subtrees that are no biggere than the specified size
    setSTRoots.clear();
    stack<TreeNode *> stackTrNodes;
    stackTrNodes.push( this->GetRoot() );
    
    while( stackTrNodes.size() > 0 )
    {
        //
        TreeNode *pncurr = stackTrNodes.top();
        stackTrNodes.pop();
        
        // save it if this subtree size is not too big
        set<TreeNode *> setDescendents;
        pncurr->GetAllLeavesUnder(setDescendents);
//cout << "pncur: number of descendents: " << setDescendents.size() << " ";
//pncurr->Dump();
        if( (int)setDescendents.size() <= maxSzSubtree )
        {
//cout << "Adding tis node.\n";
            setSTRoots.insert(pncurr);
        }
        else
        {
//cout << "Process each of its descendents.\n";
            // then check all its descendents
            for(int i=0; i<pncurr->GetChildrenNum(); ++i)
            {
                TreeNode *pnc = pncurr->GetChild(i);
                stackTrNodes.push(pnc);
//cout << "pushing child: ";
//pnc->Dump();
            }
        }
    }
//#endif
}
  
void PhylogenyTreeBasic :: GetMaxSubtrees( set<TreeNode *> &setSTRootsIdents )
{
    // obtain max subtrees with identical leaf labels
    setSTRootsIdents.clear();
    stack<TreeNode *> stackNodes;
    stackNodes.push(GetRoot() );
    while( stackNodes.empty() == false )
    {
        //
        TreeNode *pncurr = stackNodes.top();
        stackNodes.pop();
        
        vector<string> strLblLeaves;
        pncurr->GetAllLeafLabeles( strLblLeaves );
        set<string> strLblLeavesSet;
        PopulateSetByVecGen( strLblLeavesSet, strLblLeaves);
        YW_ASSERT_INFO(strLblLeavesSet.size() >=1, "Must have at least one label");
        if( strLblLeavesSet.size() == 1 )
        {
            //
            setSTRootsIdents.insert( pncurr );
        }
        else
        {
            // consider all children
            for(int i=0; i<pncurr->GetChildrenNum(); ++i)
            {
                stackNodes.push( pncurr->GetChild(i) );
            }
        }
    }
}
 
bool PhylogenyTreeBasic :: GetSiblingsPairFrom(const set<TreeNode *> &setNodesToChoose, pair<TreeNode*, TreeNode*> &pairSibs )
{
    // find which pairs of given nodes have the same paent
    bool fres = false;
    
    //
    map<TreeNode *, TreeNode *> mapParToOrigNode;
    for( set<TreeNode *> :: const_iterator it= setNodesToChoose.begin(); it != setNodesToChoose.end(); ++it )
    {
        TreeNode *pp = (*it)->GetParent();
        if( mapParToOrigNode.find( pp ) == mapParToOrigNode.end() )
        {
            mapParToOrigNode.insert( map<TreeNode *, TreeNode *> :: value_type(pp, *it) );
        }
        else
        {
            pairSibs.first = mapParToOrigNode[pp];
            pairSibs.second = *it;
            fres = true;
            break;
        }
    }
#if 0
cout << "GetSiblingsPairFrom: \n";
if( fres == true )
{
cout << "sib1: ";
pairSibs.first->Dump();
cout << "sib2: ";
pairSibs.second->Dump();
}
#endif
    
    return fres;
}
    
bool PhylogenyTreeBasic :: GetSiblingsNodesFrom(const set<TreeNode *> &setNodesToChoose, set<TreeNode*> &setSibs )
{
    // find which nodes from given nodes have the same paent
    // YW: we prefer the lower if there are multiple choices
    bool fres = false;
    
    //
    map<TreeNode *, set<TreeNode *> > mapParToOrigNode;
    for( set<TreeNode *> :: const_iterator it= setNodesToChoose.begin(); it != setNodesToChoose.end(); ++it )
    {
        TreeNode *pp = (*it)->GetParent();
        if( mapParToOrigNode.find( pp ) == mapParToOrigNode.end() )
        {
            set<TreeNode *> ss;
            mapParToOrigNode.insert( map<TreeNode *, set<TreeNode *> > :: value_type(pp, ss) );
        }
        mapParToOrigNode[pp].insert( *it );
    }
    // assign one with at least two nodes
    for( map<TreeNode *, set<TreeNode *> > :: iterator it = mapParToOrigNode.begin(); it != mapParToOrigNode.end(); ++it )
    {
        if( it->second.size() > 1 )
        {
            bool fGood = true;
            
            for( map<TreeNode *, set<TreeNode *> > :: iterator it2 = mapParToOrigNode.begin(); it2 != mapParToOrigNode.end(); ++it2 )
            {
                //
                int dummy;
                if(  it->first != it2->first && (it->first)->IsAncesterOf( it2->first, dummy ) == true )
                {
                    // this one is not lowest
                    fGood = false;
                    break;
                }
            }
            
            if( fGood )
            {
                setSibs = it->second;
                fres = true;
                break;
            }
        }
    }
    
#if 0
    cout << "GetSiblingsPairFrom: \n";
    if( fres == true )
    {
        cout << "sib1: ";
        pairSibs.first->Dump();
        cout << "sib2: ";
        pairSibs.second->Dump();
    }
#endif
    
    return fres;
}
    
    
void PhylogenyTreeBasic :: FindAllLabelsInSubtrees(const set<TreeNode *> &setSTRoots, set<string> &setLabels)
{
    // get all labels
    setLabels.clear();
    for(set<TreeNode *> :: const_iterator it = setSTRoots.begin(); it != setSTRoots.end(); ++it )
    {
        set<string> setLblsCoveredStep;
        (*it)->GetAllDistinctLeafLabeles(setLblsCoveredStep);
        UnionSetsGen( setLabels, setLblsCoveredStep);
    }
}
    
void PhylogenyTreeBasic :: FindDescendentsOfNodeWithin(TreeNode *pAnc, const set<TreeNode *> &setNodesToChoose, set<TreeNode*> &setDescendents)
{
    //
    setDescendents.clear();
    for( set<TreeNode*> :: const_iterator itg = setNodesToChoose.begin(); itg != setNodesToChoose.end(); ++itg )
    {
        int dummy;
        if( pAnc->IsAncesterOf(*itg, dummy) == true )
        {
            setDescendents.insert( *itg );
        }
    }
}
 
bool PhylogenyTreeBasic :: TestIsomorphic(PhylogenyTreeBasic &treeOther, map<TreeNode *, TreeNode *> &mapOldNodeToNew ) const
{
#if 0
cout << "TestIsomorphic: current tree: ";
this->Dump();
cout << "treeOther: ";
treeOther.Dump();
#endif
    // return true if isomorphic (and set the mapping between the leaf nodes
    // collect shape label of two trees. Here, we map each current tree node to the corresponding one of the other
    PhylogenyTreeBasic *pthis = const_cast<PhylogenyTreeBasic *>(this);
    set<int> lvidsThis, lvidsOther;
    pthis->GetLeaveIds( lvidsThis );
    treeOther.GetLeaveIds( lvidsOther );
#if 0
cout << "lvidsThis:";
DumpIntSet(lvidsThis);
cout << "lvidsOther:";
DumpIntSet(lvidsOther);
#endif
    
    map<TreeNode *, string> mapNodeShapeThis, mapNodeShapeOther;
    vector<TreeNode *> listNodesThis, listNodesOther;
    GetAllNodes( listNodesThis );
    treeOther.GetAllNodes( listNodesOther );
    for(int i=0; i<(int)listNodesThis.size(); ++i )
    {
        string strShape = listNodesThis[i]->GetShapeLabel( lvidsThis, true );
        mapNodeShapeThis.insert( map<TreeNode *, string> :: value_type( listNodesThis[i], strShape ) );
//cout << "Find a shape (this):" << strShape << endl;
    }
    for(int i=0; i<(int)listNodesOther.size(); ++i )
    {
        string strShape = listNodesOther[i]->GetShapeLabel( lvidsOther, true );
        mapNodeShapeOther.insert( map<TreeNode *, string> :: value_type( listNodesOther[i], strShape ) );
//cout << "Find a shape (other):" << strShape << endl;
    }
    if( mapNodeShapeThis[ GetRoot() ] != mapNodeShapeOther[ treeOther.GetRoot() ] )
    {
//cout << "Root label mismatch: " << mapNodeShapeThis[ GetRoot()]  << " vs " << mapNodeShapeOther[ treeOther.GetRoot() ]  << endl;
        return false;   // not isomorphic if the root symbol is not isomorhphic
    }
    // we also list the matching nodes of each node (incl. internal)
    mapOldNodeToNew.clear();
    mapOldNodeToNew.insert( map<TreeNode *, TreeNode *> :: value_type( GetRoot(), treeOther.GetRoot() ) );
    stack<TreeNode *> stackNodesToProc;
    stackNodesToProc.push( GetRoot() );
    while( stackNodesToProc.empty() == false )
    {
        TreeNode *pnCurrOld = stackNodesToProc.top();
        stackNodesToProc.pop();
#if 0
cout << "Processing node: ";
pnCurrOld->Dump();
cout << endl;
#endif
        // get all children
        set<TreeNode *> setChildren;
        pnCurrOld->GetAllChildren(setChildren);
        map<string, set<TreeNode *> > setChildrenShape;
        for( set<TreeNode *> :: iterator it = setChildren.begin(); it != setChildren.end(); ++it )
        {
            TreeNode *pchild = *it;
            string strchild = mapNodeShapeThis[pchild];
            if( setChildrenShape.find(strchild) == setChildrenShape.end() )
            {
                set<TreeNode *> ss;
                setChildrenShape.insert( map<string, set<TreeNode *> > :: value_type( strchild, ss ) );
            }
            setChildrenShape[strchild].insert( pchild );
#if 0
cout << "Adding a string:node pair: " << strchild << ": node: ";
pchild->Dump();
cout << endl;
#endif
            // also save for more processing
            stackNodesToProc.push(pchild);
        }
        // now find the matching one
        set<TreeNode *> setChildOther;
        YW_ASSERT_INFO( mapOldNodeToNew.find(pnCurrOld) != mapOldNodeToNew.end(), "Fai to find1" );
        TreeNode *pnCurrOther = mapOldNodeToNew[pnCurrOld];
        pnCurrOther->GetAllChildren( setChildOther );
#if 0
cout << "Now check the matching other: ";
pnCurrOther->Dump();
cout << endl;
#endif
        for( set<TreeNode *> :: iterator it = setChildOther.begin(); it != setChildOther.end(); ++it )
        {
            TreeNode *pchildother = *it;
            string strchildother = mapNodeShapeOther[pchildother];
#if 0
cout << "child(other): ";
pchildother->Dump();
cout << ": stringshape: " << strchildother << endl;
#endif
            YW_ASSERT_INFO( setChildrenShape.find(strchildother) != setChildrenShape.end() && setChildrenShape[strchildother].size() > 0, "Fail to find2" );
            // assign to the first one in the list
            TreeNode *pnmatch = *( setChildrenShape[strchildother].begin() );
            setChildrenShape[strchildother].erase( pnmatch );
#if 0
cout << "Matching: pncurold: ";
pnCurrOld->Dump();
cout << " to pnmatch:";
pnmatch->Dump();
cout << endl;
#endif
            // remember the matching
            mapOldNodeToNew.insert( map<TreeNode *, TreeNode *> :: value_type( pnmatch, pchildother ) );
        }
    }
#if 0
cout << "mapOldNodeToNew: \n";
for( map<TreeNode*, TreeNode*> :: iterator it = mapOldNodeToNew.begin(); it != mapOldNodeToNew.end(); ++it)
{
cout << "oldnode ";
it->first->Dump();
cout << "   to   ";
it->second->Dump();
cout << endl;
}
#endif
    
    return true;
}

void PhylogenyTreeBasic :: CollectUltraPairDists( map<pair<int,int>, double> &mapPairDists )
{
    // assume tree is ultrametric. so the distance depends on LCA height (double it)
    mapPairDists.clear();
    
    map<TreeNode *, double> mapTreeNodesHt;
    PhylogenyTreeIterator itor(*this);
    itor.Init();
    while(itor.IsDone()==false)
    {
        TreeNode *pncurr = itor.GetCurrNode();
        itor.Next();
        
        if( pncurr->IsLeaf())
        {
            mapTreeNodesHt[pncurr] = 0.0;
        }
        else
        {
            // get two children
            double htSum = 0.0;
            for(int i=0; i<pncurr->GetChildrenNum(); ++i)
            {
                TreeNode *pc = pncurr->GetChild(i);
                YW_ASSERT_INFO(mapTreeNodesHt.find(pc) != mapTreeNodesHt.end(), "Not found");
                htSum += mapTreeNodesHt[pc] + pc->GetLength();
            }
            double htUse = htSum/pncurr->GetChildrenNum();
            mapTreeNodesHt[pncurr] = htUse;
        }
    }
    
    //
    for(map<TreeNode *, double> :: iterator it = mapTreeNodesHt.begin(); it != mapTreeNodesHt.end(); ++it)
    {
        TreeNode *pncurr = it->first;
        if( pncurr->IsLeaf())
        {
            continue;
        }
        double htNode = it->second;
        vector<vector<int> > listLeavesUnder;
        for(int i=0; i<pncurr->GetChildrenNum(); ++i)
        {
            TreeNode *pc = pncurr->GetChild(i);
            vector<int> setLeaves;
            pc->GetAllLeafIntLabeles(setLeaves);
            listLeavesUnder.push_back(setLeaves);
        }
        for(int i=0; i<(int)listLeavesUnder.size(); ++i)
        {
            for(int j=i+1; j<(int)listLeavesUnder.size(); ++j)
            {
                for(unsigned int k1=0; k1<listLeavesUnder[i].size(); ++k1 )
                {
                    for(unsigned int k2=0; k2<listLeavesUnder[j].size(); ++k2)
                    {
                        pair<int,int> pp( listLeavesUnder[i][k1], listLeavesUnder[j][k2] );
                        OrderInt(pp.first, pp.second);
                        mapPairDists[pp] = 2*htNode;
                    }
                }
            }
        }
    }
}

void PhylogenyTreeBasic :: GetAllCladesForNodes(map<TreeNode *, set<int> > &mapNodeLeavesBelow)
{
    //
    mapNodeLeavesBelow.clear();
    PhylogenyTreeIterator itor(*this);
    itor.Init();
    while(itor.IsDone() == false)
    {
        TreeNode *pncurr = itor.GetCurrNode();
        if( pncurr->IsLeaf() )
        {
            int nid = pncurr->GetIntLabel();
            set<int> ss;
            ss.insert(nid);
            mapNodeLeavesBelow[pncurr] = ss;
        }
        else
        {
            set<int> ss;
            for(int i=0; i<pncurr->GetChildrenNum(); ++i)
            {
                UnionSets(ss, mapNodeLeavesBelow[pncurr->GetChild(i)]);
            }
            mapNodeLeavesBelow[pncurr] = ss;
        }
        itor.Next();
    }
}
    
void PhylogenyTreeBasic :: ScaleBrLensBy(double facScale)
{
    // Scale each branch by a factor
    PhylogenyTreeIterator itorTree(*this);
    itorTree.Init();
    while( itorTree.IsDone() == false )
    {
        TreeNode *pntree = itorTree.GetCurrNode();
        double len = pntree->GetLength();
        len *= facScale;
        pntree->SetLength(len);
        itorTree.Next();
    }
}
    
double PhylogenyTreeBasic :: GetTreeHeight()
{
    //
    map<TreeNode *, double> mapTreeNodesHt;
    PhylogenyTreeIterator itor(*this);
    itor.Init();
    while(itor.IsDone()==false)
    {
        TreeNode *pncurr = itor.GetCurrNode();
        itor.Next();
        
        if( pncurr->IsLeaf())
        {
            mapTreeNodesHt[pncurr] = 0.0;
        }
        else
        {
            // get two children
            double htSum = 0.0;
            for(int i=0; i<pncurr->GetChildrenNum(); ++i)
            {
                TreeNode *pc = pncurr->GetChild(i);
                YW_ASSERT_INFO(mapTreeNodesHt.find(pc) != mapTreeNodesHt.end(), "Not found");
                double len = pc->GetLength();
                if( len < 0.0)
                {
//cout << "This node has negative len: " << len << ", num of nodes below: " << pncurr->GetNumNodesUnder(false, false) << endl;
                    len = 0.0;
                }
                htSum += mapTreeNodesHt[pc] + len;
            }
            double htUse = htSum/pncurr->GetChildrenNum();
            mapTreeNodesHt[pncurr] = htUse;
        }
    }
    return mapTreeNodesHt[this->rootNode];
}
    
void PhylogenyTreeBasic :: CollectNodeHtLen(map<TreeNode *, double> &mapNodeLenHt)
{
    mapNodeLenHt.clear();
    PhylogenyTreeIterator itor(*this);
    itor.Init();
    while(itor.IsDone()==false)
    {
        TreeNode *pncurr = itor.GetCurrNode();
        itor.Next();
        
        if( pncurr->IsLeaf())
        {
            mapNodeLenHt[pncurr] = 0.0;
        }
        else
        {
            // get two children
            double htSum = 0.0;
            for(int i=0; i<pncurr->GetChildrenNum(); ++i)
            {
                TreeNode *pc = pncurr->GetChild(i);
                YW_ASSERT_INFO(mapNodeLenHt.find(pc) != mapNodeLenHt.end(), "Not found");
                double len = pc->GetLength();
                if( len < 0.0)
                {
                    //cout << "This node has negative len: " << len << ", num of nodes below: " << pncurr->GetNumNodesUnder(false, false) << endl;
                    len = 0.0;
                }
                htSum += mapNodeLenHt[pc] + len;
            }
            double htUse = htSum/pncurr->GetChildrenNum();
            mapNodeLenHt[pncurr] = htUse;
        }
    }
}
    
void PhylogenyTreeBasic :: CollectNodeDepth(map<TreeNode *, int> &mapNodeDepth)
{
    // collect depth
    mapNodeDepth.clear();
    vector<TreeNode *> listAllNodes;
    PhylogenyTreeIterator itor(*this);
    itor.Init();
    while(itor.IsDone()==false)
    {
        TreeNode *pncurr = itor.GetCurrNode();
        listAllNodes.push_back(pncurr);
        itor.Next();
    }
    // start from the root
    TreeNode *proot = GetRoot();
    mapNodeDepth[proot] = 0;
    for(int i=(int)listAllNodes.size()-2; i>=0; --i)
    {
        TreeNode *pncurr = listAllNodes[i];
        TreeNode *pnpar = pncurr->GetParent();
        map<TreeNode *, int> :: iterator it = mapNodeDepth.find(pnpar);
        YW_ASSERT_INFO(it != mapNodeDepth.end(), "Fail to find113");
        mapNodeDepth[pncurr] = it->second+1;
    }
}
    
void PhylogenyTreeBasic :: CollectNodeHt(map<TreeNode *, int> &mapNodeHt)
{
    mapNodeHt.clear();
    PhylogenyTreeIterator itor(*this);
    itor.Init();
    while(itor.IsDone()==false)
    {
        TreeNode *pncurr = itor.GetCurrNode();
        if( pncurr->IsLeaf() )
        {
            mapNodeHt[pncurr] = 0;
        }
        int htcurr = 0;
        TreeNode *pnpar = pncurr->GetParent();
        if( pnpar != NULL )
        {
            map<TreeNode *, int> :: iterator it = mapNodeHt.find(pncurr);
            YW_ASSERT_INFO(it != mapNodeHt.end(), "Fail to find2");
            htcurr = it->second;
            map<TreeNode *, int> :: iterator itpar = mapNodeHt.find(pnpar);
            if( itpar == mapNodeHt.end() || itpar->second < htcurr+1 )
            {
                mapNodeHt[pnpar] = htcurr+1;
            }
        }
        itor.Next();
    }
}
bool PhylogenyTreeBasic :: IsTopologicalSame(const PhylogenyTreeBasic &treeOther) const
{
    // is current tree topologically the same as the other tree?
    // approach: test if all clades are same
    set<set<int> > setAllCladesThis, setAllCladesRHS;
    PhylogenyTreeBasic *pthis = const_cast<PhylogenyTreeBasic *>(this);
    pthis->GetAllClades(setAllCladesThis);
    PhylogenyTreeBasic &treeOtherUse = const_cast<PhylogenyTreeBasic &>(treeOther);
    treeOtherUse.GetAllClades(setAllCladesRHS);
    return setAllCladesThis == setAllCladesRHS;
}
    
// *************************************
// other functions
    
PhylogenyTreeBasic * ConsPhyTreeSubsetTaxa( PhylogenyTreeBasic *ptreeIn, const set<int> &setTaxaKept)
{
    // construct a phylogeny tree by keeping subset of taxa
    PhylogenyTreeBasic *pCopy = ptreeIn->Copy();
    vector<TreeNode *> listLeafNodes;
    pCopy->GetAllLeafNodes( listLeafNodes );
    
    for(int i=0; i<(int)listLeafNodes.size(); ++i)
    {
        int lbl = listLeafNodes[i]->GetIntLabel();
        if( setTaxaKept.find(lbl) == setTaxaKept.end() )
        {
            // remove this node
            TreeNode *pParOrig = listLeafNodes[i]->GetParent();
            pCopy->RemoveNode( listLeafNodes[i] );
            pCopy->RemoveDegreeOneNodeAt(pParOrig);
        }
    }
    //pCopy->RemoveDegreeOneNodes();
    
    return pCopy;
}
    
// implement needed
string ConsEdgeLabeTreeSeg(const string &strNWWithLabels, int regBeg, int regEnd)
{
//cout << "ConsEdgeLabeTreeSeg: [" << regBeg << "," << regEnd << "]: \n";
    // if there is edge outside any parenthesis, keep it
    int posRightParenths = regEnd;
    while( posRightParenths > 0 && strNWWithLabels[posRightParenths] != ')'   )
    {
        --posRightParenths;
    }
    string strChild;
    if( posRightParenths > 0)
    {
        // search for children, perform search for each segment between separator , (on the same level)
        vector<string> listChildStrs;
        int level=0;
        int regChildStart= regBeg+1;
        for(int p=regBeg+1; p<=posRightParenths-1; ++p)
        {
            if( (strNWWithLabels[p] == ',' || p==posRightParenths-1 ) && level==0 )
            {
                int regChildEnd = p-1;
                if(p==posRightParenths-1)
                {
                    regChildEnd = p;
                }
                string strChildStep = ConsEdgeLabeTreeSeg(strNWWithLabels, regChildStart, regChildEnd);
                if( strChildStep.length()>0)
                {
                    listChildStrs.push_back( strChildStep );
                }
                regChildStart = p+1;
            }
            else if( strNWWithLabels[p] == '(' )
            {
                ++level;
            }
            else if( strNWWithLabels[p] == ')' )
            {
                --level;
            }
        }
        if( listChildStrs.size() > 0 )
        {
            strChild = "(";
            for(int i=0;i<(int)listChildStrs.size(); ++i)
            {
                strChild += listChildStrs[i];
                if( i<(int)listChildStrs.size()-1)
                {
                    strChild += ",";
                }
            }
            strChild += ")";
        }
    }
    
    string strEdgeLbelCur;
    if( regEnd != posRightParenths )
    {
        // search for :
        int pos=regEnd;
        while(pos>=regBeg && strNWWithLabels[pos] != ':' )
        {
            --pos;
        }
        if(pos>=regBeg)
        {
            strEdgeLbelCur = strNWWithLabels.substr( pos+1, regEnd-pos );
        }
    }
    string strRes = strChild + strEdgeLbelCur;
//cout << "strRes: " << strRes << endl;
    return strRes;
}

string ConsEdgeLabeTree(const string &strNWWithLabels)
{
    // construct newick format of edge label tree; that is,
    // delete all taxa, only leave edge label
    // e.g. ((2,4:#4):#3,(3:#5,5):#2,1):#1  ==> ((#4)#3,(#5)#2)#1
    return ConsEdgeLabeTreeSeg(strNWWithLabels, 0, strNWWithLabels.length()-1);
}
    
int ComputeSharedCladesInTwoTrees(PhylogenyTreeBasic &tree1, PhylogenyTreeBasic &tree2, bool fRooted)
{
    int numLvs = tree1.GetNumLeaves();
    // calculate number of shared (rooted or unrooted) clades in two trees
    set<set<int> > cladesInTree1, cladesInTree2;
    tree1.GetAllClades(cladesInTree1);
    tree2.GetAllClades(cladesInTree2);
    //tree1.GetAllCladesInt(cladesInTree1, 0);
    //tree2.GetAllCladesInt(cladesInTree2, 0);
#if 0
    cout << "Current clades: Set of clades to check for tree1: ";
    for(set<set<int> > :: iterator it = cladesInTree1.begin(); it != cladesInTree1.end(); ++it)
    {
        DumpIntSet(*it);
    }
    cout << "Set of clades to check for tree2: ";
    for(set<set<int> > :: iterator it = cladesInTree2.begin(); it != cladesInTree2.end(); ++it)
    {
        DumpIntSet(*it);
    }
#endif
//#if 0
    // remove all trivial clades
    for(set<set<int> > :: iterator it = cladesInTree1.begin(); it != cladesInTree1.end(); )
    {
        if(it->size() == 1 || it->size()==numLvs || (fRooted == false && it->size() == numLvs-1) )
        {
            it = cladesInTree1.erase(it);
        }
        else
        {
            ++it;
        }
    }
    for(set<set<int> > :: iterator it = cladesInTree2.begin(); it != cladesInTree2.end(); )
    {
        if(it->size() == 1 || it->size()==numLvs || (fRooted == false && it->size() == numLvs-1) )
        {
            it = cladesInTree2.erase(it);
        }
        else
        {
            ++it;
        }
    }
//#endif
    
//#if 0
    if( fRooted==false)
    {
        // use one sided (say with 0)
        set<set<int> > cladesInTree1Used;
        for(set<set<int> > :: iterator it = cladesInTree1.begin(); it != cladesInTree1.end(); ++it)
        {
            if( it->find(0) != it->end() )
            {
                cladesInTree1Used.insert(*it);
            }
            else
            {
                set<int> scomp=*it;
                ComplementIntSet(numLvs, scomp);
                cladesInTree1Used.insert(scomp);
            }
        }
        cladesInTree1 = cladesInTree1Used;
        set<set<int> > cladesInTree2Used;
        for(set<set<int> > :: iterator it = cladesInTree2.begin(); it != cladesInTree2.end(); ++it )
        {
            if( it->find(0) != it->end() )
            {
                cladesInTree2Used.insert(*it);
            }
            else
            {
                set<int> scomp=*it;
                ComplementIntSet(numLvs, scomp);
                cladesInTree2Used.insert(scomp);
            }
        }
        cladesInTree2 = cladesInTree2Used;
    }
//#endif
#if 0
cout << "Set of clades to check for tree1: ";
for(set<set<int> > :: iterator it = cladesInTree1.begin(); it != cladesInTree1.end(); ++it)
{
DumpIntSet(*it);
}
cout << "Set of clades to check for tree2: ";
for(set<set<int> > :: iterator it = cladesInTree2.begin(); it != cladesInTree2.end(); ++it)
{
DumpIntSet(*it);
}
#endif
    set<set<int> > sjoin;
    JoinSetsGen(cladesInTree1, cladesInTree2, sjoin);
    return sjoin.size();
}

//*****************************************************************************
// Sankoff's algorithm to compute the minimum changes in states on a tree
//*****************************************************************************

// assume classes are consecutive integers, starting from 0, e.g. 0, 1, 2 etc
TreeParismonyCost :: TreeParismonyCost(PhylogenyTreeBasic &treeIn, int numClassesIn) : treeInput(treeIn), numClasses(numClassesIn)
{
}
void TreeParismonyCost :: SetLeafClass(int leaf, int lbl)
{
    mapLeafClass[leaf] = lbl;
}
// cost of changing from cSrc to cDest; default: 1.0
void TreeParismonyCost :: SetClassCost(int cSrc, int cDest, double cost)
{
    mapCostClassTransit[cSrc][cDest] = cost;
}
double TreeParismonyCost :: CalcMinCost()
{
    // do dp. Also will do back-trace
    mapNodeCoalLabel.clear();
    map<TreeNode *, vector<double> > mapCostAtNode;
    
    // for back-trace, also save where the values are from in DP
    map<TreeNode *, vector< vector<int> > > mapNodeChildClassMin;
    
    PhylogenyTreeIterator itorTree(treeInput);
    itorTree.Init();
    while( itorTree.IsDone() == false )
    {
        TreeNode *pn = itorTree.GetCurrNode();
        vector<double> vec(numClasses);
        
        // init back-trace
        vector<vector<int> > tblChildClass(numClasses);
        for(int i=0;i<numClasses; ++i)
        {
            for(int j=0; j<pn->GetChildrenNum(); ++j)
            {
                tblChildClass[i].push_back(-1);
            }
        }
        
        // view time from top to down
        for(int cSrc = 0; cSrc <numClasses; ++cSrc )
        {
            // check each child
            double cost = 0.0;
            if( pn->IsLeaf() == false )
            {
                for(int child = 0; child<pn->GetChildrenNum(); ++child)
                {
                    TreeNode *pChild = pn->GetChild(child);
                    double costChildMin = -1.0;
                    for(int cDest=0; cDest < numClasses; ++cDest)
                    {
                        map<TreeNode *, vector<double> > :: iterator it3 = mapCostAtNode.find(pChild);
                        YW_ASSERT_INFO(it3 != mapCostAtNode.end(), "Fail to find child");
                        double costStep = it3->second[cDest] + GetClassTransCost(cSrc, cDest);
                        if( costChildMin < 0 || costChildMin > costStep )
                        {
                            costChildMin = costStep;
                            tblChildClass[cSrc][child] = cDest;
                        }
                    }
                    cost += costChildMin;
                }
            }
            else
            {
                // for leaf, it depends on the current label
                int leaf = pn->GetIntLabel();
                int leafClass = GetLeafLabel(leaf);
                cost = GetClassTransCost( cSrc, leafClass);
//cout << "Process leaf: " << leaf << ", class: " << leafClass << ", cost: " << cost << endl;
            }
            vec[cSrc] = cost;
        }
        mapCostAtNode[pn] = vec;
        mapNodeChildClassMin[pn] = tblChildClass;
        itorTree.Next();
    }
    // the answer is at the root
    TreeNode *proot = treeInput.GetRoot();
    double res = -1.0;
    map<TreeNode *, vector<double> > :: iterator it3 = mapCostAtNode.find(proot);
    YW_ASSERT_INFO(it3 != mapCostAtNode.end(), "Fail to find root");
    for(int cSrc = 0; cSrc < numClasses; ++cSrc)
    {
        if( res < 0 || res > it3->second[cSrc] )
        {
            res = it3->second[cSrc];
            mapNodeCoalLabel[proot] = cSrc;
        }
    }
    // now perform back-trace
    stack<TreeNode *> stackNodes;
    stackNodes.push(proot);
    while(stackNodes.empty() == false)
    {
        TreeNode *pn = stackNodes.top();
        int pop = mapNodeCoalLabel[pn];
        stackNodes.pop();
        
        // check for leaf
        if( pn->IsLeaf() )
        {
            int leaf = pn->GetIntLabel();
            int leafClass = GetLeafLabel(leaf);
            mapNodeCoalLabel[pn] = leafClass;
            continue;
        }
        
        // set all its children's label and
        // push children
        for(int c=0; c<pn->GetChildrenNum(); ++c)
        {
            TreeNode *pnc = pn->GetChild(c);
            
            int src = mapNodeChildClassMin[pn][pop][c];
            mapNodeCoalLabel[pnc] = src;
            
            stackNodes.push(pnc);
        }
    }
    
    return res;
}
    
int TreeParismonyCost :: GetNodeCoalClass(TreeNode *pn) const
{
    //
    map<TreeNode *,int> :: const_iterator it = mapNodeCoalLabel.find(pn);
    if( it != mapNodeCoalLabel.end() )
    {
        return it->second;
    }
    return -1;
}
    
double TreeParismonyCost :: GetClassTransCost(int cSrc, int cDest)
{
    double cost = 0.0;
    std::map<int, map<int, double> > :: iterator it1 = mapCostClassTransit.find(cSrc);
    if( it1 != mapCostClassTransit.end() )
    {
        map<int, double> :: iterator it2 = it1->second.find(cDest);
        if( it2 != it1->second.end() )
        {
            cost = it2->second;
        }
    }
    return cost;
}
    
int TreeParismonyCost :: GetLeafLabel(int leaf)
{
    std::map<int, int> :: iterator it = mapLeafClass.find(leaf);
    if( it == mapLeafClass.end() )
    {
        YW_ASSERT_INFO(false, "Fail to find");
    }
    return it->second;
}
    
/*
// test main
int main()
{
    // test TreeParsimonyCost function
    const string strNW = "(((((0,1),2),3),4),((5,6),7));";
    PhylogenyTreeBasic phtree;
    phtree.ConsOnNewick(strNW);
    // setup classes
    const int NUM_CLASSES = 2;
    TreeParismonyCost costCalc(phtree, NUM_CLASSES);
    costCalc.SetLeafClass(0, 1);
    costCalc.SetLeafClass(1, 0);
    costCalc.SetLeafClass(2, 0);
    costCalc.SetLeafClass(3, 0);
    costCalc.SetLeafClass(4, 0);
    costCalc.SetLeafClass(5, 1);
    costCalc.SetLeafClass(6, 1);
    costCalc.SetLeafClass(7, 1);
    // set up cost
    costCalc.SetClassCost(0, 1, 1.0);
    costCalc.SetClassCost(1, 0, 1.0);
    double cost1 = costCalc.CalcMinCost();
    cout << "Min cost: " << cost1 << endl;
    
    // check all internal coal labels
    vector<TreeNode *> listAllNodes;
    phtree.GetAllNodes(listAllNodes);
    for(unsigned int i=0; i<listAllNodes.size(); ++i)
    {
        set<int> setLvs;
        listAllNodes[i]->GetAllLeavesIdUnder(setLvs);
        int coalLbl = costCalc.GetNodeCoalClass(listAllNodes[i]);
        cout << "COAL LBL: " << coalLbl << ", leaves under it: ";
        DumpIntSet(setLvs);
    }
    
return 0;
    // now set up cost for different transition cost
    costCalc.SetClassCost(0, 1, 1.0);
    costCalc.SetClassCost(1,0, 10000000.0);
    double cost2 = costCalc.CalcMinCost();
    cout << "Min cost (only allow 0 to 1 transition): " << cost2 << endl;

    // now set up cost for different transition cost
    costCalc.SetClassCost(1, 0, 1.0);
    costCalc.SetClassCost(0,1, 10000000.0);
    double cost3 = costCalc.CalcMinCost();
    cout << "Min cost (only allow 1 to 0 transition): " << cost3 << endl;
}
*/
