dfpnstat.cc
Go to the documentation of this file.
00001 #include "osl/checkmate/dfpn.h"
00002 #include "osl/checkmate/dfpnParallel.h"
00003 #include "osl/record/csaString.h"
00004 #include "osl/record/csaRecord.h"
00005 #include "osl/record/csaIOError.h"
00006 #include "osl/state/numEffectState.h"
00007 #include "osl/misc/perfmon.h"
00008 #include "osl/misc/milliSeconds.h"
00009 
00010 #include "osl/move_generator/legalMoves.h"
00011 #include "osl/checkmate/dfpnRecord.h"
00012 #include "osl/oslConfig.h"
00013 
00014 #include <boost/scoped_ptr.hpp>
00015 #include <boost/foreach.hpp>
00016 #include <string>
00017 #include <iostream>
00018 #include <iomanip>
00019 #include <fstream>
00020 #include <cstdlib>
00021 #include <unistd.h>
00022 
00023 #include <bitset>
00024 
00025 using namespace osl;
00026 using namespace osl::checkmate;
00027 using namespace osl::misc;
00028 
00029 bool verbose=false;
00030 unsigned long long total_cycles=0;
00031 bool show_escape_filename = false;
00032 bool force_attack = false;
00033 int num_checkmate=0, num_nocheckmate=0, num_escape=0, num_unkown=0;
00034 double total_nodes=0, total_tables=0;
00035 int limit = 100000;
00036 bool blocking_verify = true;
00037 size_t table_growth_limit = 8000000;
00038 bool debug = false;
00039 int forward_moves = 0;
00040 
00041 template<class DfpnSearch>
00042 void search(DfpnSearch&, const char *filename);
00043 void usage(const char *program_name)
00044 {
00045   std::cerr << "usage: " << program_name << " [-d] [-v] [-f] [-l limit] [-N] csa-files\n";
00046 }
00047 int main(int argc, char **argv)
00048 {
00049   const char *program_name = argv[0];
00050   bool error_flag = false;
00051   int parallel = 0;
00052   extern char *optarg;
00053   extern int optind;
00054 
00055   char c;
00056   while ((c = getopt(argc, argv, "dfl:N:F:t:vh")) != EOF)
00057   {
00058     switch(c)
00059     {
00060     case 'd':   debug = true;
00061       break;
00062     case 'f':   force_attack = true;
00063       break;
00064     case 'F':   forward_moves = atoi(optarg);
00065       break;
00066     case 'l':   limit = atoi(optarg);
00067       break;
00068     case 'N':   parallel = atoi(optarg);
00069       break;
00070     case 't':   table_growth_limit = atoi(optarg);
00071       break;
00072 #if 0
00073     case 'V':   blocking_verify = false;
00074       break;
00075 #endif
00076     case 'v':   verbose = true;
00077       break;
00078     default:    error_flag = true;
00079     }
00080   }
00081   argc -= optind;
00082   argv += optind;
00083 
00084   if (error_flag || (argc < 1)) {
00085     usage(program_name);
00086     return 1;
00087   }
00088   OslConfig::setDfpnMaxDepth(1600);     // sufficient for microcosmos
00089   try
00090   {
00091     for (int i=0; i<argc; ++i)
00092     {
00093       if (parallel) 
00094       {
00095 #ifdef OSL_DFPN_SMP
00096         DfpnParallel dfpn(parallel);
00097         search(dfpn, argv[i]);
00098 #else
00099         std::cerr << "to use parallel dfpn, try compile with -DOSL_SMP or -DOSL_DFPN_SMP\n";
00100         return 1;
00101 #endif
00102       }
00103       else 
00104       {
00105         Dfpn dfpn;
00106         search(dfpn, argv[i]);
00107       }
00108       total_cycles = 0;
00109     }
00110     std::cerr << "check " << num_checkmate << " nocheckmate " << num_nocheckmate << " escape " << num_escape
00111               << " unknown " << num_unkown << "\n";
00112     std::cerr << "total nodes " << total_nodes 
00113               << " tables " << total_tables << "\n";
00114   }
00115   catch (std::exception& e)
00116   {
00117     std::cerr << e.what() << "\n";
00118     return 1;
00119   }
00120 }
00121 
00122 double real_seconds = 0.0;
00123 
00124 template <class DfpnSearch>
00125 void analyzeCheckmate(DfpnSearch& searcher, const NumEffectState& state, Move checkmate_move)
00126 {
00127   NumEffectState new_state = state;
00128   std::cerr << state << " " << checkmate_move << "\n";
00129   new_state.makeMove(checkmate_move);
00130   HashKey key(new_state);
00131   const DfpnTable& table = searcher.currentTable();
00132   DfpnRecordBase record = table.probe(key, PieceStand(WHITE, new_state));
00133   std::cerr << record.proof_disproof << " " << std::bitset<64>(record.solved) << "\n";
00134 
00135   MoveVector moves;
00136   LegalMoves::generate(new_state, moves);
00137   for (size_t i=0; i<moves.size(); ++i) {
00138     NumEffectState tmp = new_state;
00139     tmp.makeMove(moves[i]);
00140     DfpnRecordBase record = table.probe(key.newHashWithMove(moves[i]), PieceStand(WHITE, tmp));
00141     std::cerr << moves[i] << " " << record.proof_disproof << " " << record.best_move << "\n";
00142   }
00143 
00144   {
00145     Dfpn::DfpnMoveVector moves;
00146     if (state.turn() == BLACK)
00147       Dfpn::generateEscape<BLACK>(new_state, false, Square(), moves);
00148     else
00149       Dfpn::generateEscape<WHITE>(new_state, false, Square(), moves);
00150     std::cerr << "Escape " << moves.size()<< "\n";
00151     moves.clear();
00152     if (state.turn() == BLACK)
00153       Dfpn::generateEscape<BLACK>(new_state, true, Square(), moves);
00154     else
00155       Dfpn::generateEscape<BLACK>(new_state, true, Square(), moves);
00156     std::cerr << "Escape full " << moves.size() << "\n";
00157   }
00158 }
00159 
00160 template <class DfpnSearch>
00161 void testWinOrLose(const char *filename,
00162                    DfpnSearch& searcher,
00163                    const SimpleState& sstate, int limit,
00164                    ProofDisproof& result, Move& best_move,
00165                    const vector<Move>& moves)
00166 {
00167   const Player P = sstate.turn();
00168   NumEffectState state(sstate);
00169   const PathEncoding path(state.turn());
00170   const Square my_king = state.kingSquare(P);
00171   if ((! force_attack) 
00172       && ! my_king.isPieceStand() && state.inCheck(P))
00173   {
00174     // 相手から王手がかかっている
00175     MilliSeconds timer = MilliSeconds::now();
00176     misc::PerfMon clock;
00177     result = searcher.hasEscapeMove(state, HashKey(state), path, limit, Move::PASS(alt(P)));
00178     total_cycles += clock.stop();
00179     real_seconds = timer.elapsedSeconds();
00180 
00181     if (verbose)
00182       std::cerr << result << "\n";
00183     if (result.isCheckmateSuccess()) {
00184       ++num_checkmate;
00185     }
00186     else {
00187       if (result.isCheckmateFail())
00188         ++num_escape;
00189       else {
00190         assert(! result.isFinal());
00191         ++num_unkown;
00192       }
00193     }
00194     return;
00195   }
00196 
00197   Move checkmate_move;
00198   vector<Move> pv;
00199   MilliSeconds timer = MilliSeconds::now();
00200   PerfMon clock;
00201   result = searcher.
00202     hasCheckmateMove(state, HashKey(state), path, limit, checkmate_move, Move(), &pv);
00203   total_cycles += clock.stop();
00204   real_seconds = timer.elapsedSeconds();
00205   if (verbose)
00206     std::cerr << result << "\n";
00207 
00208   if (result.isCheckmateSuccess()) {
00209     ++num_checkmate;
00210     best_move = checkmate_move;
00211     if (verbose) {
00212       std::cerr << checkmate_move << "\n";
00213       for (size_t i=0; i<pv.size(); ++i) {
00214         std::cerr << std::setw(4) << std::setfill(' ') << i+1
00215                   << ' ' << record::csa::show(pv[i]) << " ";
00216         if (i % 6 == 5) 
00217           std::cerr << "\n";
00218       }
00219       if (pv.size() % 6 != 0)
00220           std::cerr << "\n";
00221     }
00222     if (debug) {
00223       // analyzeCheckmate(searcher, state, checkmate_move);
00224       if (! moves.empty())
00225         searcher.analyze(path, state, moves);
00226     }
00227   }
00228   else {
00229     if (result.isFinal())
00230       ++num_nocheckmate;
00231     else
00232       ++num_unkown;
00233     if (debug)
00234       searcher.analyze(path, state, moves);
00235   }
00236 }
00237 
00238 template <class DfpnSearch>
00239 void search(DfpnSearch& searcher, const char *filename)
00240 {
00241   NumEffectState state;
00242   vector<Move> moves;
00243   try {
00244     CsaFile file(filename);
00245     state = file.getInitialState();
00246     moves = file.getRecord().getMoves();
00247     int forward_here = std::min(forward_moves, (int)moves.size());
00248     for (int i=0; i<forward_here; ++i)
00249       state.makeMove(moves[i]);
00250     moves.erase(moves.begin(), moves.begin()+forward_here);
00251   }
00252   catch (CsaIOError&) {
00253     std::cerr << "\nskipping " << filename << "\n";
00254     return;
00255   }
00256   if (verbose)
00257     std::cerr << "\nsolving " << filename << "\n";
00258   
00259   // searcher.setBlockingVerify(blocking_verify);
00260   const bool attack = force_attack
00261     || state.kingSquare(state.turn()).isPieceStand()
00262     || ! state.inCheck(state.turn());
00263   DfpnTable table(attack ? state.turn() : alt(state.turn()));
00264   table.setGrowthLimit(table_growth_limit);
00265   searcher.setTable(&table);
00266   ProofDisproof result;
00267   Move best_move;
00268   testWinOrLose(filename, searcher, state, limit, result, best_move, moves);
00269   const size_t table_used = searcher.currentTable().size();
00270   total_nodes += searcher.nodeCount();
00271   total_tables += table_used;
00272 
00273   if (verbose) {
00274     PerfMon::message(total_cycles, "total ", 
00275                      searcher.nodeCount());
00276     PerfMon::message(total_cycles, "unique", table_used);
00277     std::cerr << "real " << real_seconds << " sec. nps " << searcher.nodeCount()/real_seconds << "\n";
00278   }
00279   std::cout << filename << "\t" << searcher.nodeCount() 
00280             << "\t" << table_used << "\t" << real_seconds
00281             << " " << result;
00282   if (best_move.isNormal())
00283     std::cout << " " << record::csa::show(best_move);
00284   std::cout << "\n" << std::flush;
00285 }
00286 
00287 
00288 /* ------------------------------------------------------------------------- */
00289 // ;;; Local Variables:
00290 // ;;; mode:c++
00291 // ;;; c-basic-offset:2
00292 // ;;; coding:utf-8
00293 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines