00001
00002
00003
00004
00005
00006 #ifndef SOLVERDFPN_HPP
00007 #define SOLVERDFPN_HPP
00008
00009 #include "SgSystem.h"
00010 #include "SgStatistics.h"
00011 #include "SgTimer.h"
00012
00013 #include "Hex.hpp"
00014 #include "HexBoard.hpp"
00015 #include "HexState.hpp"
00016 #include "Game.hpp"
00017 #include "TransTable.hpp"
00018 #include "StateDB.hpp"
00019 #include "SolverDB.hpp"
00020
00021 #include <limits>
00022 #include <boost/scoped_ptr.hpp>
00023
00024 _BEGIN_BENZENE_NAMESPACE_
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 typedef SgStatisticsExt<float, std::size_t> DfpnStatistics;
00040
00041
00042
00043
00044
00045
00046 typedef unsigned DfpnBoundType;
00047
00048
00049
00050
00051 struct DfpnBounds
00052 {
00053
00054 static const DfpnBoundType INFTY = 2000000000;
00055
00056
00057 static const DfpnBoundType MAX_WORK = INFTY / 2;
00058
00059
00060
00061 DfpnBoundType phi;
00062
00063
00064
00065 DfpnBoundType delta;
00066
00067 DfpnBounds();
00068
00069 DfpnBounds(DfpnBoundType p, DfpnBoundType d);
00070
00071
00072
00073
00074 bool GreaterThan(const DfpnBounds& other) const;
00075
00076
00077 bool IsWinning() const;
00078
00079
00080 bool IsLosing() const;
00081
00082
00083 bool IsSolved() const;
00084
00085 void CheckConsistency() const;
00086
00087
00088 std::string Print() const;
00089
00090
00091 static void SetToWinning(DfpnBounds& bounds);
00092
00093
00094 static void SetToLosing(DfpnBounds& bounds);
00095 };
00096
00097 inline DfpnBounds::DfpnBounds()
00098 : phi(INFTY),
00099 delta(INFTY)
00100 {
00101 }
00102
00103 inline DfpnBounds::DfpnBounds(DfpnBoundType p, DfpnBoundType d)
00104 : phi(p),
00105 delta(d)
00106 {
00107 }
00108
00109 inline std::string DfpnBounds::Print() const
00110 {
00111 std::ostringstream os;
00112 os << "[" << phi << ", " << delta << "]";
00113 return os.str();
00114 }
00115
00116 inline bool DfpnBounds::GreaterThan(const DfpnBounds& other) const
00117 {
00118 return (phi > other.phi) && (delta > other.delta);
00119 }
00120
00121 inline bool DfpnBounds::IsWinning() const
00122 {
00123 return phi == 0;
00124 }
00125
00126 inline bool DfpnBounds::IsLosing() const
00127 {
00128 return delta == 0;
00129 }
00130
00131 inline bool DfpnBounds::IsSolved() const
00132 {
00133 return IsWinning() || IsLosing();
00134 }
00135
00136 inline void DfpnBounds::SetToWinning(DfpnBounds& bounds)
00137 {
00138 bounds.phi = 0;
00139 bounds.delta = INFTY;
00140 }
00141
00142 inline void DfpnBounds::SetToLosing(DfpnBounds& bounds)
00143 {
00144 bounds.phi = INFTY;
00145 bounds.delta = 0;
00146 }
00147
00148
00149 inline std::ostream& operator<<(std::ostream& os, const DfpnBounds& bounds)
00150 {
00151 os << bounds.Print();
00152 return os;
00153 }
00154
00155
00156
00157
00158
00159
00160 class DfpnChildren
00161 {
00162 public:
00163 DfpnChildren();
00164
00165 void SetChildren(const std::vector<HexPoint>& children);
00166
00167 std::size_t Size() const;
00168
00169 HexPoint FirstMove(int index) const;
00170
00171 void PlayMove(int index, HexState& state) const;
00172
00173 void UndoMove(int index, HexState& state) const;
00174
00175 private:
00176 friend class DfpnData;
00177 friend class DfpnSolver;
00178
00179 std::vector<HexPoint> m_children;
00180 };
00181
00182 inline std::size_t DfpnChildren::Size() const
00183 {
00184 return m_children.size();
00185 }
00186
00187 inline HexPoint DfpnChildren::FirstMove(int index) const
00188 {
00189 return m_children[index];
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199 class DfpnData
00200 {
00201 public:
00202
00203 DfpnBounds m_bounds;
00204
00205 DfpnChildren m_children;
00206
00207 HexPoint m_bestMove;
00208
00209 size_t m_work;
00210
00211 bitset_t m_maxProofSet;
00212
00213 float m_evaluationScore;
00214
00215 DfpnData();
00216
00217 DfpnData(const DfpnBounds& bounds, const DfpnChildren& children,
00218 HexPoint bestMove, size_t work, bitset_t maxProofSet,
00219 float evaluationScore);
00220
00221 ~DfpnData();
00222
00223 std::string Print() const;
00224
00225
00226
00227
00228 bool Initialized() const;
00229
00230 bool ReplaceWith(const DfpnData& data) const;
00231
00232
00233
00234
00235
00236
00237 int PackedSize() const;
00238
00239 byte* Pack() const;
00240
00241 void Unpack(const byte* data);
00242
00243 void Rotate(const ConstBoard& brd);
00244
00245
00246
00247 private:
00248
00249 bool m_initialized;
00250 };
00251
00252
00253 inline DfpnData::DfpnData()
00254 : m_initialized(false)
00255 {
00256 }
00257
00258 inline DfpnData::DfpnData(const DfpnBounds& bounds,
00259 const DfpnChildren& children,
00260 HexPoint bestMove, size_t work,
00261 bitset_t maxProofSet, float evaluationScore)
00262 : m_bounds(bounds),
00263 m_children(children),
00264 m_bestMove(bestMove),
00265 m_work(work),
00266 m_maxProofSet(maxProofSet),
00267 m_evaluationScore(evaluationScore),
00268 m_initialized(true)
00269 {
00270 }
00271
00272 inline DfpnData::~DfpnData()
00273 {
00274 }
00275
00276 inline std::string DfpnData::Print() const
00277 {
00278 std::ostringstream os;
00279 os << '['
00280 << "bounds=" << m_bounds << ' '
00281 << "children=" << m_children.Size() << ' '
00282 << "bestmove=" << m_bestMove << ' '
00283 << "work=" << m_work << ' '
00284 << "maxpfset=not printing"
00285 << "evaluation=" << m_evaluationScore
00286 << ']';
00287 return os.str();
00288 }
00289
00290 inline bool DfpnData::ReplaceWith(const DfpnData& data) const
00291 {
00292 SG_UNUSED(data);
00293 return true;
00294 }
00295
00296 inline bool DfpnData::Initialized() const
00297 {
00298 return m_initialized;
00299 }
00300
00301
00302 inline std::ostream& operator<<(std::ostream& os, const DfpnData& data)
00303 {
00304 os << data.Print();
00305 return os;
00306 }
00307
00308
00309
00310
00311
00312
00313 class DfpnHistory
00314 {
00315 public:
00316 DfpnHistory();
00317
00318
00319 void Push(HexPoint m_move, hash_t hash);
00320
00321
00322 void Pop();
00323
00324
00325 int Depth() const;
00326
00327
00328 hash_t LastHash() const;
00329
00330
00331 HexPoint LastMove() const;
00332
00333 private:
00334
00335
00336 std::vector<HexPoint> m_move;
00337
00338
00339 std::vector<hash_t> m_hash;
00340 };
00341
00342 inline DfpnHistory::DfpnHistory()
00343 {
00344 m_move.push_back(INVALID_POINT);
00345 m_hash.push_back(0);
00346 }
00347
00348 inline void DfpnHistory::Push(HexPoint move, hash_t hash)
00349 {
00350 m_move.push_back(move);
00351 m_hash.push_back(hash);
00352 }
00353
00354 inline void DfpnHistory::Pop()
00355 {
00356 m_move.pop_back();
00357 m_hash.pop_back();
00358 }
00359
00360 inline int DfpnHistory::Depth() const
00361 {
00362 HexAssert(!m_move.empty());
00363 return static_cast<int>(m_move.size() - 1);
00364 }
00365
00366 inline hash_t DfpnHistory::LastHash() const
00367 {
00368 return m_hash.back();
00369 }
00370
00371 inline HexPoint DfpnHistory::LastMove() const
00372 {
00373 return m_move.back();
00374 }
00375
00376
00377
00378
00379
00380
00381 class DfpnListener
00382 {
00383 public:
00384 virtual ~DfpnListener();
00385
00386
00387 virtual void StateSolved(const DfpnHistory& history, const DfpnData& data) = 0;
00388 };
00389
00390
00391
00392
00393
00394
00395 typedef TransTable<DfpnData> DfpnHashTable;
00396
00397
00398
00399
00400 class DfpnDB : public StateDB<DfpnData>
00401 {
00402 public:
00403 static const std::string DFPN_DB_VERSION;
00404
00405 DfpnDB(const std::string& filename)
00406 : StateDB<DfpnData>(filename, DFPN_DB_VERSION)
00407 { }
00408 };
00409
00410
00411
00412
00413 typedef SolverDB<DfpnHashTable, DfpnDB, DfpnData> DfpnStates;
00414
00415
00416
00417
00418
00419
00420 class DfpnSolver
00421 {
00422 public:
00423
00424 DfpnSolver();
00425
00426 ~DfpnSolver();
00427
00428
00429
00430
00431 HexColor StartSearch(const HexState& state, HexBoard& brd,
00432 DfpnStates& positions, PointSequence& pv);
00433
00434 HexColor StartSearch(const HexState& state, HexBoard& brd,
00435 DfpnStates& positions, PointSequence& pv,
00436 const DfpnBounds& maxBounds);
00437
00438 void AddListener(DfpnListener& listener);
00439
00440
00441
00442 std::string EvaluationInfo() const;
00443
00444
00445
00446 void PropagateBackwards(const Game& game, DfpnStates& pos);
00447
00448
00449
00450
00451
00452
00453
00454 bool UseGuiFx() const;
00455
00456
00457 void SetUseGuiFx(bool enable);
00458
00459
00460
00461 double Timelimit() const;
00462
00463
00464 void SetTimelimit(double timelimit);
00465
00466
00467
00468
00469
00470
00471 int WideningBase() const;
00472
00473
00474 void SetWideningBase(int wideningBase);
00475
00476
00477
00478
00479 float WideningFactor() const;
00480
00481
00482 void SetWideningFactor(float wideningFactor);
00483
00484
00485
00486 private:
00487
00488
00489 class GuiFx
00490 {
00491 public:
00492
00493 GuiFx();
00494
00495 void SetChildren(const DfpnChildren& children,
00496 const std::vector<DfpnData>& bounds);
00497
00498 void PlayMove(HexColor color, int index);
00499
00500 void UndoMove();
00501
00502 void UpdateCurrentBounds(const DfpnBounds& bounds);
00503
00504 void Write();
00505
00506 void WriteForced();
00507
00508 private:
00509
00510 DfpnChildren m_children;
00511
00512 std::vector<DfpnData> m_data;
00513
00514 HexColor m_color;
00515
00516 int m_index;
00517
00518 double m_timeOfLastWrite;
00519
00520 int m_indexAtLastWrite;
00521
00522 double m_delay;
00523
00524 void DoWrite();
00525 };
00526
00527 boost::scoped_ptr<HexState> m_state;
00528
00529 HexBoard* m_workBoard;
00530
00531 DfpnStates* m_positions;
00532
00533 std::vector<DfpnListener*> m_listener;
00534
00535 SgTimer m_timer;
00536
00537
00538 bool m_useGuiFx;
00539
00540
00541 double m_timelimit;
00542
00543
00544 int m_wideningBase;
00545
00546
00547 float m_wideningFactor;
00548
00549
00550
00551
00552 size_t m_checkTimerAbortCalls;
00553
00554 bool m_aborted;
00555
00556 GuiFx m_guiFx;
00557
00558 size_t m_numTerminal;
00559
00560 size_t m_numMIDcalls;
00561
00562 size_t m_numVCbuilds;
00563
00564 SgStatisticsExt<float, std::size_t> m_prunedSiblingStats;
00565
00566 SgStatisticsExt<float, std::size_t> m_moveOrderingPercent;
00567
00568 SgStatisticsExt<float, std::size_t> m_moveOrderingIndex;
00569
00570 SgStatisticsExt<float, std::size_t> m_considerSetSize;
00571
00572 SgStatisticsExt<float, std::size_t> m_deltaIncrease;
00573
00574 size_t m_totalWastedWork;
00575
00576 SgHistogram<float, std::size_t> m_allEvaluation;
00577
00578 SgHistogram<float, std::size_t> m_allSolvedEvaluation;
00579
00580 SgHistogram<float, std::size_t> m_winningEvaluation;
00581
00582 SgHistogram<float, std::size_t> m_losingEvaluation;
00583
00584 size_t MID(const DfpnBounds& n, DfpnHistory& history);
00585
00586 void SelectChild(int& bestMove, DfpnBoundType& delta2,
00587 const std::vector<DfpnData>& childrenDfpnBounds,
00588 size_t maxChildIndex) const;
00589
00590 void UpdateBounds(DfpnBounds& bounds,
00591 const std::vector<DfpnData>& childBounds,
00592 size_t maxChildIndex) const;
00593
00594 bool CheckAbort();
00595
00596 void LookupData(DfpnData& data, const DfpnChildren& children,
00597 int childIndex, HexState& state);
00598
00599 bool TTRead(const HexState& state, DfpnData& data);
00600
00601 void TTWrite(const HexState& state, const DfpnData& data);
00602
00603 void DumpGuiFx(const std::vector<HexPoint>& children,
00604 const std::vector<DfpnBounds>& childBounds) const;
00605
00606 void PrintStatistics(HexColor winner, const PointSequence& p) const;
00607
00608 size_t ComputeMaxChildIndex(const std::vector<DfpnData>&
00609 childrenData) const;
00610
00611 void DeleteChildren(DfpnChildren& children,
00612 std::vector<DfpnData>& childrenData,
00613 bitset_t deleteChildren) const;
00614
00615 void NotifyListeners(const DfpnHistory& history, const DfpnData& data);
00616 };
00617
00618 inline void DfpnSolver::AddListener(DfpnListener& listener)
00619 {
00620 if (std::find(m_listener.begin(), m_listener.end(), &listener)
00621 != m_listener.end())
00622 m_listener.push_back(&listener);
00623 }
00624
00625 inline bool DfpnSolver::UseGuiFx() const
00626 {
00627 return m_useGuiFx;
00628 }
00629
00630 inline void DfpnSolver::SetUseGuiFx(bool enable)
00631 {
00632 m_useGuiFx = enable;
00633 }
00634
00635 inline double DfpnSolver::Timelimit() const
00636 {
00637 return m_timelimit;
00638 }
00639
00640 inline void DfpnSolver::SetTimelimit(double timelimit)
00641 {
00642 m_timelimit = timelimit;
00643 }
00644
00645 inline int DfpnSolver::WideningBase() const
00646 {
00647 return m_wideningBase;
00648 }
00649
00650 inline void DfpnSolver::SetWideningBase(int wideningBase)
00651 {
00652 m_wideningBase = wideningBase;
00653 }
00654
00655 inline float DfpnSolver::WideningFactor() const
00656 {
00657 return m_wideningFactor;
00658 }
00659
00660 inline void DfpnSolver::SetWideningFactor(float wideningFactor)
00661 {
00662 m_wideningFactor = wideningFactor;
00663 }
00664
00665
00666
00667 _END_BENZENE_NAMESPACE_
00668
00669 #endif // SOLVERDFPN_HPP