00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00093 struct BodyData {
00094 BodyData() : watches(0), picked(0) {}
00095 uint32 watches : 31;
00096 uint32 picked : 1;
00097 uint32 lower_or_ext;
00098 };
00099 struct BodyPtr {
00100 BodyPtr(const BodyNode* n, uint32 i) : node(n), id(i) {}
00101 const BodyNode* node;
00102 uint32 id;
00103 };
00104
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
00132 struct AtomData {
00133 AtomData() : source(nill_source), todo(0), ufs(0), validS(0) {}
00134
00135 NodeId watch() const { return source; }
00136
00137 bool hasSource() const { return validS; }
00138
00139 void markSourceInvalid() { validS = 0; }
00140
00141 void resurrectSource() { validS = 1; }
00142
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;
00149 uint32 todo : 1;
00150 uint32 ufs : 1;
00151 uint32 validS : 1;
00152 };
00153
00154 struct ExtWatch {
00155 NodeId bodyId;
00156 uint32 data;
00157 };
00158
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
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
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
00201 void propagateSource();
00202 struct AddSource {
00203 explicit AddSource(DefaultUnfoundedCheck* u) : self(u) {}
00204
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
00210 void operator()(NodeId bId, uint32 idx) const;
00211 DefaultUnfoundedCheck* self;
00212 };
00213 struct RemoveSource {
00214 explicit RemoveSource(DefaultUnfoundedCheck* u, bool add = false) : self(u), addTodo(add) {}
00215
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
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
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_;
00264 DependencyGraph* graph_;
00265 MiniPtr mini_;
00266 AtomVec atoms_;
00267 BodyVec bodies_;
00268 IdQueue todo_;
00269 IdQueue ufs_;
00270 VarVec invalidQ_;
00271 VarVec sourceQ_;
00272 ExtVec extended_;
00273 WatchVec watches_;
00274 VarVec pickedExt_;
00275 LitVec loopAtoms_;
00276 LitVec activeClause_;
00277 LitVec* reasons_;
00278 ClauseInfo info_;
00279 ReasonStrategy strategy_;
00280 };
00281 }
00282 #endif