OKlibrary  0.2.1.6
Analyse.cpp
Go to the documentation of this file.
00001 // Oliver Kullmann, 5.5.2005 (Swansea)
00002 /* Copyright 2005 - 2007 Oliver Kullmann
00003 This file is part of the OKlibrary. OKlibrary is free software; you can redistribute
00004 it and/or modify it under the terms of the GNU General Public License as published by
00005 the Free Software Foundation and included in this library; either version 3 of the
00006 License, or any later version. */
00007 
00015 #include <iostream>
00016 #include <vector>
00017 #include <algorithm>
00018 #include <set>
00019 #include <stdexcept>
00020 #include <string>
00021 #include <iterator>
00022 #include <cstdlib>
00023 #include <fstream>
00024 #include <cassert>
00025 
00026 #include <boost/lexical_cast.hpp>
00027 
00028 namespace Analyse {
00029 
00030   typedef unsigned int CountSolved;
00031   typedef unsigned int NumberSolver;
00032   typedef double Time;
00033 
00034   struct FormatError : std::runtime_error {
00035     FormatError(const std::string& m) : std::runtime_error(m) {}
00036   };
00037 
00038   struct mean_time {
00039     void set_NaN() { is_NaN = true; }
00040     void set_time(const Time t) { is_NaN = false; time = t; }
00041     bool is_NaN;
00042     Time time;
00043   };
00044 
00045   std::istream& operator >>(std::istream& in, mean_time& t) {
00046     if (not in)
00047       throw FormatError("operator >>(std::istream& in, mean_time& t): stream unreadable from the beginning");
00048     std::string time;
00049     in >> time;
00050     if (not in)
00051       throw FormatError("operator >>(std::istream& in, mean_time& t): can't read time");
00052     if (time == "NaN")
00053       t.set_NaN();
00054     else {
00055       try {
00056         t.set_time(boost::lexical_cast<Time>(time));
00057       }
00058       catch(const boost::bad_lexical_cast& e) {
00059         throw FormatError(std::string("operator >>(std::istream& in, mean_time& t): can't convert time; message from boost::bad_lexical_cast is\n") + e.what());
00060       }
00061     }
00062     return in;
00063   }
00064 
00065   std::ostream& operator <<(std::ostream& out, const mean_time& t) {
00066     if (t.is_NaN)
00067       return out << "NaN";
00068     else
00069       return out << t.time;
00070   }
00071 
00072   bool operator <(const mean_time& a, const mean_time& b) {
00073     if (b.is_NaN)
00074       return false;
00075     else
00076       if (a.is_NaN)
00077         return true;
00078       else
00079         return b.time < a.time;
00080   }
00081 
00082   struct SolverResult {
00083     NumberSolver num_solver;
00084     typedef std::vector<CountSolved> vector_numbers;
00085     typedef std::vector<mean_time> vector_times;
00086     unsigned int ncolumns;
00087     vector_numbers solved;
00088     vector_times times;
00089   };
00090 
00091   bool operator <(const SolverResult& a, const SolverResult& b) {
00092     const bool a_l_b = std::lexicographical_compare(a.solved.rbegin(), a.solved.rend(), b.solved.rbegin(), b.solved.rend());
00093     if (a_l_b) return true;
00094     const bool b_l_a = std::lexicographical_compare(b.solved.rbegin(), b.solved.rend(), a.solved.rbegin(), a.solved.rend());
00095     if (b_l_a) return false;
00096     return std::lexicographical_compare(a.times.rbegin(), a.times.rend(), b.times.rbegin(), b.times.rend());
00097   }
00098 
00099   std::ostream& operator <<(std::ostream& out, const SolverResult& r) {
00100     if (not out)
00101       throw FormatError("operator >>(std::ostream& in, SolverResult& R): stream unwritable from the beginning");
00102     out << r.num_solver << "\n";
00103     std::copy(r.solved.begin(), r.solved.end(), std::ostream_iterator<CountSolved>(out, " "));
00104     out << "\n";
00105     std::copy(r.times.begin(), r.times.end(), std::ostream_iterator<mean_time>(out, " "));
00106     out << "\n";
00107     return out;
00108   }
00109 
00110   typedef std::set<SolverResult> SolverResults;
00111 
00112   std::istream& operator >> (std::istream& in, SolverResults& R) {
00113     if (not in)
00114       throw FormatError("operator >>(std::istream& in, SolverResults& R): stream unreadable from the beginning");
00115     unsigned int number_results;
00116     unsigned int number_columns;
00117     in >> number_results >> number_columns;
00118     if  (not in)
00119       throw FormatError("operator >>(std::istream& in, SolverResults& R): can't read number_results, number_columns");
00120 
00121     for (unsigned int i = 0; i < number_results; ++i) {
00122       SolverResult r;
00123       in >> r.num_solver;
00124       if  (not in)
00125           throw FormatError(std::string("operator >>(std::istream& in, SolverResults& R): can't read solver number for result number ") + boost::lexical_cast<std::string>(i + 1));
00126       r.solved.reserve(number_columns);
00127       for (unsigned int j = 0; j < number_columns; ++j) {
00128         CountSolved c;
00129         in >> c;
00130         if  (not in)
00131           throw FormatError(std::string("operator >>(std::istream& in, SolverResults& R): can't read number of instances solved for result number ") + boost::lexical_cast<std::string>(i + 1) + " and column number " + boost::lexical_cast<std::string>(j + 1));
00132         r.solved.push_back(c);
00133       }
00134       r.times.reserve(number_columns);
00135       for (unsigned int j = 0; j < number_columns; ++j) {
00136         mean_time t;
00137         in >> t;
00138         if  (not in)
00139           throw FormatError(std::string("operator >>(std::istream& in, SolverResults& R): can't read mean time for result number ") + boost::lexical_cast<std::string>(i + 1) + " and column number " + boost::lexical_cast<std::string>(j + 1));
00140         r.times.push_back(t);
00141       }
00142       R.insert(r);
00143       assert(R.size() == i+1);
00144     }
00145     return in;
00146   }
00147 
00148   std::ostream& operator <<(std::ostream& out, const SolverResults& R) {
00149     std::copy(R.rbegin(), R.rend(), std::ostream_iterator<SolverResult>(out, "\n"));
00150     return out;
00151   }
00152 
00153 }
00154 
00155 int main(const int argc, const char* const argv[]) {
00156   if (argc != 2) {
00157     std::cerr << "ERROR[Analyse]: Exactly one argument expected, the name of the file with the data.\n";
00158     return EXIT_FAILURE;
00159   }
00160   std::ifstream file(argv[1]);
00161   Analyse::SolverResults R;
00162   file >> R;
00163   std::cout << R;
00164 }