shared_context.h
Go to the documentation of this file.
00001 // 
00002 // Copyright (c) 2010-2012, Benjamin Kaufmann
00003 // 
00004 // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ 
00005 // 
00006 // Clasp is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU General Public License as published by
00008 // the Free Software Foundation; either version 2 of the License, or
00009 // (at your option) any later version.
00010 // 
00011 // Clasp is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 // 
00016 // You should have received a copy of the GNU General Public License
00017 // along with Clasp; if not, write to the Free Software
00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019 //
00020 #ifndef CLASP_SHARED_CONTEXT_H_INCLUDED
00021 #define CLASP_SHARED_CONTEXT_H_INCLUDED
00022 #ifdef _MSC_VER
00023 #pragma warning (disable : 4200) // nonstandard extension used : zero-sized array
00024 #pragma once
00025 #endif
00026 
00027 #include <clasp/literal.h>
00028 #include <clasp/constraint.h>
00029 #include <clasp/util/left_right_sequence.h>
00030 #include <clasp/util/misc_types.h>
00031 #include <clasp/util/atomic.h>
00032 #include <clasp/solver_strategies.h>
00037 namespace Clasp {
00038 class Solver;
00039 class ClauseInfo;
00040 class Assignment;
00041 class SharedContext;
00042 class SharedLiterals;
00043 class SharedDependencyGraph;
00044 struct SolverStats;
00045 
00050 
00051 class SatPreprocessor {
00052 public:
00054         class Clause {
00055         public:
00056                 static Clause*  newClause(const Literal* lits, uint32 size);
00057                 static uint64   abstractLit(Literal p)      { return uint64(1) << ((p.var()-1) & 63);  }
00058                 uint32          size()                const { return size_;       }
00059                 const Literal&  operator[](uint32 x)  const { return lits_[x];    }
00060                 bool            inQ()                 const { return inQ_ != 0;   }
00061                 uint64          abstraction()         const { return data_.abstr; }
00062                 Clause*         next()                const { return data_.next;  }
00063                 bool            marked()              const { return marked_ != 0;}
00064                 Literal&        operator[](uint32 x)        { return lits_[x];    }    
00065                 void            setInQ(bool b)              { inQ_    = (uint32)b;}
00066                 void            setMarked(bool b)           { marked_ = (uint32)b;}
00067                 uint64&         abstraction()               { return data_.abstr; }
00068                 Clause*         linkRemoved(Clause* next)   { data_.next = next; return this; }
00069                 void            strengthen(Literal p);
00070                 void            simplify(Solver& s);
00071                 void            destroy();
00072         private:
00073                 Clause(const Literal* lits, uint32 size);
00074                 union {
00075                         uint64  abstr;      // abstraction of literals
00076                         Clause* next;       // next removed clause
00077                 }       data_;
00078                 uint32  size_   : 30; // size of the clause
00079                 uint32  inQ_    : 1;  // in todo-queue?
00080                 uint32  marked_ : 1;  // a marker flag
00081                 Literal lits_[1];     // literals of the clause: [lits_[0], lits_[size_])
00082         };
00083         
00084         SatPreprocessor() : ctx_(0), elimTop_(0), seen_(1,1) {}
00085         virtual ~SatPreprocessor();
00086 
00088 
00091         virtual SatPreprocessor* clone() = 0;
00092 
00093         uint32 numClauses() const { return (uint32)clauses_.size(); }
00095 
00100         bool addClause(const LitVec& cl) { return addClause(!cl.empty() ? &cl[0] : 0, cl.size()); }
00101         bool addClause(const Literal* clause, uint32 size);
00103 
00106         bool preprocess(SharedContext& ctx, SatPreParams& opts);
00107         bool preprocess(SharedContext& ctx);
00108 
00110         void cleanUp(bool discardEliminated = false);
00111 
00113         void extendModel(ValueVec& m, LitVec& open);
00114         struct Stats {
00115                 Stats() : clRemoved(0), clAdded(0), litsRemoved(0) {}
00116                 uint32 clRemoved;
00117                 uint32 clAdded;
00118                 uint32 litsRemoved;
00119         } stats;
00120         typedef SatPreParams Options;
00121 protected:
00122         typedef PodVector<Clause*>::type  ClauseList;
00123         virtual bool  initPreprocess(SatPreParams& opts) = 0;
00124         virtual bool  doPreprocess() = 0;
00125         virtual void  doExtendModel(ValueVec& m, LitVec& open) = 0;
00126         virtual void  doCleanUp() = 0;
00127         Clause*       clause(uint32 clId)       { return clauses_[clId]; }
00128         const Clause* clause(uint32 clId) const { return clauses_[clId]; }
00129         void          freezeSeen();
00130         void          discardClauses(bool discardEliminated);
00131         void          setClause(uint32 clId, const LitVec& cl) {
00132                 clauses_[clId] = Clause::newClause(&cl[0], (uint32)cl.size());
00133         }
00134         void          destroyClause(uint32 clId){
00135                 clauses_[clId]->destroy();
00136                 clauses_[clId] = 0;
00137                 ++stats.clRemoved;
00138         }
00139         void          eliminateClause(uint32 id){
00140                 elimTop_     = clauses_[id]->linkRemoved(elimTop_);
00141                 clauses_[id] = 0;
00142                 ++stats.clRemoved;
00143         }
00144         SharedContext*  ctx_;     // current context
00145         Clause*         elimTop_; // stack of blocked/eliminated clauses
00146 private:
00147         SatPreprocessor(const SatPreprocessor&);
00148         SatPreprocessor& operator=(const SatPreprocessor&);
00149         ClauseList clauses_; // initial non-unit clauses
00150         LitVec     units_;   // initial unit clauses
00151         Range32    seen_;    // vars seen in previous step
00152 };
00154 
00159 
00161 // Problem statistics
00164 
00167 struct ProblemStats {
00168         ProblemStats() { reset(); }
00169         uint32  vars;
00170         uint32  vars_eliminated;
00171         uint32  vars_frozen;
00172         uint32  constraints;
00173         uint32  constraints_binary;
00174         uint32  constraints_ternary;
00175         uint32  complexity;
00176         void    reset() { std::memset(this, 0, sizeof(*this)); }
00177         uint32  numConstraints() const   { return constraints + constraints_binary + constraints_ternary; }
00178         void diff(const ProblemStats& o) {
00179                 vars               = std::max(vars, o.vars)-std::min(vars, o.vars);
00180                 vars_eliminated    = std::max(vars_eliminated, o.vars_eliminated)-std::min(vars_eliminated, o.vars_eliminated);
00181                 vars_frozen        = std::max(vars_frozen, o.vars_frozen)-std::min(vars_frozen, o.vars_frozen);
00182                 constraints        = std::max(constraints, o.constraints) - std::min(constraints, o.constraints);
00183                 constraints_binary = std::max(constraints_binary, o.constraints_binary) - std::min(constraints_binary, o.constraints_binary);
00184                 constraints_ternary= std::max(constraints_ternary, o.constraints_ternary) - std::min(constraints_ternary, o.constraints_ternary);
00185         }
00186         double operator[](const char* key) const;
00187         static const char* keys(const char* = 0);
00188 };
00189 
00191 struct VarInfo {
00192         enum FLAG {
00193                 MARK_P = 0x1u, // mark for positive literal
00194                 MARK_N = 0x2u, // mark for negative literal
00195                 NANT   = 0x4u, // var in NAnt(P)?
00196                 PROJECT= 0x8u, // do we project on this var?
00197                 BODY   = 0x10u,// is this var representing a body?
00198                 EQ     = 0x20u,// is the var representing both a body and an atom?
00199                 DISJ   = 0x40u,// in non-hcf disjunction?
00200                 FROZEN = 0x80u // is the variable frozen?
00201         };
00202         VarInfo() : rep(0) {}
00203 
00205         VarType type()          const { return has(VarInfo::EQ) ? Var_t::atom_body_var : VarType(Var_t::atom_var + has(VarInfo::BODY)); }
00207         bool    nant()          const { return has(VarInfo::NANT); }
00209         bool    project()       const { return has(VarInfo::PROJECT);}
00210         bool    inDisj()        const { return has(VarInfo::DISJ);}
00212         bool    frozen()        const { return has(VarInfo::FROZEN); }
00214 
00217         bool    preferredSign() const { return !has(VarInfo::BODY); }
00218         
00219         bool    has(FLAG f)     const { return (rep & flag(f)) != 0; }
00220         bool    has(uint32 f)   const { return (rep & f) != 0;       }
00221         void    set(FLAG f)           { rep |= flag(f); }
00222         void    toggle(FLAG f)        { rep ^= flag(f); }
00223         static uint8 flag(FLAG x)     { return uint8(x); }
00224         uint8 rep;
00225 };
00226 
00228 class ShortImplicationsGraph {
00229 public:
00230         ShortImplicationsGraph();
00231         ~ShortImplicationsGraph();
00232         enum ImpType { binary_imp = 2, ternary_imp = 3 };
00233         
00235         void resize(uint32 nodes);
00237 
00241         void markShared(bool b) { shared_ = b; }
00243 
00246         bool add(ImpType t, bool learnt, const Literal* lits);
00247         
00249 
00252         void removeTrue(const Solver& s, Literal p);
00253         
00255 
00258         bool   propagate(Solver& s, Literal p) const;
00260         bool   propagateBin(Assignment& out, Literal p, uint32 dl) const;
00262         bool   reverseArc(const Solver& s, Literal p, uint32 maxLev, Antecedent& out) const;
00263         
00264         uint32 numBinary() const { return bin_[0]; }
00265         uint32 numTernary()const { return tern_[0]; }
00266         uint32 numLearnt() const { return bin_[1] + tern_[1]; }
00267         uint32 numEdges(Literal p) const;
00268         uint32 size() const      { return graph_.size(); }
00270 
00278         template <class OP>
00279         bool forEach(Literal p, const OP& op) const {
00280                 const ImplicationList& x = graph_[p.index()];
00281                 if (x.empty()) return true;
00282                 ImplicationList::const_right_iterator rEnd = x.right_end(); // prefetch
00283                 for (ImplicationList::const_left_iterator it = x.left_begin(), end = x.left_end(); it != end; ++it) {
00284                         if (!op.unary(p, *it)) { return false; }
00285                 }
00286                 for (ImplicationList::const_right_iterator it = x.right_begin(); it != rEnd; ++it) {
00287                         if (!op.binary(p, it->first, it->second)) { return false; }
00288                 }
00289 #if WITH_THREADS
00290                 for (Block* b = (x).learnt; b ; b = b->next) {
00291                         p.watch(); bool r = true;
00292                         for (Block::const_iterator imp = b->begin(), endOf = b->end(); imp != endOf; ) {
00293                                 if (!imp->watched()) { r = op.binary(p, imp[0], imp[1]); imp += 2; }
00294                                 else                 { r = op.unary(p, imp[0]);          imp += 1; }
00295                                 if (!r)              { return false; }
00296                         }
00297                 }
00298 #endif
00299                 return true;
00300         }
00301 private:
00302         ShortImplicationsGraph(const ShortImplicationsGraph&);
00303         ShortImplicationsGraph& operator=(ShortImplicationsGraph&);
00304         struct Propagate;
00305         struct ReverseArc;
00306 #if WITH_THREADS
00307         struct Block {
00308                 typedef Clasp::atomic<uint32> atomic_size;
00309                 typedef Clasp::atomic<Block*> atomic_ptr;
00310                 typedef const Literal*      const_iterator;
00311                 typedef       Literal*      iterator;
00312                 enum { block_cap = (64 - (sizeof(atomic_size)+sizeof(atomic_ptr)))/sizeof(Literal) };
00313                 explicit Block();
00314                 const_iterator  begin() const { return data; }
00315                 const_iterator  end()   const { return data+size(); }
00316                 iterator        end()         { return data+size(); }
00317                 uint32          size()  const { return size_lock >> 1; }
00318                 bool tryLock(uint32& lockedSize);
00319                 void addUnlock(uint32 lockedSize, const Literal* x, uint32 xs);
00320                 atomic_ptr  next;
00321                 atomic_size size_lock;
00322                 Literal     data[block_cap];
00323         };
00324         typedef Block::atomic_ptr SharedBlockPtr;
00325         typedef bk_lib::left_right_sequence<Literal, std::pair<Literal,Literal>, 64-sizeof(SharedBlockPtr)> ImpListBase;
00326         struct ImplicationList : public ImpListBase {
00327                 ImplicationList() : ImpListBase() { learnt = 0; }
00328                 ImplicationList(const ImplicationList& other) : ImpListBase(other), learnt(other.learnt) {}
00329                 ~ImplicationList();
00330                 bool hasLearnt(Literal q, Literal r = negLit(0)) const;
00331                 void addLearnt(Literal q, Literal r = negLit(0));
00332                 void simplifyLearnt(const Solver& s);
00333                 bool empty() const { return ImpListBase::empty() && learnt == 0; }
00334                 void move(ImplicationList& other);
00335                 void clear(bool b);
00336                 SharedBlockPtr learnt; 
00337         };
00338 #else
00339         typedef bk_lib::left_right_sequence<Literal, std::pair<Literal,Literal>, 64> ImplicationList;
00340 #endif
00341         ImplicationList& getList(Literal p) { return graph_[p.index()]; }
00342         void remove_bin(ImplicationList& w, Literal p);
00343         void remove_tern(ImplicationList& w, Literal p);
00344         typedef PodVector<ImplicationList>::type ImpLists;
00345         ImpLists   graph_;     // one implication list for each literal
00346         uint32     bin_[2];    // number of binary constraints (0: problem / 1: learnt)
00347         uint32     tern_[2];   // number of ternary constraints(0: problem / 1: learnt)
00348         bool       shared_;
00349 };
00350 
00352 class Distributor {
00353 public:
00354         struct Policy {
00355                 enum Types { 
00356                         no       = 0,
00357                         conflict = Constraint_t::learnt_conflict,
00358                         loop     = Constraint_t::learnt_loop,
00359                         all      = conflict | loop,
00360                         implicit = all + 1
00361                 };
00362                 Policy(uint32 a_sz = 0, uint32 a_lbd = 0, uint32 a_type = 0) : size(a_sz), lbd(a_lbd), types(a_type) {}
00363                 uint32 size  : 22; 
00364                 uint32 lbd   :  7; 
00365                 uint32 types :  3; 
00366         };
00367         static  uint64  mask(uint32 i)             { return uint64(1) << i; }
00368         static  uint32  initSet(uint32 sz)         { return (uint64(1) << sz) - 1; }
00369         static  bool    inSet(uint64 s, uint32 id) { return (s & mask(id)) != 0; }
00370         explicit Distributor(const Policy& p);
00371         virtual ~Distributor();
00372         bool            isCandidate(uint32 size, uint32 lbd, uint32 type) const {
00373                 return size <= policy_.size && lbd <= policy_.lbd && ((type & policy_.types) != 0);
00374         }
00375         virtual void    publish(const Solver& source, SharedLiterals* lits) = 0;
00376         virtual uint32  receive(const Solver& in, SharedLiterals** out, uint32 maxOut) = 0;
00377 private:
00378         Distributor(const Distributor&);
00379         Distributor& operator=(const Distributor&);
00380         Policy policy_;
00381 };
00382 
00384 
00396 class SharedContext {
00397 public:
00398         typedef SharedDependencyGraph SDG;
00399         typedef PodVector<Solver*>::type       SolverVec;
00400         typedef SingleOwnerPtr<SDG>            SccGraph;
00401         typedef Configuration*                 ConfigPtr;
00402         typedef SingleOwnerPtr<Distributor>    DistrPtr;
00403         typedef const ProblemStats&            StatsRef;
00404         typedef SymbolTable&                   SymbolsRef;
00405         typedef LitVec::size_type              size_type;
00406         typedef ShortImplicationsGraph         ImpGraph;
00407         typedef const ImpGraph&                ImpGraphRef;
00408         typedef EventHandler*                  LogPtr;
00409         typedef SingleOwnerPtr<SatPreprocessor>SatPrePtr;
00410         enum InitMode   { init_share_symbols, init_copy_symbols };
00415 
00416         explicit SharedContext();
00417         ~SharedContext();
00419         void       reset();
00421         void       setEventHandler(EventHandler* r) { progress_ = r; }
00423         void       setShareMode(ContextParams::ShareMode m);
00425         void       setShortMode(ContextParams::ShortMode m);
00427         void       setConcurrency(uint32 numSolver);
00429         Solver&    addSolver();
00431 
00439         void       enableStats(uint32 level);
00440         void       accuStats();
00442         void       setPreserveModels(bool b = true) { share_.satPreM = b ? SatPreParams::prepro_preserve_models : SatPreParams::prepro_preserve_sat; }
00444 
00447         void       setConfiguration(Configuration* c, bool own);
00448         SatPrePtr  satPrepro;  
00449         SccGraph   sccGraph;   
00451 
00452         ConfigPtr  configuration()      const { return config_.get(); }
00454         LogPtr     eventHandler()       const { return progress_; }
00456         bool       seedSolvers()        const { return share_.seed != 0; }
00458         uint32     concurrency()        const { return share_.count; }
00459         bool       preserveModels()     const { return static_cast<SatPreParams::Mode>(share_.satPreM) == SatPreParams::prepro_preserve_models; }
00461         bool       physicalShare(ConstraintType t) const { return (share_.shareM & (1 + (t != Constraint_t::static_constraint))) != 0; }
00463         bool       physicalShareProblem()          const { return (share_.shareM & ContextParams::share_problem) != 0; }
00465         bool       allowImplicit(ConstraintType t) const { return t != Constraint_t::static_constraint ? share_.shortM != ContextParams::short_explicit : !isShared(); }
00467 
00473 
00474         bool       ok()                 const;
00476         bool       frozen()             const { return share_.frozen;}
00478         bool       isShared()           const { return frozen() && concurrency() > 1; } 
00479         bool       isExtended()         const { return problem_.vars_frozen || symbolTable().type() == SymbolTable::map_indirect; }
00481         bool       hasSolver(uint32 id) const { return id < solvers_.size(); }
00483         Solver*    master()             const { return solver(0);    }  
00485         Solver*    solver(uint32 id)    const { return solvers_[id]; }
00486         
00488 
00496         uint32     numVars()            const { return static_cast<uint32>(varInfo_.size() - 1); }
00498         uint32     numEliminatedVars()  const { return problem_.vars_eliminated; }
00500 
00504         bool       validVar(Var var)    const { return var < static_cast<uint32>(varInfo_.size()); }
00506         VarInfo    varInfo(Var v)       const { assert(validVar(v)); return varInfo_[v]; }
00508         bool       eliminated(Var v)    const;
00509         bool       marked(Literal p)    const { return varInfo(p.var()).has(VarInfo::MARK_P + p.sign()); }
00510         Literal    stepLiteral()        const { return step_; }
00512         uint32     numConstraints()     const;
00514         uint32     numBinary()          const { return btig_.numBinary();  }
00516         uint32     numTernary()         const { return btig_.numTernary(); }
00518         uint32     numUnary()           const { return lastTopLevel_; }
00520         uint32     problemComplexity()  const;
00521         StatsRef   stats()              const { return problem_; }
00522         SymbolsRef symbolTable()        const { return symTabPtr_->symTab; }
00524 
00543 
00544 
00550         bool    unfreeze();
00552         void    cloneVars(const SharedContext& other, InitMode m = init_copy_symbols);
00554         void    resizeVars(uint32 maxVar) { varInfo_.resize(std::max(Var(1), maxVar)); problem_.vars = numVars(); }
00556 
00563         Var     addVar(VarType t, bool eq = false);
00565         void    requestStepVar();
00567         void    requestData(Var v);
00569         void    setFrozen(Var v, bool b);
00571         void    setNant(Var v, bool b)       { if (b != varInfo(v).has(VarInfo::NANT))    varInfo_[v].toggle(VarInfo::NANT);    }
00573         void    setInDisj(Var v, bool b)     { if (b != varInfo(v).has(VarInfo::DISJ))    varInfo_[v].toggle(VarInfo::DISJ);    }
00575         void    setProject(Var v, bool b)    { if (b != varInfo(v).has(VarInfo::PROJECT)) varInfo_[v].toggle(VarInfo::PROJECT); }
00576         void    setVarEq(Var v, bool b)      { if (b != varInfo(v).has(VarInfo::EQ))      varInfo_[v].toggle(VarInfo::EQ);      }
00577         void    mark(Literal p)              { assert(validVar(p.var())); varInfo_[p.var()].rep |= (VarInfo::MARK_P + p.sign()); }
00578         void    unmark(Var v)                { assert(validVar(v)); varInfo_[v].rep &= ~(VarInfo::MARK_P|VarInfo::MARK_N); }
00580 
00583         void    eliminate(Var v);
00584 
00586 
00591         Solver& startAddConstraints(uint32 constraintGuess = 100);
00592         
00594         bool    addUnary(Literal x);
00596         bool    addBinary(Literal x, Literal y);
00598         bool    addTernary(Literal x, Literal y, Literal z);
00600         void    add(Constraint* c);
00601 
00603 
00614         bool    endInit(bool attachAll = false);
00616         
00625 
00626 
00632         bool     attach(uint32 id) { return attach(*solver(id)); }
00633         bool     attach(Solver& s);
00634         
00635         
00637 
00644         void     detach(uint32 id, bool reset = false) { return detach(*solver(id), reset); }
00645         void     detach(Solver& s, bool reset = false);
00646         
00647         DistrPtr distributor;
00649         uint32   winner()             const   { return share_.winner; }
00650         void     setWinner(uint32 sId)        { share_.winner = std::min(sId, concurrency()); }
00651         
00653         void     simplify(bool shuffle);
00655         void     removeConstraint(uint32 idx, bool detach);
00656         
00658 
00664         int         addImp(ImpGraph::ImpType t, const Literal* lits, ConstraintType ct);
00666         uint32      numLearntShort()     const { return btig_.numLearnt(); }
00667         ImpGraphRef shortImplications()  const { return btig_; }
00668         void        simplifyShort(const Solver& s, Literal p);
00669         void               report(const Event& ev)                 const { if (progress_) progress_->dispatch(ev);  }
00670         bool               report(const Solver& s, const Model& m) const { return !progress_ || progress_->onModel(s, m); }
00671         void               initStats(Solver& s)                    const;
00672         const SolverStats& stats(const Solver& s, bool accu)       const;
00674 private:
00675         SharedContext(const SharedContext&);
00676         SharedContext& operator=(const SharedContext&);
00677         void    init();
00678         bool    unfreezeStep();
00679         Literal addAuxLit();
00680         typedef SingleOwnerPtr<Configuration> Config;
00681         typedef PodVector<VarInfo>::type      VarVec;
00682         typedef PodVector<SolverStats*>::type StatsVec;
00683         struct SharedSymTab {
00684                 SharedSymTab() : refs(1) {}
00685                 SymbolTable symTab;
00686                 uint32      refs;
00687         }*           symTabPtr_;     // pointer to shared symbol table
00688         ProblemStats   problem_;     // problem statistics
00689         VarVec         varInfo_;     // varInfo[v] stores info about variable v
00690         ImpGraph       btig_;        // binary-/ternary implication graph
00691         Config         config_;      // active configuration
00692         SolverVec      solvers_;     // solvers associated with this context
00693         LogPtr         progress_;    // event handler or 0 if not used
00694         Literal        step_;        // literal for tagging enumeration/step constraints
00695         uint32         lastTopLevel_;// size of master's top-level after last init
00696         struct Share {               // Additional data
00697                 uint32 count   :12;        //   max number of objects sharing this object
00698                 uint32 winner  :12;        //   id of solver that terminated the search
00699                 uint32 shareM  : 3;        //   physical sharing mode
00700                 uint32 shortM  : 1;        //   short clause mode
00701                 uint32 frozen  : 1;        //   is adding of problem constraints allowed?
00702                 uint32 seed    : 1;        //   set seed of new solvers
00703                 uint32 satPreM : 1;        //   preprocessing mode
00704                 Share() : count(1), winner(0), shareM((uint32)ContextParams::share_auto), shortM(0), frozen(0), seed(0), satPreM(0) {}
00705         }              share_;
00706         StatsVec       accu_;        // optional stats accumulator for incremental solving
00707 };
00709 }
00710 #endif


clasp
Author(s): Benjamin Kaufmann
autogenerated on Thu Aug 27 2015 12:41:39