Share Pastebin
Guest
Public paste!

timvdm

By: a guest | Sep 29th, 2009 | Syntax: None | Size: 5.31 KB | Hits: 206 | Expires: Never
Copy text to clipboard
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <cassert>
  5.  
  6. #include <Eigen/Core>
  7.  
  8. #include <openbabel/mol.h>
  9. #include <openbabel/obconversion.h>
  10. #include <openbabel/graphsym.h>
  11.  
  12. #include <graph.hh>
  13.  
  14. #include "permutation.h"
  15. using namespace OpenBabel;
  16.  
  17. ////////////////////////////////////////////////////////////////////////////////
  18. //
  19. //
  20. //  O P E N B A B E L   S P E C I F I C   C O D E
  21. //
  22. //
  23. ////////////////////////////////////////////////////////////////////////////////
  24.  
  25. OpenBabel::OBMol* ReadMolecule(const std::string &filename)
  26. {
  27.   OpenBabel::OBConversion conv;
  28.   OpenBabel::OBFormat *format = conv.FormatFromExt(filename.c_str());
  29.   if (!format || !conv.SetInFormat(format)) {
  30.     std::cout << "ERROR: Could not detect file format for: " << filename << std::endl;
  31.     return 0;
  32.   }
  33.  
  34.   std::ifstream ifs;
  35.   ifs.open(filename.c_str());
  36.   if (!ifs) {
  37.     std::cout << "ERROR: Could not open file: " << filename << std::endl;
  38.     return 0;  
  39.   }
  40.  
  41.   OpenBabel::OBMol *obmol = new OpenBabel::OBMol;
  42.   if (!conv.Read(obmol, &ifs)) {
  43.     std::cout << "ERROR: Could not read molecule from file: " << filename << std::endl;
  44.     delete obmol;
  45.     ifs.close();
  46.     return 0;
  47.   }
  48.  
  49.   ifs.close();
  50.   return obmol;
  51. }
  52.  
  53. ////////////////////////////////////////////////////////////////////////////////
  54. //
  55. //
  56. //  U N I T   T E S T S
  57. //
  58. //
  59. ////////////////////////////////////////////////////////////////////////////////
  60.  
  61.  
  62.  
  63. void testPermutation()
  64. {
  65.   std::vector<unsigned int> e;
  66.   e.push_back(1);
  67.   e.push_back(2);
  68.   e.push_back(3);
  69.   e.push_back(4);
  70.   Permutation p1(e), p2(e);
  71.  
  72.   assert(p1 == p2);
  73. }
  74.  
  75. void testPermutationGroup()
  76. {
  77.   Permutation p;
  78.   p.map.push_back(1);
  79.   p.map.push_back(2);
  80.   p.map.push_back(3);
  81.   p.map.push_back(4);
  82.  
  83.   PermutationGroup group;
  84.   assert( !group.contains(p) );
  85.  
  86.   group.add(p);
  87.   assert( group.contains(p) );
  88. }
  89.  
  90. void unitTests()
  91. {
  92.   testPermutation();
  93.   testPermutationGroup();
  94.  
  95. }
  96.  
  97.  
  98.  
  99.  
  100. void callback(void *param, unsigned int n, const unsigned int *aut)
  101. {
  102.   assert(param);
  103.   /*
  104.   fprintf((FILE*)param, "Generator: ");
  105.   bliss::print_permutation((FILE*)param, n, aut, 0);
  106.   fprintf((FILE*)param, "\n");
  107.   */
  108.  
  109.   std::vector<unsigned int> elements;
  110.   cout << "Generator: ";
  111.   for (unsigned int i = 0; i < n; ++i) {
  112.     cout << aut[i] + 1 << " ";
  113.     elements.push_back(aut[i]+1);
  114.   }
  115.   cout << endl;
  116.  
  117.   PermutationGroup *generators = static_cast<PermutationGroup*>(param);
  118.   generators->add(Permutation(elements));
  119. }
  120.  
  121. void addInverses(PermutationGroup &G)
  122. {
  123.   unsigned int size = G.permutations.size();
  124.   for (unsigned int i = 0; i < size; ++i) {
  125.     Permutation inv_p(G.permutations.at(i).matrix().transpose());
  126.     if (!G.contains(inv_p))
  127.       G.add(inv_p);
  128.   }
  129. }
  130.  
  131. void addProducts(PermutationGroup &G)
  132. {
  133.   for (unsigned int i = 0; i < G.permutations.size(); ++i) {
  134.     for (unsigned int j = 0; j < G.permutations.size(); ++j) {
  135.       if (i >= j)
  136.         continue;
  137.  
  138.       Permutation p = G.permutations.at(i) * G.permutations.at(j);
  139.       if (!G.contains(p))
  140.         G.add(p);
  141.     }
  142.   }
  143. }
  144.  
  145. PermutationGroup findAutomorphisms(OpenBabel::OBMol *obmol, const std::vector<unsigned int> &symClasses)
  146. {
  147.   using OpenBabel::OBMolAtomIter;
  148.   using OpenBabel::OBMolBondIter;
  149.  
  150.   // construct the bliss graph
  151.   bliss::Graph g;
  152.   std::map<OpenBabel::OBAtom*, unsigned int> atom2index;
  153.   FOR_ATOMS_OF_MOL (atom, obmol) {
  154.     atom2index[&*atom] = g.add_vertex(symClasses.at(atom->GetIndex()));
  155.   }
  156.   FOR_BONDS_OF_MOL (bond, obmol) {
  157.     g.add_edge(atom2index[bond->GetBeginAtom()], atom2index[bond->GetEndAtom()]);
  158.   }
  159.  
  160.   // use bliss to get the automorphism group generators
  161.   PermutationGroup generators;
  162.   bliss::Stats stats;
  163.   g.find_automorphisms(stats, &callback, &generators);
  164.  
  165.   cout << "# Automorphisms:" << stats.group_size_approx << endl;
  166.   unsigned long nAut = stats.group_size_approx;
  167.  
  168.   // construct the automorphism group
  169.   PermutationGroup G;
  170.  
  171.   // add identity permutation
  172.   std::vector<unsigned int> eElements;
  173.   for (unsigned int i = 0; i < obmol->NumAtoms(); ++i)
  174.     eElements.push_back(i+1);
  175.   Permutation e(eElements);
  176.   if (!G.contains(e))
  177.     G.add(e);
  178.  
  179.   // add the generators
  180.   for (unsigned int i = 0; i < generators.size(); ++i) {
  181.     if (!G.contains(generators.at(i)))
  182.       G.add(generators.at(i));
  183.   }
  184.  
  185.  
  186.   unsigned int counter = 0;
  187.   unsigned int lastSize = 0;
  188.   while (G.permutations.size() != lastSize) {
  189.     lastSize = G.permutations.size();
  190.    
  191.     addInverses(G);
  192.     addProducts(G);
  193.    
  194.     counter++;
  195.     if (counter > 100)
  196.       break;
  197.   }
  198.  
  199.   return G;
  200. }
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207. int main(int argc, char **argv)
  208. {
  209.   unitTests();
  210.  
  211.   if (argc < 2) {
  212.     std::cout << "Usage: " << argv[0] << " <filename>" << std::endl;
  213.     return -1;
  214.   }
  215.  
  216.   OpenBabel::OBMol *obmol = ReadMolecule(argv[1]);
  217.   if (!obmol)
  218.     return -1;
  219.  
  220.   std::vector<unsigned int> elements;
  221.   for (int i = 0; i < obmol->NumAtoms(); ++i) {
  222.     elements.push_back(i+1);
  223.   }
  224.  
  225.   OpenBabel::OBGraphSym graphSym(obmol);
  226.   std::vector<unsigned int> symClasses;
  227.   graphSym.GetSymmetry(symClasses);
  228.  
  229.  
  230.   PermutationGroup G = findAutomorphisms(obmol, symClasses);
  231.  
  232.   std::cout << "Automorphisms:" << std::endl;
  233.   for (unsigned int i = 0; i < G.size(); ++i)
  234.     G.at(i).print();
  235.  
  236.  
  237.   return 0;
  238. }