Page 1 of 1

analyze epd automatically

PostPosted: 27 Nov 2004, 10:46
by Uri Blass
I still do not have a tool to analyze epd automatically.

There are basically 2 ways that I can think about:

1)Writing a new thread that will give the engine the impression that it gets winboard commands under analysis mode.

2)adding more option for analyze varaible.

today there are 3 values that analyze can get(note that it is used only when the engine is searching so it's value is unimportant in force mode):

analyze = PLAY_MODE
analyze=PONDER_MODE
analyze=ANALYSIS_MODE

It is possible to add analyze_epd mode when the program may look at some global variables only if analyze=analyze_epd mode to decide when to stop the analysis (more varaibles can be for example time arrayt that will give time for every position in the epd file because I may want to give different times for different positions).


Option 1 has the advantage of being more general but option 2 seems to me more easy to write when I have no idea how to write option 1 because I have no experience in threads and I also need to translate the information that I get from the engine to some analysis file in that case.

What is your opinion?
Do you have a function to read epd files and if yes what design do you use to do it.
Uri

Re: analyze epd automatically

PostPosted: 27 Nov 2004, 15:57
by milix
Hi Uri.
In AICE I have a special command 'epdtest' yhat takes two arguments: The time or depth we want to spend for each epd position and an epd file name. AICE opens the file, reads the position and for each position it setups the board and calls the think() function. So basically it emulates a new game for a given starting position. Here is my code for epdtest function, I hope it helps:

Code: Select all
void Engine::on_epdtest(CMSG& msg)
{
   FILE* fp;
   int   res;
   char* args;
   bool  log=true;
   char  epdtest[256];
   char  epdfile[256];
   char  buff[256];
   int   i, tests, solved;
   long  totnodes, nodes;
   clock_t totdiff, tdiff, start, end;

   // parse command's arguments
   args = (char*)msg.lParam;
   if (tolower(*args)=='d') {
      args++;
      m_level.type = LEVEL_DEPTHSEARCH;
      m_level.u1.depth = atoi(args);
      if ((unsigned)m_level.u1.depth > MAX_DEPTH) m_level.u1.depth = MAX_DEPTH;
   } else if (tolower(*args)=='t') {
      args++;
      m_level.type = LEVEL_MOVETIME;
      m_level.u1.secs_per_move = atoi(args);
      if ((unsigned)m_level.u1.secs_per_move > 3600)
         m_level.u1.secs_per_move = 3600;
   } else {
      output(log, "Syntax is: epdtest <dDEPTH>|<tSECS> <EPD file name>\n");
      return;
   }
   while (*args && (*args==' ' || isdigit(*args))) args++;
   strcpy(epdfile, args);

   // open EPD file
   fp = fopen(epdfile, "rt");
   if (!fp) {
      strcpy(epdtest, epdfile);
      strcpy(epdfile, "tests/");
      strcat(epdfile, epdtest);
      fp = fopen(epdfile, "rt");
      if (!fp) {
         output(log, "Error opening EPD file.\n");
         return;
      }
   }

   if (m_level.type == LEVEL_DEPTHSEARCH) {
      output(log, "RUNNING EPD TEST \"%s\" @ DEPTH %d\n", epdfile, m_level.u1.depth);
   } else {
      output(log, "RUNNING EPD TEST \"%s\" @ %d SECONDS PER POSITION\n", epdfile, m_level.u1.secs_per_move);
   }
   
   // start tests
   totnodes = 0;
   totdiff  = 0;
   tests = solved = 0;
   unsigned long tnull=1, tnullcuts=0;
   unsigned long tdepth=0, tfh=1, tfhf=0;
   for (;;) {
      if (!fgets(epdtest, 256, fp)) break;
      if (brd->setup(epdtest) != OK) {
         output(log, "Error in EPD position %s\n", epdtest);
         continue;
      }
      initnew();
      brd->generate_legal();
      sprintf(buff, "%s %s (best move: %s", brd->epd_id.c_str(),
         brd->turn==WHITE ? "WTM" : "BTM",
         brd->move2str(brd->epd_bm[0], N_ALGEBRAIC));
      i = 1;
      while (!IsNullMove(brd->epd_bm[i])) {
         strcat(buff, " ");
         strcat(buff, brd->move2str(brd->epd_bm[i], N_ALGEBRAIC));
         i++;
      }
      output(log, "%s)\n", buff);
      memset(&stats, 0, sizeof(stats));
      m_color = brd->turn;
      msg.type = MSG_NONE;
      start = time_ms();
      res   = think();
      end   = time_ms();
      nodes = m_nodes;
      totnodes += nodes;
      tdiff = end - start;
      totdiff += tdiff;
      tests++;
      tdepth += stats.depth;
      tnull += stats.nm_searches;
      tnullcuts += stats.nm_cuts;
      tfh += stats.fh_total;
      tfhf += stats.fh_first;
      bool found = false;
      while (!found && --i>=0) {
         if (SameMove(m_bestmove, brd->epd_bm[i])) found = true;
      }
      if (found) {
         output(log, "SOLVED! ");
         solved++;
      } else {
         output(log, "Failed. ");
      }
      if (mcl::abs(m_pv.score[0]) >= MATE-MAX_MATE_DEPTH) {
         output(log, "found %s %s #%d, depth %d, %d KN in %.2f sec",
                  brd->move2str(m_bestmove, N_LONGALGEBRAIC),
                  evaluation_text(m_pv.score[0], m_color), mate_score(m_pv.score[0]),
                  stats.depth, nodes/1000, (double)tdiff/1000);
      } else {
         output(log, "found %s %s (%.2f) depth %d, %d KN in %.2f sec",
                  brd->move2str(m_bestmove, N_LONGALGEBRAIC),
                  evaluation_text(m_pv.score[0], m_color),
                  m_pv.score[0]/100.0, stats.depth, nodes/1000, (double)tdiff/1000);
      }
      if ((double)tdiff/1000 <= 0.001) output(log, ", REALLY GREAT KN/sec!\n");
      else output(log, ", %.1f KN/sec\n", (double)(nodes/1000)/((double)tdiff/1000));
      output(log, "Hash hits %.1f%%, cutoffs %.1f%%, nullmove %.1f%% move ordering %.1f%%\n\n",
               100.0*stats.ht_hits/stats.ht_probs, 100.0*(stats.ht_hits-stats.ht_miss)/stats.ht_probs,
               100.0*((double)stats.nm_cuts/stats.nm_searches), 100.0*((double)stats.fh_first/stats.fh_total));
   }

   fclose(fp);

   output(log, "\nTOTALS: Tests %d Solved %d (%.1f%%), depth %.1f, %d KN in %.2f sec (%.1f KN/sec)\n",
      tests, solved, 100.0*solved/tests, (float)tdepth/tests, totnodes/1000, (double)totdiff/1000, (double)(totnodes/1000)/((double)totdiff/1000));
   output(log, "Successful nullmove searches: %.1f%%, move ordering %.1f%%\n",
      100.0*((double)tnullcuts/tnull), 100.0*((double)tfhf/tfh));
}