All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
searchRecorder.cc
Go to the documentation of this file.
1 /* searchRecorder.cc
2  */
5 #include "osl/eval/evalTraits.h"
7 #include "osl/moveLogProb.h"
8 #include "osl/record/csa.h"
9 #include <fstream>
10 #include <iostream>
11 #include <cassert>
12 #ifndef _MSC_VER
13 # include <unistd.h>
14 #endif
15 
16 #ifndef MINIMAL
17 const char *checkmateFileName = "currentCheck.csa";
18 #endif
19 
21 #define SELECT_CHECKMATE_LOG
22 
24 // #define CHECKMATE_SEARCHER_DEBUG
25 
26 /* ------------------------------------------------------------------------- */
27 
29  : node_count(0), quiescence_count(0), checkmate_count(0)
30 {
31 }
32 
34 {
35 }
36 
37 void osl::search::
38 CountRecorder::recordInvalidMoveInTable(const SimpleState& state,
39  const MoveLogProb& move, int limit) const
40 {
41  std::cerr << "?? invalid move in table " << move.move() << " " << move.logProb()
42  << " limit " << limit << "\n"
43  << state;
44 }
45 
47 {
48  node_count = quiescence_count = checkmate_count = 0;
49 }
50 
51 void osl::search::
52 CountRecorder::finishSearch(Move /*best_move*/, double sec, bool verbose) const
53 {
54  if (! verbose)
55  return;
56  reportCount(std::cerr, sec);
57 }
58 
59 void osl::search::
60 CountRecorder::reportCount(std::ostream& os) const
61 {
62  os << "#normal : " << nodeCount() << ", ";
63  os << "#quiescence: " << quiescenceCount() << ", ";
64  os << "#checkmate : " << checkmateCount() << "\n";
65 }
66 
67 void osl::search::
68 CountRecorder::reportCount(std::ostream& os, double seconds) const
69 {
70  const double total = nodeCount() + quiescenceCount() + checkmateCount();
71  os << "#total : " << total
72  << std::setprecision(10)
73  << " in " << seconds << " sec., " << total/seconds << " nodes/sec."
74  << std::setprecision(4)
75  << " (quiesce " << 100.0*quiescenceCount()/total << "%,"
76  << " checkmate " << 100.0*checkmateCount()/total << "%)\n";
77 }
78 
79 /* ------------------------------------------------------------------------- */
80 
81 #ifndef MINIMAL
82 static bool showAllValues = false;
84 {
85  std::ofstream os;
91 
92  Recorder(const char *filename)
93  : os(filename),
94  current_depth(0), initial_limit(0),
95  log_margin(RealizationProbability::TableMove)
96  {
97  }
98  std::ostream& stream()
99  {
100  assert(os);
101 #if 0
102  os << current_depth << ':';
103 #endif
104  for (int i=0; i<=current_depth; ++i)
105  os << '*';
106  os << ' ';
107  return os;
108  }
110  bool notSoDeep(int limit) const
111  {
112  return
113 #ifdef SELECT_CHECKMATE_LOG
114  (limit <= initial_limit) // SearchTable::CheckmateSpecialDepth が来ることがある
115  &&
116 #endif
117  (initial_limit - limit) <= log_margin;
118  }
119  void flush()
120  {
121 #if 1
122  os << std::flush;
123 #endif
124  }
125 };
126 
128 SearchRecorder::SearchRecorder(const char *filename)
129  : recorder(new Recorder(filename))
130 {
131 }
132 
135 {
136 }
137 
138 void osl::search::
140 {
141  recorder->log_margin = margin;
142 }
143 
144 void osl::search::
145 SearchRecorder::tryMove(const MoveLogProb& m, int last_f, int limit) const
146 {
147  ++recorder->current_depth;
148  if (recorder->notSoDeep(limit-100)) // 末端ではtryMove を無視
149  {
150  std::ostream& os = stream();
151  os << "==> ";
152  csaShow(os, m.move());
153  os << " " << m.logProb() << "\t"
154  << "last_f: " << last_f << " limit: " << limit << "\n";
155  recorder->flush();
156  }
157 }
158 
159 void osl::search::
160 SearchRecorder::retryMove(const MoveLogProb& m, int last_f, int limit,
161  int retryCount) const
162 {
163  ++recorder->current_depth;
164  if (recorder->notSoDeep(limit)) // 再探索は必ず記録しないとややこしい
165  {
166  std::ostream& os = stream();
167  os << "ex" << retryCount << "> ";
168  csaShow(os, m.move());
169  os << " " << m.logProb() << "\t"
170  << "last_f: " << last_f << " limit: " << limit << "\n";
171  recorder->flush();
172  }
173 }
174 
175 void osl::search::
176 SearchRecorder::recordValue(const MoveLogProb& m, int val, bool betterMove, int limit) const
177 {
178  if (recorder->notSoDeep(limit)
179  && (showAllValues || betterMove))
180  {
181  std::ostream& os = stream();
182  os << "<== " << val << "\t";
183  csaShow(os, m.move());
184  os << "\n";
185  recorder->flush();
186  }
187  CountRecorder::recordValue(m,val,betterMove,limit);
188  --recorder->current_depth;
189 }
190 
191 static const char *lowerChar(osl::Player p)
192 {
193  return (p == osl::BLACK) ? "B (lb)>" : "W (lb)<";
194 }
195 static const char *higherChar(osl::Player p)
196 {
197  return (p == osl::BLACK) ? "B (ub)<" : "W (ub)>";
198 }
199 
200 void osl::search::
201 SearchRecorder::tableHitLowerBound(Player p, int val, int last_f, int limit) const
202 {
203  if (recorder->notSoDeep(limit))
204  {
205  stream() << "==| table answered " << lowerChar(p) << val
206  << " for " << p << " last_f " << last_f << "\n";
207  recorder->flush();
208  }
209 }
210 
211 void osl::search::
212 SearchRecorder::tableHitUpperBound(Player p, int val, int last_f, int limit) const
213 {
214  if (recorder->notSoDeep(limit))
215  {
216  stream() << "==| table answered " << higherChar(p) << val
217  << " for " << p << " last_f " << last_f << "\n";
218  recorder->flush();
219  }
220 }
221 
222 void osl::search::
223 SearchRecorder::tableStoreLowerBound(Player p, const MoveLogProb& best_move, int val, int limit) const
224 {
225  const Move move = best_move.move();
226  assert(move.isInvalid() || move.isValidOrPass());
227  // TODO: lower bound は invalid はないはず?
228  if (recorder->notSoDeep(limit-100)) // 末端は無視
229  {
230  std::ostream& os = stream();
231  os << "|== table store " << lowerChar(p) << val << " ";
232  csaShow(os, move);
233  os << " limit " << limit << "\n";
234  recorder->flush();
235  }
236 }
237 
238 void osl::search::
239 SearchRecorder::tableStoreUpperBound(Player p, const MoveLogProb& best_move, int val, int limit) const
240 {
241  const Move move = best_move.move();
242  assert(move.isInvalid() || move.isValidOrPass());
243  if (recorder->notSoDeep(limit-100)) // 末端は無視
244  {
245  std::ostream& os = stream();
246  os << "|== table store " << higherChar(p) << val << " ";
247  csaShow(os, move);
248  os << " limit " << limit << "\n";
249  recorder->flush();
250  }
251 }
252 
253 void osl::search::
254 SearchRecorder::recordTopLevelLowFail(const MoveLogProb& /* best */, int last_f) const
255 {
256  stream() << "low fail, last_f=" << last_f << "\n";
257  reportCount(stream());
258 }
259 void osl::search::
260 SearchRecorder::recordTopLevelHighFail(const MoveLogProb& best_move, int last_f) const
261 {
262  stream() << "high fail, last_f=" << last_f << " " << best_move << "\n";
263  reportCount(stream());
264 }
265 
266 void osl::search::
268 {
269  stream() << "\nnew search: limit " << limit
270  << ", log " << recorder->log_margin << "\n";
271  recorder->initial_limit = limit;
273 }
274 void osl::search::
275 SearchRecorder::finishSearch(Move best_move, double sec, bool verbose) const
276 {
277  stream() << "search finished\t" << best_move << "\n";
278  CountRecorder::finishSearch(best_move, sec, verbose);
279 }
280 
281 void osl::search::
283 #ifdef CHECKMATE_SEARCHER_DEBUG
284  state
285 #endif
286  , int
287 #ifdef CHECKMATE_SEARCHER_DEBUG
288  nodeLimit
289 #endif
290  ) const
291 {
292 #ifdef CHECKMATE_SEARCHER_DEBUG
293  std::ofstream os(checkmateFileName, std::ios::app);
294  os << state;
295  os << nodeLimit << "\n";
296 #endif
297 }
298 
299 void osl::search::
301 {
302 #ifdef CHECKMATE_SEARCHER_DEBUG
303  std::ofstream os(checkmateFileName, std::ios::app);
304  os << "done\n";
305 #endif
306 }
307 
308 std::ostream& osl::search::
310 {
311  return recorder->stream();
312 }
313 #endif
314 
315 /* ------------------------------------------------------------------------- */
316 // ;;; Local Variables:
317 // ;;; mode:c++
318 // ;;; c-basic-offset:2
319 // ;;; End: