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