| deba@360 |      1 | /* -*- mode: C++; indent-tabs-mode: nil; -*-
 | 
| deba@360 |      2 |  *
 | 
| deba@360 |      3 |  * This file is a part of LEMON, a generic C++ optimization library.
 | 
| deba@360 |      4 |  *
 | 
| alpar@463 |      5 |  * Copyright (C) 2003-2009
 | 
| deba@360 |      6 |  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
 | 
| deba@360 |      7 |  * (Egervary Research Group on Combinatorial Optimization, EGRES).
 | 
| deba@360 |      8 |  *
 | 
| deba@360 |      9 |  * Permission to use, modify and distribute this software is granted
 | 
| deba@360 |     10 |  * provided that this copyright notice appears in all copies. For
 | 
| deba@360 |     11 |  * precise terms see the accompanying LICENSE file.
 | 
| deba@360 |     12 |  *
 | 
| deba@360 |     13 |  * This software is provided "AS IS" with no warranty of any kind,
 | 
| deba@360 |     14 |  * express or implied, and with no claim as to its suitability for any
 | 
| deba@360 |     15 |  * purpose.
 | 
| deba@360 |     16 |  *
 | 
| deba@360 |     17 |  */
 | 
| deba@360 |     18 | 
 | 
| deba@360 |     19 | #ifndef LEMON_NAUTY_READER_H
 | 
| deba@360 |     20 | #define LEMON_NAUTY_READER_H
 | 
| deba@360 |     21 | 
 | 
| deba@360 |     22 | #include <vector>
 | 
| deba@360 |     23 | #include <iostream>
 | 
| deba@360 |     24 | #include <string>
 | 
| deba@360 |     25 | 
 | 
| deba@360 |     26 | /// \ingroup nauty_group
 | 
| deba@360 |     27 | /// \file
 | 
| deba@360 |     28 | /// \brief Nauty file reader.
 | 
| kpeter@363 |     29 | 
 | 
| deba@360 |     30 | namespace lemon {
 | 
| deba@360 |     31 | 
 | 
| deba@360 |     32 |   /// \ingroup nauty_group
 | 
| deba@360 |     33 |   ///
 | 
| deba@360 |     34 |   /// \brief Nauty file reader
 | 
| deba@360 |     35 |   ///
 | 
| deba@360 |     36 |   /// The \e geng program is in the \e gtools suite of the nauty
 | 
| deba@360 |     37 |   /// package. This tool can generate all non-isomorphic undirected
 | 
| kpeter@364 |     38 |   /// graphs of several classes with given node number (e.g.
 | 
| deba@360 |     39 |   /// general, connected, biconnected, triangle-free, 4-cycle-free,
 | 
| deba@360 |     40 |   /// bipartite and graphs with given edge number and degree
 | 
| kpeter@370 |     41 |   /// constraints). This function reads a \e nauty \e graph6 \e format
 | 
| deba@360 |     42 |   /// line from the given stream and builds it in the given graph.
 | 
| deba@360 |     43 |   ///
 | 
| deba@360 |     44 |   /// The site of nauty package: http://cs.anu.edu.au/~bdm/nauty/
 | 
| deba@360 |     45 |   ///
 | 
| kpeter@364 |     46 |   /// For example, the number of all non-isomorphic planar graphs
 | 
| kpeter@364 |     47 |   /// can be computed with the following code.
 | 
| deba@360 |     48 |   ///\code
 | 
| deba@360 |     49 |   /// int num = 0;
 | 
| deba@360 |     50 |   /// SmartGraph graph;
 | 
| kpeter@371 |     51 |   /// while (readNautyGraph(graph, std::cin)) {
 | 
| deba@362 |     52 |   ///   PlanarityChecking<SmartGraph> pc(graph);
 | 
| deba@360 |     53 |   ///   if (pc.run()) ++num;
 | 
| deba@360 |     54 |   /// }
 | 
| deba@360 |     55 |   /// std::cout << "Number of planar graphs: " << num << std::endl;
 | 
| deba@360 |     56 |   ///\endcode
 | 
| deba@360 |     57 |   ///
 | 
| deba@360 |     58 |   /// The nauty files are quite huge, therefore instead of the direct
 | 
| kpeter@364 |     59 |   /// file generation pipelining is recommended. For example,
 | 
| deba@360 |     60 |   ///\code
 | 
| kpeter@364 |     61 |   /// ./geng -c 10 | ./num_of_planar_graphs
 | 
| deba@360 |     62 |   ///\endcode
 | 
| deba@360 |     63 |   template <typename Graph>
 | 
| kpeter@371 |     64 |   std::istream& readNautyGraph(Graph& graph, std::istream& is = std::cin) {
 | 
| deba@360 |     65 |     graph.clear();
 | 
| deba@360 |     66 | 
 | 
| deba@360 |     67 |     std::string line;
 | 
| deba@360 |     68 |     if (getline(is, line)) {
 | 
| deba@360 |     69 |       int index = 0;
 | 
| deba@360 |     70 | 
 | 
| deba@360 |     71 |       int n;
 | 
| deba@360 |     72 | 
 | 
| deba@360 |     73 |       if (line[index] == '>') {
 | 
| deba@360 |     74 |         index += 10;
 | 
| deba@360 |     75 |       }
 | 
| deba@360 |     76 | 
 | 
| deba@360 |     77 |       char c = line[index++]; c -= 63;
 | 
| deba@360 |     78 |       if (c != 63) {
 | 
| deba@360 |     79 |         n = int(c);
 | 
| deba@360 |     80 |       } else {
 | 
| deba@360 |     81 |         c = line[index++]; c -= 63;
 | 
| deba@360 |     82 |         n = (int(c) << 12);
 | 
| deba@360 |     83 |         c = line[index++]; c -= 63;
 | 
| deba@360 |     84 |         n |= (int(c) << 6);
 | 
| deba@360 |     85 |         c = line[index++]; c -= 63;
 | 
| deba@360 |     86 |         n |= int(c);
 | 
| deba@360 |     87 |       }
 | 
| deba@360 |     88 | 
 | 
| deba@360 |     89 |       std::vector<typename Graph::Node> nodes;
 | 
| deba@360 |     90 |       for (int i = 0; i < n; ++i) {
 | 
| deba@360 |     91 |         nodes.push_back(graph.addNode());
 | 
| deba@360 |     92 |       }
 | 
| deba@360 |     93 | 
 | 
| deba@360 |     94 |       int bit = -1;
 | 
| deba@360 |     95 |       for (int j = 0; j < n; ++j) {
 | 
| deba@360 |     96 |         for (int i = 0; i < j; ++i) {
 | 
| deba@360 |     97 |           if (bit == -1) {
 | 
| deba@360 |     98 |             c = line[index++]; c -= 63;
 | 
| deba@360 |     99 |             bit = 5;
 | 
| deba@360 |    100 |           }
 | 
| deba@360 |    101 |           bool b = (c & (1 << (bit--))) != 0;
 | 
| deba@360 |    102 | 
 | 
| deba@360 |    103 |           if (b) {
 | 
| deba@360 |    104 |             graph.addEdge(nodes[i], nodes[j]);
 | 
| deba@360 |    105 |           }
 | 
| deba@360 |    106 |         }
 | 
| deba@360 |    107 |       }
 | 
| deba@360 |    108 |     }
 | 
| deba@360 |    109 |     return is;
 | 
| deba@360 |    110 |   }
 | 
| deba@360 |    111 | }
 | 
| deba@360 |    112 | 
 | 
| deba@360 |    113 | #endif
 |