14 #include <boost/shared_ptr.hpp> 
   15 #include <boost/program_options.hpp> 
   16 #include <boost/progress.hpp> 
   17 #include <boost/format.hpp> 
   25 #include <boost/shared_ptr.hpp> 
   39                 const boost::program_options::options_description& command_line_options)
 
   41   out << 
"Usage: " << argv[0] << 
" [options] <book-a.dat> <book-b.dat>\n" 
   42       << command_line_options 
 
   46 typedef osl::hash_map<osl::HashKey,int> 
table_t;
 
   51   std::fill(parents.begin(), parents.end(), -1);
 
   54   typedef std::pair<int, int> state_depth_t;
 
   55   std::deque<state_depth_t> stateToVisit;
 
   56   stateToVisit.push_back(state_depth_t(book.
getStartState(), 1)); 
 
   60   typedef std::pair<int, int> eval_depth_t;
 
   63   while (!stateToVisit.empty())
 
   65     const state_depth_t state_depth = stateToVisit.front();
 
   66     const int stateIndex = state_depth.first;
 
   67     const int depth      = state_depth.second;
 
   68     stateToVisit.pop_front();
 
   70     assert(parents[stateIndex] >= 0 || stateIndex == book.
getStartState());
 
   72     depth_found = 
std::max(depth_found, depth);
 
   78     if ( !moves.empty() &&
 
   85         min = moves.at(0).getWeight();
 
   90             const int weight = moves.at(i).getWeight();
 
   91             if ((
double)weight < (
double)moves.at(i-1).getWeight()*
ratio)
 
   98       if (min == 0) min = 1;
 
  100       WMoveContainer::iterator each = moves.begin();
 
  101       for (; each != moves.end(); ++each)
 
  103         if (each->getWeight() < 
min)
 
  106       moves.erase(each, moves.end());
 
  115     if (moves[0].getWeight()) {
 
  118       const osl::HashKey key(state);
 
  119       table[key] = stateIndex;
 
  124     for (std::vector<osl::record::opening::WMove>::const_iterator each = moves.begin();
 
  125          each != moves.end(); ++each)
 
  127       const int nextIndex = each->getStateIndex();
 
  128       if (parents[nextIndex] < 0) {
 
  129         parents[nextIndex] = stateIndex;
 
  130         stateToVisit.push_back(state_depth_t(nextIndex, depth+1));
 
  136   std::cout << std::endl;
 
  137   std::cout << boost::format(
"Player: %s\n") % 
the_player;
 
  139     boost::format(
"#leaves: %d, max_depth %d\n") 
 
  149   if (! moves.empty() && moves[0].getWeight()) {
 
  151     for (
size_t i=0; i<moves.size(); ++i) {
 
  152       if (moves[i].getWeight() == 0)
 
  154       const int next_state_index = moves[i].getStateIndex();
 
  158                 << 
"(" << moves[i].getWeight() << 
"," << black_win << 
"," << white_win << 
")";
 
  166   std::cout << 
"[" << history.size() << 
"]";
 
  167   for (
size_t i=0; i<history.size(); ++i)
 
  169   std::cout << std::endl;
 
  174   osl::vector<int> history;
 
  175   history.push_back(node);
 
  176   while (parents[node] >= 0) {
 
  177     node = parents[node];
 
  178     history.push_back(node);
 
  180   std::reverse(history.begin(), history.end());
 
  184   for (
size_t i=0; i<history.size()-1; ++i) {
 
  186     for (WMoveContainer::const_iterator p=moves.begin(); p!=moves.end(); ++p) {
 
  187       if (p->getStateIndex() != history[i+1])
 
  189       result.push_back(p->getMove());
 
  201                                   boost::shared_ptr<osl::record::Characters>(
 
  204   printer.print(state);
 
  205   const osl::MoveVector history_a = 
make_history(book_a, parents_a, node_a);
 
  206   const osl::MoveVector history_b = 
make_history(book_b, parents_b, node_b);
 
  208   if (! (history_a == history_b))
 
  218                                   boost::shared_ptr<osl::record::Characters>(
 
  221   printer.print(state);
 
  236   for (; i<
std::min(moves_a.size(), moves_b.size()); ++i) {
 
  237     if (moves_a[i].getWeight() == 0)
 
  238       return moves_b[i].getWeight() == 0;
 
  239     if (moves_b[i].getWeight() == 0)
 
  241     if (moves_a[i].getMove() != moves_b[i].getMove())
 
  244   if (i == moves_a.size())
 
  245     return i == moves_b.size() || moves_b[i].getWeight() == 0;
 
  246   return moves_a[i].getWeight() == 0;
 
  252   long only_a = 0, only_b = 0, same = 0, diff = 0;
 
  253   for (table_t::const_iterator p=table_a.begin(); p!=table_a.end(); ++p) {
 
  254     table_t::const_iterator q=table_b.find(p->first);
 
  255     if (q == table_b.end()) {
 
  258         dump(
"a", book_a, parents_a, p->second);        
 
  266         dump(book_a, parents_a, p->second, 
 
  267              book_b, parents_b, q->second);     
 
  270   for (table_t::const_iterator p=table_b.begin(); p!=table_b.end(); ++p) {
 
  271     table_t::const_iterator q=table_a.find(p->first);
 
  272     if (q == table_a.end()) {
 
  275         dump(
"b", book_b, parents_b, p->second);        
 
  279   std::cout << 
"same " << same << 
" diff " << diff
 
  280             << 
" only-in-a " << only_a << 
" only-in-b " << only_b << std::endl;
 
  283 int main(
int argc, 
char **argv)
 
  285   std::string player_str;
 
  287   namespace bp = boost::program_options;
 
  288   bp::variables_map 
vm;
 
  289   bp::options_description command_line_options;
 
  290   command_line_options.add_options()
 
  291     (
"player,p", bp::value<std::string>(&player_str)->default_value(
"black"),
 
  292      "specify a player, black or white, in whose point of view the book is validated. " 
  294     (
"input-file,f", bp::value<std::vector<std::string> >(),
 
  295      "a joseki file to validate.")
 
  297      "common: dump positions where two books have different moves\n" 
  298      "(a|b): dump positions registered to only book_[ab]\n")
 
  299     (
"determinate", bp::value<int>(&
is_determinate)->default_value(0),
 
  300      "only search the top n moves.  (0 for all,  1 for determinate).")
 
  302      "use the best move where the depth is greater than this value")
 
  303     (
"max-depth", bp::value<int>(&
max_depth)->default_value(100),
 
  304      "do not go beyond this depth from the root")
 
  305     (
"ratio", bp::value<double>(&
ratio)->default_value(0.0),
 
  306      "skip move[i] (i >= n), if weight[n] < weight[n-1]*ratio")
 
  307     (
"help,h", 
"show this help message.");
 
  308   bp::positional_options_description p;
 
  309   p.add(
"input-file", -1);
 
  311   std::vector<std::string> filenames;
 
  315       bp::command_line_parser(
 
  316         argc, argv).options(command_line_options).positional(p).
run(), vm);
 
  318     filenames = vm[
"input-file"].as<std::vector<std::string> >();
 
  319     if (vm.count(
"help") || filenames.size() != 2 
 
  322       printUsage(std::cout, argv, command_line_options);
 
  326   catch (std::exception &e)
 
  328     std::cerr << 
"error in parsing options\n" 
  329               << e.what() << std::endl;
 
  330     printUsage(std::cerr, argv, command_line_options);
 
  334   if (player_str == 
"black")
 
  336   else if (player_str == 
"white")
 
  340     printUsage(std::cerr, argv, command_line_options);
 
  345   osl::CArray<osl::vector<int>,2> parents;
 
  346   osl::CArray<table_t,2> tables;
 
  347   std::cout << boost::format(
"Book: %s\n") % filenames[0];
 
  348   store(book_a, tables[0], parents[0]);
 
  349   std::cout << boost::format(
"Book: %s\n") % filenames[1];
 
  350   store(book_b, tables[1], parents[1]);
 
  352   compare(book_a, tables[0], parents[0], book_b, tables[1], parents[1]);