OKlibrary  0.2.1.6
ResultProcessing_Tests.hpp
Go to the documentation of this file.
00001 // Oliver Kullmann, 18.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 
00008 #ifndef RESULTPROCESSINGTESTS_905Tgb
00009 #define RESULTPROCESSINGTESTS_905Tgb
00010 
00011 #include <vector>
00012 #include <sstream>
00013 #include <algorithm>
00014 #include <cassert>
00015 #include <string>
00016 #include <set>
00017 #include <iterator>
00018 #include <utility>
00019 
00020 #include <boost/lexical_cast.hpp>
00021 #include <boost/iterator/transform_iterator.hpp>
00022 
00023 #include <OKlib/General/FunctionHandling.hpp>
00024 #include <OKlib/Structures/Sets/SetAlgorithms/BasicMapOperations.hpp>
00025 
00026 #include <OKlib/TestSystem/TestBaseClass.hpp>
00027 #include <OKlib/TestSystem/TestExceptions.hpp>
00028 
00029 #include <OKlib/Experimentation/Competition/SingleResult.hpp>
00030 #include <OKlib/Experimentation/Competition/ParsingSingleResult_Tests.hpp>
00031 #include <OKlib/Experimentation/Competition/ParsingResultSequences.hpp>
00032 #include <OKlib/Experimentation/Competition/ParsingResultSequences_Tests.hpp>
00033 
00034 namespace OKlib {
00035   namespace SATCompetition {
00036 
00037     template <class Map, typename Size>
00038     class Check_sizes : public ::OKlib::TestSystem::Test {
00039       const Map& m;
00040       const Size s;
00041     public :
00042       typedef Check_sizes test_type;
00043       Check_sizes(const Map& m, const Size s) : m(m), s(s) {}
00044       Check_sizes(const Check_sizes& cs) : m(cs.m), s(cs.s) {}
00045     private :
00046       void perform_test_trivial() {
00047         Size total = 0;
00048         for (typename Map::const_iterator i = m.begin(); i != m.end(); ++i)
00049           total += i -> second -> size();
00050         if (total != s)
00051           OKLIB_THROW("Total count is " + boost::lexical_cast<std::string>(total) + ", and not " + boost::lexical_cast<std::string>(s));
00052       }
00053     };
00054 
00055     template <class Map, typename Size>
00056     inline Check_sizes<Map, Size> check_sizes(const Map& m, const Size s) {
00057       return Check_sizes<Map, Size>(m, s);
00058     }
00059 
00060     // -------------------------------------------------------------------------------------------------------------------------------
00061 
00062     template <class Map, class Set>
00063     class Check_set : public ::OKlib::TestSystem::Test {
00064       // ToDo: Make a general test tool out of it (with concepts etc.)
00065       const Map& m;
00066       const Set& s;
00067     public :
00068       typedef Check_set test_type;
00069       Check_set(const Map& m, const Set& s) : m(m), s(s) {}
00070       Check_set(const Check_set& cs) : m(cs.m), s(cs.s) {}
00071     private :
00072       void perform_test_trivial() {
00073         typedef typename Map::value_type Pair;
00074         typedef typename Map::const_iterator map_iterator;
00075         typedef FunctionHandling::First<Pair> First;
00076         typedef boost::transform_iterator<First, map_iterator> iterator;
00077         typedef typename Map::value_type::first_type value_type_map;
00078         typedef typename Set::value_type value_type_set;
00079         
00080         if (m.size() != s.size())
00081           OKLIB_THROW("Size is " + boost::lexical_cast<std::string>(m.size()) + ", and not " + boost::lexical_cast<std::string>(s.size()));
00082         if (not std::equal(s.begin(), s.end(), iterator(m.begin(), First()))) {
00083           std::stringstream message;
00084           message << "Domain of map is ";
00085           std::copy(iterator(m.begin(), First()), iterator(m.end(), First()), std::ostream_iterator<value_type_map>(message, ","));
00086           message << ", and not ";
00087           std::copy(s.begin(), s.end(), std::ostream_iterator<value_type_set>(message, ","));
00088           OKLIB_THROW(message.str());
00089         }
00090       }
00091     };
00092 
00093     template <class Map, class Set>
00094     inline Check_set<Map, Set> check_set(const Map& m, const Set& s) {
00095       return Check_set<Map, Set>(m, s);
00096     }
00097 
00098     // -------------------------------------------------------------------------------------------------------------------------------
00099 
00100     template <class ResultDatabase, class ResultContainer>
00101     class Test_Database_vs_Container : public ::OKlib::TestSystem::Test {
00102       ResultDatabase& rdb;
00103       ResultContainer& rc;
00104     public :
00105       typedef Test_Database_vs_Container test_type;
00106       Test_Database_vs_Container(ResultDatabase& rdb, ResultContainer& rc) : rdb(rdb), rc(rc) {}
00107       typedef typename ResultContainer::value_type result_type;
00108     private :
00109       typedef typename ResultContainer::const_iterator const_iterator;
00110       typedef typename ResultContainer::size_type size_type;
00111 
00112       void perform_test_trivial() {
00113 
00114         const size_type rc_size = rc.size();
00115         if (rdb.number_results() != rc_size)
00116           OKLIB_THROW("Element count is " + boost::lexical_cast<std::string>(rdb.number_results()) + ", and not " + boost::lexical_cast<std::string>(rc_size));
00117 
00118         std::set<SuperSeries> ref_set_super_series;
00119         std::set<Series> ref_set_series;
00120         std::set<Benchmark> ref_set_benchmark;
00121         std::set<Solver> ref_set_solver;
00122         std::set<SATStatus> ref_set_sat_status;
00123         std::set<TimeOut> ref_set_time_out;
00124 
00125         for (const_iterator i = rc.begin(); i != rc.end(); ++i) {
00126             ref_set_super_series.insert(i -> super_series());
00127             ref_set_series.insert(i -> series());
00128             ref_set_benchmark.insert(i -> benchmark());
00129             ref_set_solver.insert(i -> solver());
00130             ref_set_sat_status.insert(i -> sat_status());
00131             ref_set_time_out.insert(i -> time_out());
00132           }
00133 
00134         const MapSuperSeries& super_series(rdb.super_series());
00135         const MapSeries& series(rdb.series());
00136         const MapBenchmark& benchmark(rdb.benchmark());
00137         const MapSolver& solver(rdb.solver());
00138         const MapSATStatus& sat_status(rdb.sat_status());
00139         const MapTimeOut& time_out(rdb.time_out());
00140 
00141         OKLIB_TESTTRIVIAL_RETHROW((check_set(super_series, ref_set_super_series)));
00142         OKLIB_TESTTRIVIAL_RETHROW((check_set(series, ref_set_series)));
00143         OKLIB_TESTTRIVIAL_RETHROW((check_set(benchmark, ref_set_benchmark)));
00144         OKLIB_TESTTRIVIAL_RETHROW((check_set(solver, ref_set_solver)));
00145         OKLIB_TESTTRIVIAL_RETHROW((check_set(sat_status, ref_set_sat_status)));
00146         OKLIB_TESTTRIVIAL_RETHROW((check_set(time_out, ref_set_time_out)));
00147 
00148         OKLIB_TESTTRIVIAL_RETHROW((check_sizes(super_series, rc_size)));
00149         OKLIB_TESTTRIVIAL_RETHROW((check_sizes(series, rc_size)));
00150         OKLIB_TESTTRIVIAL_RETHROW((check_sizes(benchmark, rc_size)));
00151         OKLIB_TESTTRIVIAL_RETHROW((check_sizes(solver, rc_size)));
00152         OKLIB_TESTTRIVIAL_RETHROW((check_sizes(sat_status, rc_size)));
00153         OKLIB_TESTTRIVIAL_RETHROW((check_sizes(time_out, rc_size)));
00154 
00155         typedef VectorResultNodesP intersection_type;
00156         const ResultNode* result_p = 0;
00157         {
00158           const intersection_type& res(rdb.intersection());
00159           if (res.size() != rc_size)
00160             OKLIB_THROW("Result size is " + boost::lexical_cast<std::string>(res.size()) + ", and not " + boost::lexical_cast<std::string>(rc_size));
00161           if (not res.empty())
00162             result_p = *res.begin();
00163         }
00164         if (rc_size == 0) return;
00165         assert(result_p);
00166 
00167         const SuperSeries first_super_series = result_p -> rb -> super_series();
00168         const Series first_series = result_p -> rb -> series();
00169         const Benchmark first_benchmark = result_p -> rb -> benchmark();
00170 
00171         typedef typename ResultDatabase::VectorOfSetsP Sets;
00172         Sets& query(rdb.vector_of_sets);
00173         if (not query.empty())
00174           OKLIB_THROW("Query vector is not empty, but has size " + boost::lexical_cast<std::string>(query.size()));
00175 
00176         const SetResultNodesP* const res_super_series(OKlib::SetAlgorithms::map_value(rdb.super_series(), first_super_series));
00177         const SetResultNodesP::iterator res_super_series_end = res_super_series -> end();
00178         if (res_super_series -> find(result_p) == res_super_series_end)
00179           OKLIB_THROW("Resulting set of super series' does not contain " + boost::lexical_cast<std::string>(*result_p));
00180         query.push_back(res_super_series);
00181         if (query.size() != 1)
00182           OKLIB_THROW("Query vector has size " + boost::lexical_cast<std::string>(query.size()));
00183 
00184         const SetResultNodesP* const res_series(OKlib::SetAlgorithms::map_value(rdb.series(), first_series));
00185         const SetResultNodesP::iterator res_series_end = res_series -> end();
00186         if (res_series -> find(result_p) == res_series_end)
00187           OKLIB_THROW("Resulting set of series' does not contain " + boost::lexical_cast<std::string>(*result_p));
00188         query.push_back(res_series);
00189         if (query.size() != 2)
00190           OKLIB_THROW("Query vector has size " + boost::lexical_cast<std::string>(query.size()));
00191 
00192         const SetResultNodesP* const res_benchmark(OKlib::SetAlgorithms::map_value(rdb.benchmark(), first_benchmark));
00193         const SetResultNodesP::iterator res_benchmark_end = res_benchmark -> end();
00194         if (res_benchmark -> find(result_p) == res_benchmark_end)
00195           OKLIB_THROW("Resulting set of benchmarks does not contain " + boost::lexical_cast<std::string>(*result_p));
00196         query.push_back(res_benchmark);
00197         if (not query.size() == 3)
00198           OKLIB_THROW("Query vector has size " + boost::lexical_cast<std::string>(query.size()));
00199 
00200         if (query[0] != res_super_series)
00201           OKLIB_THROW("Query vector[0] has changed");
00202         if (query[1] != res_series)
00203           OKLIB_THROW("Query vector[1] has changed");
00204         if (query[2] != res_benchmark)
00205           OKLIB_THROW("Query vector[2] has changed");
00206         const intersection_type& res(rdb.intersection());
00207         if (not std::binary_search(res.begin(), res.end(), result_p)) {
00208           std::stringstream message;
00209           message <<"Result does not contain element\n" << *result_p << "\nResult contains " << res.size() << " elements";
00210           OKLIB_THROW(message.str());
00211         }
00212         {
00213           intersection_type ref1;
00214           ref1.reserve(std::min(res_super_series -> size(), res_series -> size()));
00215           typedef typename intersection_type::iterator iterator;
00216           std::set_intersection(res_super_series -> begin(), res_super_series_end, res_series -> begin(), res_series_end, std::back_inserter(ref1));
00217           intersection_type ref2;
00218           ref2.reserve(std::min(ref1.size(), res_benchmark -> size()));
00219           std::set_intersection(ref1.begin(), ref1.end(), res_benchmark -> begin(), res_benchmark_end, std::back_inserter(ref2));
00220           OKLIB_TEST_EQUAL(res, ref2);
00221         }
00222         {
00223           typedef VectorResultNodesP::const_iterator const_iterator;
00224           const const_iterator end = res.end();
00225           for (const_iterator i = res.begin(); i != end; ++i) {
00226             const ResultNode& node(**i);
00227 
00228             OKLIB_TEST_EQUAL(node.rb -> super_series(), first_super_series);
00229             OKLIB_TEST_EQUAL(node.rb -> series(), first_series);
00230             OKLIB_TEST_EQUAL(node.rb -> benchmark(), first_benchmark);
00231 
00232             const MapSuperSeries::value_type node_sup_ser_it(*node.m_sup_ser_it);
00233             OKLIB_TEST_EQUAL(node_sup_ser_it.first, first_super_series);
00234             OKLIB_TEST_EQUAL(node_sup_ser_it.second, res_super_series);
00235             const MapSeries::value_type node_ser_it(*node.m_ser_it);
00236             OKLIB_TEST_EQUAL(node_ser_it.first, first_series);
00237             OKLIB_TEST_EQUAL(node_ser_it.second, res_series);
00238             const MapBenchmark::value_type node_bench_it(*node.m_bench_it);
00239             OKLIB_TEST_EQUAL(node_bench_it.first, first_benchmark);
00240             OKLIB_TEST_EQUAL(node_bench_it.second, res_benchmark);
00241           }
00242         }
00243       }
00244     };
00245 
00246     template <class ResultDatabase, class ResultContainer>
00247     inline Test_Database_vs_Container<ResultDatabase, ResultContainer> test_Database_vs_Container(ResultDatabase& rdb, ResultContainer& rc) {
00248       return Test_Database_vs_Container<ResultDatabase, ResultContainer>(rdb, rc);
00249     }
00250 
00251     // -------------------------------------------------------------------------------------------------------------------------------
00252 
00253     template <template <typename ResultIterator> class ResultDatabase>
00254     class Test_ResultDatabase_ResultIterator : public ::OKlib::TestSystem::TestBase {
00255     public :
00256       typedef Test_ResultDatabase_ResultIterator test_type;
00257       Test_ResultDatabase_ResultIterator() {
00258         insert(this);
00259       }
00260 
00261     private :
00262       
00263       void perform_test_trivial() {
00264 
00265         test_result<Result>(filename_large_industrial, line_count_large_industrial);
00266         test_result<ResultRandomSat>(filename_large_random, line_count_large_random);
00267 
00268       }
00269 
00270       template <class result_type>
00271       void test_result(const std::string& filename, const unsigned int line_count) {
00272 
00273         typedef typename tuple_type<result_type>::type TupleResult;
00274         typedef std::vector<result_type> VectorResult;
00275         typedef typename VectorResult::const_iterator const_iterator;
00276         typedef typename VectorResult::iterator iterator;
00277         typedef typename VectorResult::size_type size_type;
00278         typedef ResultDatabase<const_iterator> result_database;
00279 
00280         {
00281           typedef ParserResult<result_type> Parser;
00282           typedef std::vector<TupleResult> VectorTupleResult;
00283           typedef typename VectorTupleResult::size_type size_type_tuple;
00284           VectorTupleResult pre_test_vector;
00285           add_positive_result_tuples(pre_test_vector);
00286 
00287           std::stringstream input;
00288           std::copy(pre_test_vector.begin(), pre_test_vector.end(), std::ostream_iterator<TupleResult>(input, "\n"));
00289 
00290           VectorResult test_vector;
00291           assert(copy_results<Parser>(input.str().c_str(), std::back_inserter(test_vector)).full);
00292           assert(test_vector.size() == pre_test_vector.size());
00293 
00294           result_database db(test_vector.begin(), test_vector.end());
00295 
00296           OKLIB_TESTTRIVIAL_RETHROW(test_Database_vs_Container(db, test_vector));
00297         }
00298         {
00299           VectorResult test_vector;
00300           typedef std::back_insert_iterator<VectorResult> OutputIterator;
00301           typedef Copy_results_from_file<ParserResult, OutputIterator, result_type> Copy;
00302           assert(Copy()(filename, std::back_inserter(test_vector)).full);
00303           assert(test_vector.size() == line_count);
00304           result_database db(test_vector.begin(), test_vector.end());
00305           OKLIB_TESTTRIVIAL_RETHROW(test_Database_vs_Container(db, test_vector));
00306         }
00307 
00308       }
00309 
00310     };
00311     
00312   }
00313 
00314 }
00315 
00316 #endif