dfpn.h
Go to the documentation of this file.
00001 /* dfpn.h
00002  */
00003 #ifndef OSL_DFPN_H
00004 #define OSL_DFPN_H
00005 #include "osl/checkmate/proofDisproof.h"
00006 #include "osl/checkmate/checkMoveVector.h"
00007 #include "osl/state/numEffectState.h"
00008 #include "osl/container/moveVector.h"
00009 #include "osl/hash/hashKey.h"
00010 #include "osl/stl/vector.h"
00011 #include "osl/pathEncoding.h"
00012 #include "osl/config.h"
00013 #include <boost/scoped_array.hpp>
00014 #include <boost/scoped_ptr.hpp>
00015 #include <boost/noncopyable.hpp>
00016 
00017 #ifdef OSL_SMP
00018 #  ifndef OSL_DFPN_SMP
00019 #    define OSL_DFPN_SMP
00020 #  endif
00021 #endif
00022 
00023 #ifdef OSL_DFPN_SMP
00024 #  include "osl/misc/lightMutex.h"
00025 #  include <boost/thread/mutex.hpp>
00026 #endif
00027 
00028 namespace osl
00029 {
00030   namespace checkmate
00031   {
00032     class DfpnRecord;
00034     class DfpnTable
00035     {
00036       struct Table;
00037       struct List;
00038       boost::scoped_array<Table> table;
00039       size_t total_size;
00040       int dfpn_max_depth;
00041       size_t growth_limit, gc_threshold;
00042     public:
00043       DfpnTable(Player attack);
00044       DfpnTable();
00045       ~DfpnTable();
00046       template <Player Attack>
00047       const DfpnRecord probe(const HashKey& key, PieceStand white) const;
00048       const DfpnRecord probe(const HashKey& key, PieceStand white) const;
00049       size_t estimateNodeCount(const HashKey& key, bool dominance_max=false) const;
00050       template <Player Attack>
00051       const DfpnRecord findProofOracle(const HashKey& key, PieceStand white, Move last_move=Move()) const;
00052       const DfpnRecord findProofOracle(const HashKey& key, PieceStand white, Move last_move=Move()) const;
00053       template <Player Attack>
00054       void showProofOracles(const HashKey& key, PieceStand white, Move last_move=Move()) const;
00055       size_t
00056 #ifdef __GNUC__
00057         __attribute__ ((pure))
00058 #endif
00059       size() const;
00060       void showStats() const;
00061 
00062       void setAttack(Player);
00063       void setWorking(const HashKey& key, const DfpnRecord& value, int thread_id);
00064       void leaveWorking(const HashKey& key, int thread_id);
00065       void store(const HashKey& key, DfpnRecord& value, int leaving_thread_id=-1);
00066       void addDag(const HashKey& key, DfpnRecord& value);
00067       void clear();
00068       size_t totalSize() { return total_size; }
00069       Player attack() const;
00070 
00071       void setMaxDepth(int);
00072       int maxDepth() const;
00073 
00074       void testTable();
00075       size_t smallTreeGC(size_t threshold=10);
00077       void setGrowthLimit(size_t new_limit);
00078       size_t growthLimit() const { return growth_limit; }
00079       bool runGC();
00080     private:
00081 #ifdef OSL_DFPN_SMP
00082       typedef osl::misc::LightMutex Mutex;
00083 #  ifdef USE_TBB_HASH
00084       static const int DIVSIZE=1;
00085 #  else
00086       static const int DIVSIZE=256;
00087       mutable CArray<Mutex,DIVSIZE> mutex;
00088 #  endif
00089       // typedef boost::mutex Mutex;
00090       // TODO: boost::thread::shared_lock (available version >= 1.35) for multi read accessess
00091       LightMutex root_mutex;
00092 #else
00093       static const int DIVSIZE=1;
00094 #endif
00095       static int keyToIndex(const HashKey& key)
00096       {
00097         unsigned long val=key.signature();
00098         return (val>>24)%DIVSIZE;
00099       }
00100       template <Player Attack>
00101       List *find(const HashKey& key, int subindex);
00102       template <Player Attack>
00103       const List *find(const HashKey& key, int subindex) const;
00104       const List *find(const HashKey& key, int subindex) const;
00105     };
00107     class DfpnPathTable;
00109     class DfpnShared;
00111     class Dfpn : boost::noncopyable
00112     {
00113     public:
00114       enum { DfpnMaxUniqMoves = CheckOrEscapeMaxUniqMoves };
00115       typedef CheckMoveVector DfpnMoveVector;
00116       typedef DfpnTable table_t;
00117     private:
00118       DfpnTable *table;
00119       struct NodeBase;
00120       struct Node;
00121       struct Tree;
00122       boost::scoped_ptr<Tree> tree;
00123       boost::scoped_ptr<DfpnPathTable> path_table;
00124       size_t node_count;
00125       size_t node_count_limit;
00126       DfpnShared *parallel_shared;
00127       int thread_id;
00128       bool blocking_verify;
00129     public:
00130       Dfpn();
00131       ~Dfpn();
00132       void setTable(DfpnTable *new_table);
00133       void setIllegal(const HashKey& key, PieceStand white);
00134       void setBlockingVerify(bool enable=true) { blocking_verify = enable; }
00135       void setParallel(int id, DfpnShared *s) 
00136       {
00137         if (s)
00138           assert(id >= 0);
00139         thread_id = id; 
00140         parallel_shared = s; 
00141       }
00142       const ProofDisproof 
00143       hasCheckmateMove(const NumEffectState& state, const HashKey& key,
00144                        const PathEncoding& path, size_t limit, Move& best_move,
00145                        Move last_move=Move::INVALID(), vector<Move> *pv=0);
00146       const ProofDisproof 
00147       hasCheckmateMove(const NumEffectState& state, const HashKey& key,
00148                        const PathEncoding& path, size_t limit, Move& best_move, PieceStand& proof,
00149                        Move last_move=Move::INVALID(), vector<Move> *pv=0);
00150       const ProofDisproof
00151       hasEscapeMove(const NumEffectState& state, 
00152                     const HashKey& key, const PathEncoding& path, 
00153                     size_t limit, Move last_move);
00154 
00155       size_t nodeCount() const { return node_count; }
00156       const DfpnTable& currentTable() const { return *table; }
00157       void analyze(const PathEncoding& path, 
00158                    const NumEffectState& state, const vector<Move>& moves) const;
00159       void clear();
00160 
00161       // private:
00162       template <Player P> void attack();
00163       template <Player P> void defense();
00164       template <Player P> struct CallAttack;      
00165       template <Player P> struct CallDefense;      
00166       struct DepthLimitReached {};
00167 
00168       struct ProofOracle;
00169       template <Player P, bool UseTable> void proofOracleAttack(const ProofOracle& oracle, int proof_limit);
00170       template <Player P, bool UseTable> void proofOracleDefense(const ProofOracle& oracle, int proof_limit);
00171       template <Player P, bool UseTable> struct CallProofOracleAttack;      
00172       template <Player P, bool UseTable> struct CallProofOracleDefense;      
00174       template <Player P> void blockingSimulation(int seed, const ProofOracle&);
00175       template <Player P> void grandParentSimulation(int cur_move, const Node& gparent, int gp_move);
00176     private:
00177       template <bool UseTable>
00178       const ProofDisproof 
00179       tryProofMain(const NumEffectState& state, const HashKey& key,
00180                    const PathEncoding& path, const ProofOracle&, size_t oracle_id, Move& best_move,
00181                    Move last_move);
00182     public:
00183       const ProofDisproof 
00184       tryProof(const NumEffectState& state, const HashKey& key,
00185                const PathEncoding& path, const ProofOracle&, size_t oracle_id, Move& best_move,
00186                Move last_move=Move::INVALID());
00187       const ProofDisproof 
00188       tryProofLight(const NumEffectState& state, const HashKey& key,
00189                     const PathEncoding& path, const ProofOracle&, size_t oracle_id, Move& best_move,
00190                     Move last_move=Move::INVALID());
00191 
00192       // debug
00193       int distance(const HashKey&) const;
00195       template <Player P>
00196       static void generateCheck(const NumEffectState&, DfpnMoveVector&, bool&);
00198       template <Player P>
00199       static void generateEscape(const NumEffectState&, bool need_full_width, 
00200                                  Square grand_parent_delay_last_to, DfpnMoveVector&);
00202       bool grandParentSimulationSuitable() const;
00203       template <Player Turn>
00204       static void sort(const NumEffectState&, DfpnMoveVector&);
00205     private:
00206       void findDagSource();
00207       void findDagSource(const HashKey& terminal_key,
00208                          DfpnRecord& terminal_record,
00209                          PieceStand terminal_stand, int offset=0);
00210     };
00211 
00212   }
00213 }
00214 
00215 struct osl::checkmate::Dfpn::ProofOracle
00216 {
00217   HashKey key;
00218   PieceStand white_stand;
00219   ProofOracle(const HashKey& k, PieceStand w) : key(k), white_stand(w)
00220   {
00221   }
00222   const ProofOracle newOracle(Player P, Move move) const
00223   {
00224     assert(P == move.player());
00225     return ProofOracle(key.newHashWithMove(move),
00226                        (P == WHITE) ? white_stand.nextStand(P, move) : white_stand);
00227   }
00228   bool traceable(Player P, Move move) const
00229   {
00230     assert(P == move.player());
00231     if (! move.isDrop()) 
00232       return true;
00233     if (P == BLACK) {
00234       if (key.blackStand().get(move.ptype()) == 0)
00235         return false;
00236     }
00237     else {
00238       if (white_stand.get(move.ptype()) == 0)
00239         return false;
00240     }
00241     return true;
00242   }
00243 };
00244 
00245 #endif /* OSL_DFPN_H */
00246 // ;;; Local Variables:
00247 // ;;; mode:c++
00248 // ;;; c-basic-offset:2
00249 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines