unfounded_check.h
Go to the documentation of this file.
00001 // 
00002 // Copyright (c) 2010, 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 
00021 #ifndef CLASP_UNFOUNDED_CHECK_H_INCLUDED
00022 #define CLASP_UNFOUNDED_CHECK_H_INCLUDED
00023 
00024 #ifdef _MSC_VER
00025 #pragma once
00026 #endif
00027 #include <clasp/solver.h>
00028 #include <clasp/literal.h> 
00029 #include <clasp/dependency_graph.h>
00030 #include <clasp/constraint.h>
00031 namespace Clasp {
00032 class LoopFormula;
00033 
00035 
00048 class DefaultUnfoundedCheck : public PostPropagator {
00049 public:
00050         typedef SharedDependencyGraph DependencyGraph;
00051         typedef DependencyGraph::NodeId    NodeId;
00052         typedef DependencyGraph::BodyNode  BodyNode;
00053         typedef DependencyGraph::AtomNode  AtomNode;
00055         enum ReasonStrategy {
00056                 common_reason,    
00057                 distinct_reason,  
00058                 shared_reason,    
00059                 only_reason,      
00060                 no_reason,        
00061         };
00062         
00063         DefaultUnfoundedCheck();
00064         ~DefaultUnfoundedCheck();
00065 
00066         ReasonStrategy reasonStrategy() const { return strategy_; }
00067         
00068         DependencyGraph* graph() const { return graph_; }
00069         uint32           nodes() const { return static_cast<uint32>(atoms_.size() + bodies_.size()); }
00070 
00071         // base interface
00072         uint32 priority() const { return uint32(priority_reserved_ufs); }
00073         bool   init(Solver&);
00074         void   reset();
00075         bool   propagateFixpoint(Solver& s, PostPropagator* ctx);
00076         bool   isModel(Solver& s);
00077         bool   valid(Solver& s);
00078 private:
00079         DefaultUnfoundedCheck(const DefaultUnfoundedCheck&);
00080         DefaultUnfoundedCheck& operator=(const DefaultUnfoundedCheck&);
00081         enum UfsType {
00082                 ufs_none,
00083                 ufs_poly,
00084                 ufs_non_poly
00085         };
00086         enum WatchType {
00087                 watch_source_false = 0,
00088                 watch_head_false   = 1,
00089                 watch_head_true    = 2,
00090                 watch_subgoal_false= 3,
00091         };
00092         // data for each body
00093         struct BodyData {
00094                 BodyData() : watches(0), picked(0) {}
00095                 uint32 watches : 31; // how many atoms watch this body as source?
00096                 uint32 picked  :  1; // flag used in computeReason()
00097                 uint32 lower_or_ext; // unsourced preds or index of extended body
00098         };
00099         struct BodyPtr {
00100                 BodyPtr(const BodyNode* n, uint32 i) : node(n), id(i) {}
00101                 const BodyNode* node;
00102                 uint32          id;
00103         };
00104         // data for extended bodies
00105         struct ExtData {
00106                 ExtData(weight_t bound, uint32 preds) : lower(bound) {
00107                         for (uint32 i = 0; i != flagSize(preds); ++i) { flags[i] = 0; }
00108                 }
00109                 bool addToWs(uint32 idx, weight_t w) {
00110                         const uint32 fIdx = (idx / 32);
00111                         const uint32 m    = (1u << (idx & 31));
00112                         assert((flags[fIdx] & m) == 0);
00113                         flags[fIdx]      |= m;
00114                         return (lower -= w) <= 0;
00115                 }
00116                 bool inWs(uint32 idx) const {
00117                         const uint32 fIdx = (idx / 32);
00118                         const uint32 m    = (1u << (idx & 31));
00119                         return (flags[fIdx] & m) != 0;
00120                 }
00121                 void removeFromWs(uint32 idx, weight_t w) {
00122                         if (inWs(idx)) {
00123                                 lower += w;
00124                                 flags[(idx / 32)] &= ~(uint32(1) << (idx & 31));
00125                         }
00126                 }
00127                 static   uint32 flagSize(uint32 preds) { return (preds+31)/32; }
00128                 weight_t lower;
00129                 uint32   flags[0];
00130         };
00131         // data for each atom
00132         struct AtomData {
00133                 AtomData() : source(nill_source), todo(0), ufs(0), validS(0) {}
00134                 // returns the body that is currently watched as possible source
00135                 NodeId watch()     const   { return source; }
00136                 // returns true if atom has currently a source, i.e. a body that can still define it
00137                 bool   hasSource() const   { return validS; }
00138                 // mark source as invalid but keep the watch
00139                 void   markSourceInvalid() { validS = 0; }
00140                 // restore validity of source
00141                 void   resurrectSource()   { validS = 1; }
00142                 // sets b as source for this atom
00143                 void   setSource(NodeId b) {
00144                         source = b;
00145                         validS = 1;
00146                 }
00147                 static const uint32 nill_source = (uint32(1) << 29)-1;
00148                 uint32 source : 29; // id of body currently watched as source
00149                 uint32 todo   :  1; // in todo-queue?
00150                 uint32 ufs    :  1; // in ufs-queue?
00151                 uint32 validS :  1; // is source valid?
00152         };
00153         // Watch-structure used to update extended bodies affected by literal assignments
00154         struct ExtWatch {
00155                 NodeId bodyId;
00156                 uint32 data;
00157         };
00158         // Minimality checker for disjunctive logic programs.
00159         struct MinimalityCheck {
00160                 typedef SolveParams::FwdCheck FwdCheck;
00161                 explicit MinimalityCheck(const FwdCheck& fwd);
00162                 bool     partialCheck(uint32 level);
00163                 void     schedNext(uint32 level, bool ok);
00164                 FwdCheck fwd;
00165                 uint32   high;
00166                 uint32   low;
00167                 uint32   next;
00168         };
00169         // -------------------------------------------------------------------------------------------  
00170         // constraint interface
00171         PropResult propagate(Solver&, Literal, uint32& data) {
00172                 uint32 index = data >> 2;
00173                 uint32 type  = (data & 3u);
00174                 if (type != watch_source_false || bodies_[index].watches) {
00175                         invalidQ_.push_back(data);
00176                 }
00177                 return PropResult(true, true);
00178         }
00179         void reason(Solver& s, Literal, LitVec&);
00180         // -------------------------------------------------------------------------------------------
00181         // initialization
00182         BodyPtr getBody(NodeId bId) const { return BodyPtr(&graph_->getBody(bId), bId); }
00183         void    initBody(const BodyPtr& n);
00184         void    initExtBody(const BodyPtr& n);
00185         void    initSuccessors(const BodyPtr& n, weight_t lower);
00186         void    addWatch(Literal, uint32 data, WatchType type);
00187         void    addExtWatch(Literal p, const BodyPtr& n, uint32 data);
00188         struct  InitExtWatches {
00189                 void operator()(Literal p, uint32 idx, bool ext) const { 
00190                         self->addExtWatch(~p, *B, (idx<<1)+ext); 
00191                         if (ext && !self->solver_->isFalse(p)) {
00192                                 extra->addToWs(idx, B->node->pred_weight(idx, true));
00193                         }
00194                 }
00195                 DefaultUnfoundedCheck* self;
00196                 const BodyPtr*         B;
00197                 ExtData*               extra;
00198         };
00199         // -------------------------------------------------------------------------------------------  
00200         // propagating source pointers
00201         void propagateSource();
00202         struct AddSource { // an atom in a body has a new source, check if body is now a valid source
00203                 explicit AddSource(DefaultUnfoundedCheck* u) : self(u) {}
00204                 // normal body
00205                 void operator()(NodeId bId) const {
00206                         BodyPtr n(self->getBody(bId));
00207                         if (--self->bodies_[bId].lower_or_ext == 0 && !self->solver_->isFalse(n.node->lit)) { self->forwardSource(n); }
00208                 }
00209                 // extended body
00210                 void operator()(NodeId bId, uint32 idx) const;
00211                 DefaultUnfoundedCheck* self;
00212         };
00213         struct RemoveSource {// an atom in a body has lost its source, check if body is no longer a valid source 
00214                 explicit RemoveSource(DefaultUnfoundedCheck* u, bool add = false) : self(u), addTodo(add) {}
00215                 // normal body
00216                 void operator()(NodeId bId) const { 
00217                         if (++self->bodies_[bId].lower_or_ext == 1 && self->bodies_[bId].watches != 0) { 
00218                                 self->forwardUnsource(self->getBody(bId), addTodo); 
00219                         }
00220                 }
00221                 // extended body
00222                 void operator()(NodeId bId, uint32 idx) const;
00223                 DefaultUnfoundedCheck* self;
00224                 bool                   addTodo;
00225         };
00226         void setSource(NodeId atom, const BodyPtr& b);
00227         void removeSource(NodeId bodyId);
00228         void forwardSource(const BodyPtr& n);
00229         void forwardUnsource(const BodyPtr& n, bool add);
00230         void updateSource(AtomData& atom, const BodyPtr& n);
00231         // -------------------------------------------------------------------------------------------  
00232         // finding & propagating unfounded sets
00233         void updateAssignment(Solver& s);
00234         bool findSource(NodeId atom);
00235         bool isValidSource(const BodyPtr&);
00236         void addUnsourced(const BodyPtr&);
00237         bool falsifyUfs(UfsType t);
00238         bool assertAtom(Literal a, UfsType t);
00239         void computeReason(UfsType t);
00240         void addIfReason(const BodyPtr&, uint32 uScc);
00241         void addDeltaReason(const BodyPtr& body, uint32 uScc);
00242         void addReasonLit(Literal);
00243         void createLoopFormula();
00244         struct  AddReasonLit {
00245                 void operator()(Literal p, NodeId, bool) const { if (self->solver_->isFalse(p)) self->addReasonLit(p); }
00246                 DefaultUnfoundedCheck* self;
00247         };
00248         UfsType findUfs(Solver& s, bool checkNonHcf);
00249         UfsType findNonHcfUfs(Solver& s);
00250         // -------------------------------------------------------------------------------------------  
00251         bool pushTodo(NodeId at) { return (atoms_[at].todo == 0 && (todo_.push(at), atoms_[at].todo = 1) != 0); }
00252         bool pushUfs(NodeId at)  { return (atoms_[at].ufs  == 0 && (ufs_.push(at),  atoms_[at].ufs  = 1) != 0); }
00253         void resetTodo()         { while (!todo_.empty()){ atoms_[todo_.pop_ret()].todo = 0; } todo_.clear();   }
00254         void resetUfs()          { while (!ufs_.empty()) { atoms_[ufs_.pop_ret()].ufs   = 0; } ufs_.clear();    } 
00255         // -------------------------------------------------------------------------------------------  
00256         typedef PodVector<AtomData>::type       AtomVec;
00257         typedef PodVector<BodyData>::type       BodyVec;
00258         typedef PodVector<ExtData*>::type       ExtVec;
00259         typedef PodVector<ExtWatch>::type       WatchVec;
00260         typedef PodQueue<NodeId>                IdQueue;
00261         typedef SingleOwnerPtr<MinimalityCheck> MiniPtr;
00262         // -------------------------------------------------------------------------------------------  
00263         Solver*          solver_;      // my solver
00264         DependencyGraph* graph_;       // PBADG
00265         MiniPtr          mini_;        // minimality checker (only for DLPs)
00266         AtomVec          atoms_;       // data for each atom       
00267         BodyVec          bodies_;      // data for each body
00268         IdQueue          todo_;        // ids of atoms that recently lost their source
00269         IdQueue          ufs_;         // ids of atoms that are unfounded wrt the current assignment (limited to one scc)
00270         VarVec           invalidQ_;    // ids of invalid elements to be processed
00271         VarVec           sourceQ_;     // source-pointer propagation queue
00272         ExtVec           extended_;    // data for each extended body
00273         WatchVec         watches_;     // watches for handling choice-, cardinality- and weight rules
00274         VarVec           pickedExt_;   // extended bodies visited during reason computation
00275         LitVec           loopAtoms_;   // only used if strategy_ == shared_reason
00276         LitVec           activeClause_;// activeClause_[0] is the current unfounded atom
00277         LitVec*          reasons_;     // only used if strategy_ == only_reason. reasons_[v] reason why v is unfounded
00278         ClauseInfo       info_;        // info on active clause
00279         ReasonStrategy   strategy_;    // what kind of reasons to compute?
00280 };
00281 }
00282 #endif


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