00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef CLASP_LOGIC_PROGRAM_H_INCLUDED
00022 #define CLASP_LOGIC_PROGRAM_H_INCLUDED
00023
00024 #ifdef _MSC_VER
00025 #pragma once
00026 #endif
00027
00028 #include <clasp/logic_program_types.h>
00029 #include <clasp/program_builder.h>
00030 #include <clasp/util/misc_types.h>
00031 #include <map>
00032
00033 namespace Clasp { namespace Asp {
00035 class LpStats {
00036 public:
00037 typedef std::pair<uint32, uint32> RPair;
00038 LpStats() { reset(); }
00039 void reset();
00040 uint32 eqs() const { return eqs(Var_t::atom_var) + eqs(Var_t::body_var) + eqs(Var_t::atom_body_var); }
00041 uint32 eqs(VarType t) const { return eqs_[t-1]; }
00042 uint32 rules() const;
00043 RPair rules(RuleType t) const { return rules_[ruleIndex(t)]; }
00044 RPair& rules(RuleType t) { return rules_[ruleIndex(t)]; }
00045 bool tr() const { return rules_[0].first != rules_[0].second; }
00046 void incEqs(VarType t) { ++eqs_[t-1]; }
00047 void upRule(RuleType t, int32 i) { RPair& x = rules_[ruleIndex(t)]; x.first += i; x.second += i; }
00048 void trRule(RuleType t, uint32 i) { --rules_[ruleIndex(t)].second; rules_[0].first -= i; }
00049 void accu(const LpStats& o);
00050 double operator[](const char* key) const;
00051 static const char* keys(const char* path);
00052 uint32 bodies;
00053 uint32 atoms;
00054 uint32 auxAtoms;
00055 uint32 sccs;
00056 uint32 nonHcfs;
00057 uint32 gammas;
00058 uint32 ufsNodes;
00059 private:
00060 uint32 eqs_[3];
00061 RPair rules_[NUM_RULE_TYPES];
00062 };
00064 class RedefinitionError : public std::logic_error {
00065 public:
00066 explicit RedefinitionError(unsigned atomId, const char* atomName = "");
00067 unsigned atom() const { return atomId_; }
00068 private:
00069 unsigned atomId_;
00070 };
00071
00073
00077 class LogicProgram : public ProgramBuilder {
00078 public:
00079 LogicProgram();
00080 ~LogicProgram();
00082 enum ExtendedRuleMode {
00083 mode_native = 0,
00084 mode_transform = 1,
00085 mode_transform_choice = 2,
00086 mode_transform_card = 3,
00087 mode_transform_weight = 4,
00088 mode_transform_scc = 5,
00089 mode_transform_nhcf = 6,
00090 mode_transform_integ = 7,
00091 mode_transform_dynamic= 8
00092 };
00093
00095 struct AspOptions {
00096 static const uint32 MAX_EQ_ITERS = static_cast<uint32>( (1u<<26)-1 );
00097 AspOptions() : erMode(mode_native), iters(5), noSCC(0), dfOrder(0), backprop(0), normalize(0), suppMod(0), noGamma(0) {}
00098 AspOptions& iterations(uint32 it) { iters = it;return *this;}
00099 AspOptions& depthFirst() { dfOrder = 1; return *this;}
00100 AspOptions& backpropagate() { backprop= 1; return *this;}
00101 AspOptions& noScc() { noSCC = 1; return *this;}
00102 AspOptions& noEq() { iters = 0; return *this;}
00103 AspOptions& disableGamma() { noGamma = 1; return *this;}
00104 AspOptions& ext(ExtendedRuleMode m) { erMode = m; return *this;}
00105 AspOptions& supportedModels() { suppMod = 1; noEq(); return noScc(); }
00106 ExtendedRuleMode erMode;
00107 uint32 iters : 26;
00108 uint32 noSCC : 1;
00109 uint32 dfOrder : 1;
00110 uint32 backprop : 1;
00111 uint32 normalize: 1;
00112 uint32 suppMod : 1;
00113 uint32 noGamma : 1;
00114 };
00119
00121 LogicProgram& start(SharedContext& ctx, const AspOptions& opts = AspOptions()) {
00122 startProgram(ctx);
00123 setOptions(opts);
00124 return *this;
00125 }
00127 void setExtendedRuleMode(ExtendedRuleMode m) { opts_.ext(m); }
00129 void setOptions(const AspOptions& opts);
00131 void setNonHcfConfiguration(Configuration* c){ nonHcfCfg_ = c; }
00132
00134
00148 bool update() { return updateProgram(); }
00149
00151
00165 bool end() { return endProgram(); }
00166
00168 void write(std::ostream& os);
00169
00171
00176 void dispose(bool forceFullDispose);
00177
00179
00180
00181
00182 bool clone(SharedContext& ctx, bool shareSymbols = false);
00183
00185
00195
00197
00200 Var newAtom();
00201
00203
00216 LogicProgram& setAtomName(Var atomId, const char* name);
00217
00219
00226 LogicProgram& setCompute(Var atomId, bool value);
00227
00229
00235 LogicProgram& freeze(Var atomId, ValueRep value = value_false);
00236
00238
00246 LogicProgram& unfreeze(Var atomId);
00247
00249
00263 LogicProgram& addRule(const Rule& r);
00264
00266
00277
00279
00286 LogicProgram& startRule(RuleType t = BASICRULE, weight_t bound = -1) {
00287 rule_.clear();
00288 rule_.setType(t);
00289 if ((t == CONSTRAINTRULE || t == WEIGHTRULE) && bound > 0) {
00290 rule_.setBound(bound);
00291 }
00292 return *this;
00293 }
00294
00296
00300 LogicProgram& setBound(weight_t bound) {
00301 rule_.setBound(bound);
00302 return *this;
00303 }
00304
00306 LogicProgram& addHead(Var atomId) {
00307 assert(atomId > 0);
00308 rule_.addHead(atomId);
00309 return *this;
00310 }
00311
00313
00320 LogicProgram& addToBody(Var atomId, bool pos, weight_t weight = 1) {
00321 rule_.addToBody(atomId, pos, weight);
00322 return *this;
00323 }
00324
00326
00329 LogicProgram& endRule() {
00330 return addRule(rule_);
00331 }
00332
00334
00342
00343 bool hasMinimize() const { return minimize_ != 0; }
00345 uint32 numAtoms() const { return (uint32)atoms_.size()-1; }
00347 uint32 numBodies() const { return (uint32)bodies_.size(); }
00349 uint32 numDisjunctions() const { return (uint32)disjunctions_.size(); }
00351 Var startAtom() const { return incData_?incData_->startAtom:1; }
00353
00360 Literal getLiteral(Var atomId) const;
00361 LpStats stats;
00362 LpStats* accu;
00364
00371 typedef VarVec::const_iterator VarIter;
00372 typedef PrgHead*const* HeadIter;
00373 typedef std::pair<EdgeIterator, EdgeIterator> EdgeRange;
00374 typedef std::pair<HeadIter, HeadIter> HeadRange;
00375 const AspOptions& options() const { return opts_; }
00376 bool hasConflict() const { return getFalseAtom()->literal() == posLit(0); }
00377 bool ok() const { return !hasConflict() && ProgramBuilder::ok(); }
00378 PrgAtom* getAtom(Var atomId) const { return atoms_[atomId]; }
00379 PrgHead* getHead(PrgEdge it) const { return it.isAtom() ? (PrgHead*)getAtom(it.node()) : (PrgHead*)getDisj(it.node()); }
00380 PrgNode* getSupp(PrgEdge it) const { return it.isBody() ? (PrgNode*)getBody(it.node()) : (PrgNode*)getDisj(it.node()); }
00381 Var getEqAtom(Var a) const { return getEqNode(atoms_, a); }
00382 PrgBody* getBody(Var bodyId) const { return bodies_[bodyId]; }
00383 Var getEqBody(Var b) const { return getEqNode(bodies_, b); }
00384 PrgDisj* getDisj(Var disjId) const { return disjunctions_[disjId]; }
00385 bool isFact(PrgAtom* a) const { return a->value() == value_true && opts_.noSCC == false; }
00386 HeadIter disj_begin() const { return disjunctions_.empty() ? 0 : reinterpret_cast<HeadIter>(&disjunctions_[0]); }
00387 HeadIter disj_end() const { return disj_begin() + numDisjunctions(); }
00388 HeadIter atom_begin() const { return reinterpret_cast<HeadIter>(&atoms_[0]); }
00389 HeadIter atom_end() const { return atom_begin() + (numAtoms()+1); }
00390 VarIter unfreeze_begin() const { return incData_?incData_->update.begin() : activeHead_.end(); }
00391 VarIter unfreeze_end() const { return incData_?incData_->update.end() : activeHead_.end(); }
00392 const char*getAtomName(Var id) const;
00393 RuleType simplifyRule(const Rule& r, VarVec& head, BodyInfo& info);
00394 VarVec& getSupportedBodies(bool sorted);
00395 uint32 update(PrgBody* b, uint32 oldHash, uint32 newHash);
00396 bool assignValue(PrgAtom* a, ValueRep v);
00397 bool assignValue(PrgHead* h, ValueRep v);
00398 bool propagate(bool backprop);
00399 PrgAtom* mergeEqAtoms(PrgAtom* a, Var rootAtom);
00400 PrgBody* mergeEqBodies(PrgBody* b, Var rootBody, bool hashEq, bool atomsAssigned);
00401 bool propagate() { return propagate(options().backprop); }
00402 void setConflict() { getFalseAtom()->setLiteral(posLit(0)); }
00403 RuleState& ruleState() { return ruleState_; }
00404 void addMinimize();
00405
00406
00407 void upRules(RuleType r, int i) { stats.upRule(r, i); }
00408 void incTr(RuleType r, uint32 n){ stats.trRule(r, n); }
00409 void incTrAux(uint32 n) { stats.auxAtoms += n; }
00410 void incEqs(VarType t) { stats.incEqs(t); }
00411
00413 private:
00414 LogicProgram(const LogicProgram&);
00415 LogicProgram& operator=(const LogicProgram&);
00416 typedef PodVector<Rule*>::type RuleList;
00417 typedef std::multimap<uint32, uint32> IndexMap;
00418 typedef IndexMap::iterator IndexIter;
00419 typedef std::pair<IndexIter, IndexIter> IndexRange;
00420 typedef PodVector<uint8>::type SccMap;
00421 struct MinimizeRule;
00422
00423
00424 bool doStartProgram();
00425 bool doUpdateProgram();
00426 bool doEndProgram();
00427 void doGetAssumptions(LitVec& out) const;
00428 bool doParse(StreamSource& prg);
00429 int doType() const { return Problem_t::ASP; }
00430
00431
00432 PrgAtom* resize(Var atomId);
00433 void addRuleImpl(RuleType t, const VarVec& head, BodyInfo& body);
00434 bool handleNatively(RuleType t, const BodyInfo& i) const;
00435 bool transformNoAux(RuleType t, const BodyInfo& i) const;
00436 void transformExtended();
00437 void transformIntegrity(uint32 maxAux);
00438 PrgBody* getBodyFor(BodyInfo& body, bool addDeps = true);
00439 PrgDisj* getDisjFor(const VarVec& heads, uint32 headHash);
00440 PrgBody* assignBodyFor(BodyInfo& body, EdgeType x, bool strongSimp);
00441 uint32 findEqBody(PrgBody* b, uint32 hash);
00442 uint32 equalBody(const IndexRange& range, BodyInfo& info) const;
00443 RuleType simplifyBody(const Rule& r, BodyInfo& info);
00444 uint32 removeBody(PrgBody* b, uint32 oldHash);
00445 Literal getEqAtomLit(Literal lit, const BodyList& supports, Preprocessor& p, const SccMap& x);
00446 bool positiveLoopSafe(PrgBody* b, PrgBody* root) const;
00447 void updateFrozenAtoms();
00448 void normalize();
00449 template <class C>
00450 Var getEqNode(C& vec, Var id) const {
00451 if (!vec[id]->eq()) return id;
00452 typedef typename C::value_type NodeType;
00453 NodeType n = vec[id];
00454 NodeType r;
00455 Var root = n->id();
00456 for (r = vec[root]; r->eq(); r = vec[root]) {
00457
00458 n->setEq(root = r->id());
00459 }
00460 return root;
00461 }
00462
00463
00464 void prepareProgram(bool checkSccs);
00465 void finalizeDisjunctions(Preprocessor& p, uint32 numSccs);
00466 void prepareComponents();
00467 void simplifyMinimize();
00468 bool addConstraints();
00469
00470 void writeBody(const BodyInfo& body, std::ostream&) const;
00471 bool transform(const PrgBody& body, BodyInfo& out) const;
00472 void transform(const MinimizeRule&, BodyInfo& out) const;
00473 Var getFalseId() const { return 0; }
00474 PrgAtom* getFalseAtom() const { return atoms_[0]; }
00475 Var findLpFalseAtom() const;
00476 Rule rule_;
00477 BodyInfo activeBody_;
00478 VarVec activeHead_;
00479 RuleState ruleState_;
00480 RuleList extended_;
00481 IndexMap bodyIndex_;
00482 IndexMap disjIndex_;
00483 BodyList bodies_;
00484 AtomList atoms_;
00485 AtomList sccAtoms_;
00486 DisjList disjunctions_;
00487 VarVec initialSupp_;
00488 VarVec propQ_;
00489 NonHcfSet nonHcfs_;
00490 Configuration* nonHcfCfg_;
00491 struct MinimizeRule {
00492 WeightLitVec lits_;
00493 MinimizeRule* next_;
00494 }* minimize_;
00495 struct Incremental {
00496 Incremental();
00497 uint32 startAtom;
00498 uint32 startAux;
00499 uint32 startScc;
00500 VarVec frozen;
00501 VarVec update;
00502 }* incData_;
00503 AspOptions opts_;
00504 };
00505 } }
00506 #endif