(C++) CalcNumOfSymmetries

February 24, 2017 · View on GitHub

 

 

 

 

 

(C++) CalcNumOfSymmetries

 

CalcNumOfSymmetries is a Newick code snippets to calculate the number of symmetries a Newick has.

 


///CalcNumOfSymmetries calculates the number of symmetries in a Newick. ///From http://www.richelbilderbeek.nl/CppCalcNumOfCombinations.htm int CalcNumOfSymmetries(std::vector<int> v) {   assert(IsNewick(v));   if (v.size() == 4) return (v[1] > 0 && v[1]==v[2] ? 1 : 0);   const int n_reserved     = *std::max_element(v.begin(),v.end())     + std::count_if(v.begin(), v.end(),         std::bind2nd(std::greater<int>(),0));   int n_symmetries = 0;   int id = n_reserved + 1;   std::map<std::pair<int,int>,int> ids;   while (1)   {     //Count number of symmetries     assert(!v.empty());     const std::size_t sz = v.size();     assert(sz >= 2);     const std::size_t j = sz - 1;     for (std::size_t i = 0; i!=j; ++i)     {       if (v[i] > 0 && v[i]==v[i+1]) ++n_symmetries;     }     //Collect all leaves and store new leaves     std::vector<std::pair<int,int> > leaves;     for (std::size_t i = 0; i!=j; ++i)     {       if (v[i] > 0 && v[i+1] > 0)       {         //Keep pair sorted         const std::pair<int,int> p           = (v[i] <= v[i+1]           ? std::make_pair(v[i+0],v[i+1])           : std::make_pair(v[i+1],v[i+0]));         //If this leaf is new, store it         if (ids.find(p)==ids.end())         {           ids[p] = id;           ++id;         }       }     }     //Generalize all leaves     for (std::size_t i = 0; i < v.size()-1; ++i)     {       assert(v.size()>2);       if (v[i] > 0 && v[i+1] > 0)       {         //Keep pair sorted         const std::pair<int,int> p           = (v[i] <= v[i+1]           ? std::make_pair(v[i+0],v[i+1])           : std::make_pair(v[i+1],v[i+0]));         //If this leaf is new, store it         assert(ids.find(p)!=ids.end()           && "Leaf should have been stored already");         assert(i > 0);         std::vector<int> v_new;         std::copy(v.begin(),v.begin() + i - 1,std::back_inserter(v_new));         const int id = ids[p];         v_new.push_back(id);         std::copy(v.begin() + i + 3,v.end(),std::back_inserter(v_new));         v = v_new;         i = (i-1 > 0 ? i-1 : 0);         //Check if there are more leaves to be generalized         if (v.size()<=4)         {           //Check if the last (X,Y) is symmetrical...           return n_symmetries + (v[1] > 0 && v[1]==v[2] ? 1 : 0);           break;         }       }     }   } }