dependency_graph.cpp
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 #ifdef _MSC_VER
00021 #pragma warning(disable : 4996) // std::copy was declared deprecated
00022 #endif
00023 
00024 #include <clasp/dependency_graph.h>
00025 #include <clasp/solver.h>
00026 #include <clasp/clause.h>
00027 #include <clasp/solve_algorithms.h>
00028 #include <clasp/util/timer.h>
00029 namespace Clasp {
00030 
00032 // class SharedDependencyGraph
00034 SharedDependencyGraph::SharedDependencyGraph(Configuration* cfg) : config_(cfg) {
00035         // add sentinal atom needed for disjunctions
00036         createAtom(negLit(0), PrgNode::noScc);
00037         VarVec adj;     adj.push_back(idMax);
00038         initAtom(sentinel_atom, 0, adj, 0);
00039 }
00040 
00041 SharedDependencyGraph::~SharedDependencyGraph() {
00042         for (AtomVec::size_type i = 0; i != atoms_.size(); ++i) {
00043                 delete [] atoms_[i].adj_;
00044         }
00045         for (AtomVec::size_type i = 0; i != bodies_.size(); ++i) {
00046                 delete [] bodies_[i].adj_;
00047         }
00048         while (!components_.empty()) {
00049                 delete components_.back().second;
00050                 components_.pop_back();
00051         }
00052 }
00053 
00054 bool SharedDependencyGraph::relevantPrgAtom(const Solver& s, PrgAtom* a) const { 
00055         return a->inUpper() && a->scc() != PrgNode::noScc && !s.isFalse(a->literal());
00056 }
00057 bool SharedDependencyGraph::relevantPrgBody(const Solver& s, PrgBody* b) const { 
00058         return !s.isFalse(b->literal()); 
00059 }
00060 
00061 // Creates a positive-body-atom-dependency graph (PBADG)
00062 // The PBADG contains a node for each atom A of a non-trivial SCC and
00063 // a node for each body B, s.th. there is a non-trivially connected atom A with
00064 // B in body(A).
00065 // Pre : b->seen() = 1 for all new and relevant bodies b
00066 // Post: b->seen() = 0 for all bodies that were added to the PBADG
00067 void SharedDependencyGraph::addSccs(LogicProgram& prg, const AtomList& sccAtoms, const NonHcfSet& nonHcfs) {
00068         // Pass 1: Create graph atom nodes and estimate number of bodies
00069         atoms_.reserve(atoms_.size() + sccAtoms.size());
00070         AtomList::size_type numBodies = 0;
00071         SharedContext& ctx = *prg.ctx();
00072         for (AtomList::size_type i = 0, end = sccAtoms.size(); i != end; ++i) {
00073                 PrgAtom* a = sccAtoms[i];
00074                 if (relevantPrgAtom(*ctx.master(), a)) {
00075                         // add graph atom node and store link between program node and graph node for later lookup
00076                         a->resetId(createAtom(a->literal(), a->scc()), true);
00077                         // atom is defined by more than just a bunch of clauses
00078                         ctx.setFrozen(a->var(), true);
00079                         numBodies += a->supports();
00080                 }
00081         }
00082         // Pass 2: Init atom nodes and create body nodes
00083         VarVec adj, ext;
00084         bodies_.reserve(bodies_.size() + numBodies/2);
00085         PrgBody* prgBody; PrgDisj* prgDis;
00086         for (AtomList::size_type i = 0, end = sccAtoms.size(); i != end; ++i) {
00087                 PrgAtom*   a  = sccAtoms[i];
00088                 if (relevantPrgAtom(*ctx.master(), a)) { 
00089                         uint32 prop = 0;
00090                         for (PrgAtom::sup_iterator it = a->supps_begin(), endIt = a->supps_end(); it != endIt; ++it) {
00091                                 assert(it->isBody() || it->isDisj());
00092                                 NodeId bId= PrgNode::maxVertex;
00093                                 if (it->isBody() && !it->isGamma()) {
00094                                         prgBody = prg.getBody(it->node());
00095                                         bId     = relevantPrgBody(*ctx.master(), prgBody) ? addBody(prg, prgBody) : PrgNode::maxVertex;
00096                                 }
00097                                 else if (it->isDisj()) {
00098                                         prgDis  = prg.getDisj(it->node());
00099                                         bId     = addDisj(prg, prgDis);
00100                                         prop   |= AtomNode::property_in_disj;
00101                                         ctx.setInDisj(a->var(), true);
00102                                 }
00103                                 if (bId != PrgNode::maxVertex) {
00104                                         if (!bodies_[bId].seen()) {
00105                                                 bodies_[bId].seen(true);
00106                                                 adj.push_back(bId);
00107                                         }
00108                                         if (it->isChoice()) {
00109                                                 // mark atom as in choice
00110                                                 prop |= AtomNode::property_in_choice;
00111                                         }
00112                                 }
00113                         }
00114                         uint32 nPred= (uint32)adj.size();
00115                         for (PrgAtom::dep_iterator it = a->deps_begin(), endIt = a->deps_end(); it != endIt; ++it) {
00116                                 if (!it->sign()) {
00117                                         PrgBody* prgBody = prg.getBody(it->var());
00118                                         if (relevantPrgBody(*ctx.master(), prgBody) && prgBody->scc(prg) == a->scc()) {
00119                                                 NodeId bodyId = addBody(prg, prgBody);
00120                                                 if (!bodies_[bodyId].extended()) {
00121                                                         adj.push_back(bodyId);
00122                                                 }
00123                                                 else {
00124                                                         ext.push_back(bodyId);
00125                                                         ext.push_back(bodies_[bodyId].get_pred_idx(a->id()));
00126                                                         assert(bodies_[bodyId].get_pred(ext.back()) == a->id());
00127                                                         prop |= AtomNode::property_in_ext;
00128                                                 }
00129                                         }
00130                                 }
00131                         }
00132                         if (!ext.empty()) {
00133                                 adj.push_back(idMax);
00134                                 adj.insert(adj.end(), ext.begin(), ext.end());
00135                         }
00136                         adj.push_back(idMax);
00137                         initAtom(a->id(), prop, adj, nPred);
00138                         adj.clear(); ext.clear();
00139                 }
00140         }       
00141         // "update" existing non-hcf components
00142         for (NonHcfIter it = nonHcfBegin(), end = nonHcfEnd(); it != end; ++it) {
00143                 it->second->update(ctx);
00144         }
00145         // add new non-hcf components
00146         for (NonHcfSet::const_iterator it = nonHcfs.begin() + components_.size(), end = nonHcfs.end(); it != end; ++it) {
00147                 addNonHcf(ctx, *it);
00148         }
00149 }
00150 
00151 uint32 SharedDependencyGraph::createAtom(Literal lit, uint32 aScc) {
00152         NodeId id    = (uint32)atoms_.size();
00153         atoms_.push_back(AtomNode());
00154         AtomNode& ua = atoms_.back();
00155         ua.lit       = lit;
00156         ua.scc       = aScc;
00157         return id;
00158 }
00159 
00160 void SharedDependencyGraph::initAtom(uint32 id, uint32 prop, const VarVec& adj, uint32 numPreds) {
00161         AtomNode& ua = atoms_[id];
00162         ua.setProperties(prop);
00163         ua.adj_      = new NodeId[adj.size()];
00164         ua.sep_      = ua.adj_ + numPreds;
00165         NodeId* sExt = ua.adj_;
00166         NodeId* sSame= sExt + numPreds;
00167         uint32  aScc = ua.scc;
00168         for (VarVec::const_iterator it = adj.begin(), end = adj.begin()+numPreds; it != end; ++it) {
00169                 BodyNode& bn = bodies_[*it];
00170                 if (bn.scc != aScc) { *sExt++ = *it; }
00171                 else                { *--sSame= *it; }
00172                 bn.seen(false);
00173         }
00174         std::reverse(sSame, ua.adj_ + numPreds);
00175         std::copy(adj.begin()+numPreds, adj.end(), ua.sep_);
00176 }
00177 
00178 uint32 SharedDependencyGraph::createBody(PrgBody* b, uint32 bScc) {
00179         NodeId id = (uint32)bodies_.size();
00180         bodies_.push_back(BodyNode(b, bScc));
00181         return id;
00182 }
00183 
00184 // Creates and initializes a body node for the given body b.
00185 uint32 SharedDependencyGraph::addBody(const LogicProgram& prg, PrgBody* b) {
00186         if (b->seen()) {     // first time we see this body - 
00187                 VarVec preds, atHeads;
00188                 uint32 bScc  = b->scc(prg);
00189                 NodeId bId   = createBody(b, bScc);
00190                 addPreds(prg, b, bScc, preds);
00191                 addHeads(prg, b, atHeads);
00192                 initBody(bId, preds, atHeads);
00193                 b->resetId(bId, false);
00194                 prg.ctx()->setFrozen(b->var(), true);
00195         }
00196         return b->id();
00197 }
00198 
00199 // Adds all relevant predecessors of b to preds.
00200 // The returned list looks like this:
00201 // [[B], a1, [w1], ..., aj, [wj], idMax, l1, [w1], ..., lk, [wk], idMax], where
00202 // B is the bound of b (only for card/weight rules),
00203 // ai is a positive predecessor from bScc,
00204 // wi is the weight of ai (only for weight rules), and
00205 // li is a literal of a subgoal from some other scc (only for cardinality/weight rules)
00206 void SharedDependencyGraph::addPreds(const LogicProgram& prg, PrgBody* b, uint32 bScc, VarVec& preds) const {
00207         if (bScc == PrgNode::noScc) { preds.clear(); return; }
00208         const bool weights = b->type() == Asp::BodyInfo::SUM_BODY;
00209         for (uint32 i = 0; i != b->size() && !b->goal(i).sign(); ++i) {
00210                 PrgAtom* pred = prg.getAtom(b->goal(i).var());
00211                 if (relevantPrgAtom(*prg.ctx()->master(), pred) && pred->scc() == bScc) {
00212                         preds.push_back( pred->id() );
00213                         if (weights) { preds.push_back(b->weight(i)); }
00214                 }
00215         }
00216         if (b->type() != Asp::BodyInfo::NORMAL_BODY) {
00217                 preds.insert(preds.begin(), b->bound());
00218                 preds.push_back(idMax);
00219                 for (uint32 n = 0; n != b->size(); ++n) {
00220                         PrgAtom* pred = prg.getAtom(b->goal(n).var());
00221                         bool     ext  = b->goal(n).sign() || pred->scc() != bScc;
00222                         Literal lit   = b->goal(n).sign() ? ~pred->literal() : pred->literal();
00223                         if (ext && !prg.ctx()->master()->isFalse(lit)) {
00224                                 preds.push_back(lit.asUint());
00225                                 if (weights) { preds.push_back(b->weight(n)); }
00226                         }
00227                 }
00228         }
00229         preds.push_back(idMax);
00230 }
00231 
00232 // Splits the heads of b into atoms and disjunctions.
00233 // Disjunctions are flattened to sentinel-enclose datom-lists.
00234 uint32 SharedDependencyGraph::addHeads(const LogicProgram& prg, PrgBody* b, VarVec& heads) const {
00235         for (PrgBody::head_iterator it = b->heads_begin(), end = b->heads_end(); it != end; ++it) {
00236                 if (it->isAtom() && !it->isGamma()) {
00237                         PrgAtom* a = prg.getAtom(it->node());
00238                         if (relevantPrgAtom(*prg.ctx()->master(), a)) {
00239                                 heads.push_back(a->id());
00240                         }
00241                 }
00242                 else if (it->isDisj()) {
00243                         assert(prg.getDisj(it->node())->inUpper() && prg.getDisj(it->node())->supports() == 1);
00244                         PrgDisj* d = prg.getDisj(it->node());
00245                         // flatten disjunction and enclose in sentinels
00246                         heads.push_back(sentinel_atom);
00247                         getAtoms(prg, d, heads);
00248                         heads.push_back(sentinel_atom);
00249                 }
00250         }
00251         return heads.size();
00252 }
00253 
00254 // Adds the atoms from the given disjunction to atoms and returns the disjunction's scc.
00255 uint32 SharedDependencyGraph::getAtoms(const LogicProgram& prg, PrgDisj* d, VarVec& atoms) const {
00256         uint32 scc = PrgNode::noScc;
00257         for (PrgDisj::atom_iterator it = d->begin(), end = d->end(); it != end; ++it) {
00258                 PrgAtom* a = prg.getAtom(it->node());
00259                 if (relevantPrgAtom(*prg.ctx()->master(), a)) {
00260                         assert(scc == PrgNode::noScc || scc == a->scc());
00261                         atoms.push_back(a->id());
00262                         scc = a->scc();
00263                 }
00264         }
00265         return scc;
00266 }
00267 
00268 // Initializes preds and succs lists of the body node with the given id.
00269 void SharedDependencyGraph::initBody(uint32 id, const VarVec& preds, const VarVec& atHeads) {
00270         BodyNode* bn = &bodies_[id];
00271         uint32 nSuccs= atHeads.size();
00272         bn->adj_     = new NodeId[nSuccs + preds.size()];
00273         bn->sep_     = bn->adj_ + nSuccs;
00274         NodeId* sSame= bn->adj_;
00275         NodeId* sExt = sSame + nSuccs;
00276         uint32  bScc = bn->scc;
00277         uint32  hScc = PrgNode::noScc;
00278         uint32  disj = 0;
00279         for (VarVec::const_iterator it = atHeads.begin(), end = atHeads.end(); it != end;) {
00280                 if (*it) {
00281                         hScc = getAtom(*it).scc;
00282                         if (hScc == bScc) { *sSame++ = *it++; }
00283                         else              { *--sExt  = *it++; }
00284                 }
00285                 else {
00286                         hScc = getAtom(it[1]).scc; ++disj;
00287                         if (hScc == bScc) { *sSame++ = *it++; while ( (*sSame++ = *it++) ) { ; } }
00288                         else              { *--sExt  = *it++; while ( (*--sExt  = *it++) ) { ; } }
00289                 }
00290         }
00291         std::copy(preds.begin(), preds.end(), bn->sep_);
00292         bn->sep_ += bn->extended();
00293         if (disj) { bodies_[id].data |= BodyNode::flag_has_delta; }
00294 }
00295 
00296 uint32 SharedDependencyGraph::addDisj(const LogicProgram& prg, PrgDisj* d) {
00297         assert(d->inUpper() && d->supports() == 1);
00298         if (d->seen()) { // first time we see this disjunction
00299                 PrgBody* prgBody = prg.getBody(d->supps_begin()->node());
00300                 uint32   bId     = PrgNode::maxVertex;
00301                 if (relevantPrgBody(*prg.ctx()->master(), prgBody)) {
00302                         bId = addBody(prg, prgBody);
00303                 }
00304                 d->resetId(bId, false);
00305         }
00306         return d->id();
00307 }
00308 
00309 void SharedDependencyGraph::addNonHcf(SharedContext& ctx, uint32 scc) {
00310         VarVec sccAtoms, sccBodies;
00311         // get all atoms from scc
00312         for (uint32 i = 0; i != numAtoms(); ++i) {
00313                 if (getAtom(i).scc == scc) { 
00314                         sccAtoms.push_back(i);
00315                         atoms_[i].set(AtomNode::property_in_non_hcf);
00316                 }
00317         }
00318         // get all bodies defining an atom in scc
00319         const Solver& generator = *ctx.master(); (void)generator;
00320         for (uint32 i = 0; i != sccAtoms.size(); ++i) {
00321                 const AtomNode& a = getAtom(sccAtoms[i]);
00322                 for (const NodeId* bodyIt = a.bodies_begin(), *bodyEnd = a.bodies_end(); bodyIt != bodyEnd; ++bodyIt) {
00323                         BodyNode& B = bodies_[*bodyIt];
00324                         if (!B.seen()) {
00325                                 assert(generator.value(B.lit.var()) != value_free || !generator.seen(B.lit));
00326                                 sccBodies.push_back(*bodyIt);
00327                                 B.seen(true);
00328                         }
00329                 }
00330         }
00331         for (uint32 i = 0; i != sccBodies.size(); ++i) { bodies_[sccBodies[i]].seen(false); }
00332         components_.push_back( ComponentPair(scc, new NonHcfComponent(*this, ctx, scc, sccAtoms, sccBodies)) );
00333 }
00334 void SharedDependencyGraph::accuStats() const {
00335         for (NonHcfIter it = nonHcfBegin(), end = nonHcfEnd(); it != end; ++it) {
00336                 it->second->prg_->accuStats();
00337         }
00338 }
00340 // class SharedDependencyGraph::NonHcfComponent::ComponentMap
00342 class SharedDependencyGraph::NonHcfComponent::ComponentMap {
00343 public:
00344         ComponentMap() { static_assert(sizeof(Mapping) == sizeof(uint64), "Invalid padding!"); }
00345         struct Mapping {
00346                 explicit Mapping(NodeId id) : node(id), varOff(0), varUsed(0), isEq(0) { }
00347                 uint32 node;        // node id in dep-graph of generator program P
00348                 uint32 varOff : 30; // var offset in tester solver
00349                 uint32 varUsed:  1; // has var in tester solver?
00350                 uint32 isEq   :  1; // node literal in P is eq to some other node literal in P
00351                 Var     var()       const { return varOff * varUsed; }
00352                 Literal atPos()     const { return posLit(var()); }
00353                 Literal atAux()     const { return posLit(varOff+1); }
00354                 Literal atUnf()     const { return posLit(varOff+2); }
00355                 Literal bodyAux()   const { return posLit(var()); }
00356                 bool operator<(const Mapping& other) const { return node < other.node; }
00357         };
00358         typedef  SharedDependencyGraph       SccGraph;
00359         typedef  PodVector<Mapping>::type    NodeMap;
00360         typedef  NodeMap::iterator           MapIt;
00361         typedef  NodeMap::const_iterator     MapIt_c;
00362         typedef  std::pair<MapIt_c, MapIt_c> MapRange;
00363         void     addVars(Solver& generator, const SccGraph& dep, const VarVec& atoms, const VarVec& bodies, SharedContext& out);
00364         void     addAtomConstraints(SharedContext& out);
00365         void     addBodyConstraints(const Solver& generator, const SccGraph& dep, uint32 scc, SharedContext& out);
00366         void     mapGeneratorAssignment(const Solver& generator, const SccGraph& dep, LitVec& out) const;
00367         void     mapTesterModel(const Solver& tester, VarVec& out) const;
00368         MapRange atoms() const { return MapRange(mapping.begin(), mapping.begin() + numAtoms); }
00369         MapRange bodies()const { return MapRange(mapping.begin() + numAtoms, mapping.end()); }
00370         MapIt_c  findAtom(NodeId nodeId) const { return std::lower_bound(mapping.begin(), mapping.begin()+numAtoms, Mapping(nodeId)); }
00371         NodeMap  mapping; // maps nodes of P to literals in C;
00372         uint32   numAtoms;// number of atoms
00373 };
00374 // Adds necessary variables for all atoms and bodies to the component program.
00375 // Input-Vars: (set via assumptions)
00376 //  a+: for each atom a, a+ is true iff a is true in P
00377 //  B*: for each body B, B* is true iff B is not false in P
00378 // Aux-Var: (derived)
00379 //  a*: for each atom a, a* is true iff not a+ OR au
00380 // Output: (unfounded sets)
00381 //  au: for each atom a, au is true iff a is unfounded w.r.t to assignment of P.
00382 void SharedDependencyGraph::NonHcfComponent::ComponentMap::addVars(Solver& generator, const SccGraph& dep, const VarVec& atoms, const VarVec& bodies, SharedContext& comp) {
00383         mapping.reserve(atoms.size() + bodies.size());
00384         for (VarVec::const_iterator it = atoms.begin(), end = atoms.end(); it != end; ++it) { 
00385                 const AtomNode& at = dep.getAtom(*it);
00386                 Literal gen        = at.lit;
00387                 if (generator.isFalse(gen)) { continue; }
00388                 Mapping map(*it);
00389                 map.varUsed = !generator.isTrue(gen) || generator.level(gen.var()) > 0;
00390                 map.varOff  = map.varUsed ? comp.addVar(Var_t::atom_var) : comp.numVars();
00391                 // add additional vars for au and ax
00392                 comp.addVar(Var_t::atom_var);
00393                 comp.addVar(Var_t::atom_var);
00394                 comp.setFrozen(map.atUnf().var(), true);
00395                 comp.setFrozen(map.atPos().var(), true);
00396                 mapping.push_back(map);
00397         }
00398         numAtoms = (uint32)mapping.size();
00399         std::stable_sort(mapping.begin(), mapping.end());
00400         // add necessary vars for bodies 
00401         for (VarVec::const_iterator it = bodies.begin(), end = bodies.end(); it != end; ++it) {
00402                 Literal gen = dep.getBody(*it).lit;
00403                 if (generator.isFalse(gen))  { continue; }
00404                 Mapping map(*it);
00405                 map.varUsed = !generator.isTrue(gen) || generator.level(gen.var()) > 0;
00406                 if (map.varUsed && !generator.seen(gen)) {
00407                         map.varOff= comp.addVar(Var_t::atom_var);
00408                         generator.markSeen(gen);
00409                 }
00410                 else { // eq to TRUE or existing body
00411                         map.isEq  = 1;
00412                         map.varOff= comp.numVars()+1;
00413                         if (map.varUsed) {
00414                                 for (MapRange r = this->bodies(); r.first != r.second;) {
00415                                         --r.second;
00416                                         if (dep.getBody(r.second->node).lit == gen) {
00417                                                 map.varOff = r.second->varOff;
00418                                                 break;
00419                                         }
00420                                 }
00421                                 assert(map.varOff <= comp.numVars());
00422                         }
00423                 }
00424                 comp.setFrozen(map.bodyAux().var(), true);
00425                 mapping.push_back(map);
00426         }
00427         for (MapRange r = this->bodies(); r.first != r.second; ++r.first) {
00428                 if (!r.first->isEq) {
00429                         Var v = dep.getBody(r.first->node).lit.var();
00430                         generator.clearSeen(v);
00431                 }
00432         }
00433 }
00434 
00435 // Adds constraints stemming from the given atoms to the component program.
00436 // 1. [au(a0) v ... v au(an-1)], where 
00437 //   - ai is an atom in P from the given atom set, and 
00438 //   - au(ai) is the corresponding output-atom in the component program C.
00439 // 2. For each atom ai in atom set, [ax(ai) <=> ~ap(ai) v au(ai)], where
00440 //   ap(ai), ax(ai), au(ai) are the input, aux resp. output atoms in C.
00441 void SharedDependencyGraph::NonHcfComponent::ComponentMap::addAtomConstraints(SharedContext& comp) {
00442         ClauseCreator cc1(comp.master()), cc2(comp.master());
00443         cc1.addDefaultFlags(ClauseCreator::clause_force_simplify);
00444         cc1.start();
00445         for (MapRange r = atoms(); r.first != r.second; ++r.first) {
00446                 const Mapping& m = *r.first;
00447                 cc1.add(m.atUnf());
00448                 cc2.start().add(~m.atPos()).add(m.atUnf()).add(~m.atAux()).end(); // [~a+ v au v ~a*]
00449                 cc2.start().add(m.atAux()).add(m.atPos()).end();  // [a* v a+]
00450                 cc2.start().add(m.atAux()).add(~m.atUnf()).end(); // [a* v ~au]
00451         }
00452         cc1.end();
00453 }
00454 
00455 // Adds constraints stemming from the given bodies to the component program.
00456 // For each atom ai and rule a0 | ai | ...| an :- B, s.th. B in bodies
00457 //  [~au(ai) v ~bc(B) V ~ax(aj), j != i V au(p), p in B+ ^ C], where
00458 // ax(ai), au(ai) is the aux resp. output atom of ai in C.
00459 void SharedDependencyGraph::NonHcfComponent::ComponentMap::addBodyConstraints(const Solver& generator, const SccGraph& dep, uint32 scc, SharedContext& comp) {
00460         ClauseCreator cc(comp.master()); 
00461         cc.addDefaultFlags(ClauseCreator::clause_force_simplify);
00462         ClauseCreator dc(comp.master());
00463         MapIt j = mapping.begin() + numAtoms;
00464         for (MapRange r = bodies(); r.first != r.second; ++r.first) {
00465                 const BodyNode& B = dep.getBody(r.first->node);
00466                 if (generator.isFalse(B.lit)) { continue; }
00467                 if (B.extended())             { throw std::runtime_error("Extended bodies not supported - use '--trans-ext=weight'"); }
00468                 for (const NodeId* hIt = B.heads_begin(), *hEnd = B.heads_end(); hIt != hEnd; ++hIt) {
00469                         uint32 hScc = *hIt ? dep.getAtom(*hIt).scc : dep.getAtom(hIt[1]).scc;
00470                         if (hScc != scc) { 
00471                                 // the head is not relevant to this non-hcf - skip it
00472                                 if (!*hIt) { do { ++hIt; } while (*hIt); }
00473                                 continue;
00474                         }
00475                         // [~B* v ~au V ~o* for all o != a in B.disHead V bu for each b in B+ ^ C]
00476                         cc.start().add(~r.first->bodyAux());
00477                         if (B.scc == scc) { // add subgoals from same scc
00478                                 for (const NodeId* aIt = B.preds(); *aIt != idMax; ++aIt) {
00479                                         MapIt_c atMapped = findAtom(*aIt);
00480                                         cc.add(atMapped->atUnf());
00481                                 }
00482                         }
00483                         if (*hIt) { // normal head
00484                                 MapIt_c atMapped = findAtom(*hIt);
00485                                 assert(atMapped != atoms().second);
00486                                 cc.add(~atMapped->atUnf());
00487                                 cc.end();
00488                         }
00489                         else { // disjunctive head
00490                                 const NodeId* dHead = ++hIt;
00491                                 for (; *hIt; ++hIt) {
00492                                         dc.start();
00493                                         dc = cc;
00494                                         MapIt_c atMapped = findAtom(*hIt);
00495                                         dc.add(~atMapped->atUnf());
00496                                         for (const NodeId* other = dHead; *other; ++other) {
00497                                                 if (*other != *hIt) {
00498                                                         assert(dep.getAtom(*other).scc == scc);
00499                                                         atMapped = findAtom(*other);
00500                                                         dc.add(~atMapped->atAux());
00501                                                 }
00502                                         }
00503                                         dc.end();
00504                                 }
00505                         }
00506                 }
00507                 if (r.first->isEq == 0) { *j++ = *r.first; }
00508         }
00509         mapping.erase(j, mapping.end());
00510 }
00511 
00512 // Maps the generator assignment given in s to a list of tester assumptions.
00513 void SharedDependencyGraph::NonHcfComponent::ComponentMap::mapGeneratorAssignment(const Solver& s, const SccGraph& dep, LitVec& out) const {
00514         Literal  gen;
00515         out.clear(); out.reserve(mapping.size());
00516         for (MapRange r = atoms(); r.first != r.second; ++r.first) {
00517                 const Mapping& at = *r.first;
00518                 assert(at.varUsed || at.atPos() == posLit(0));
00519                 if (at.varUsed) {
00520                         gen = dep.getAtom(at.node).lit;
00521                         out.push_back(at.atPos());
00522                         if (!s.isTrue(gen)) {
00523                                 out.back() = ~at.atPos();
00524                                 if (s.isFalse(gen)) { out.push_back(~at.atUnf()); }
00525                         }
00526                 }
00527         }
00528         for (MapRange r = bodies(); r.first != r.second; ++r.first) {
00529                 gen = dep.getBody(r.first->node).lit;
00530                 out.push_back(!s.isFalse(gen) ? r.first->bodyAux() : ~r.first->bodyAux());
00531         }
00532 }
00533 // Maps the tester model given in s back to a list of unfounded atoms in the generator.
00534 void SharedDependencyGraph::NonHcfComponent::ComponentMap::mapTesterModel(const Solver& s, VarVec& out) const {
00535         assert(s.numFreeVars() == 0);
00536         out.clear();
00537         for (MapRange r = atoms(); r.first != r.second; ++r.first) {
00538                 if (s.isTrue(r.first->atUnf())) {
00539                         out.push_back(r.first->node);
00540                 }
00541         }
00542 }
00544 // class SharedDependencyGraph::NonHcfComponent
00546 SolveTestEvent::SolveTestEvent(const Solver& s, uint32 a_scc, bool part) 
00547         : SolveEvent<SolveTestEvent>(s, Event::verbosity_max)
00548         , result(-1), scc(a_scc), partial(part) {
00549         confDelta   = s.stats.conflicts;
00550         choiceDelta = s.stats.choices;
00551         time        = 0.0;
00552 }
00553 uint64 SolveTestEvent::choices() const {
00554         return solver->stats.choices - choiceDelta;
00555 }
00556 uint64 SolveTestEvent::conflicts() const {
00557         return solver->stats.conflicts - confDelta;
00558 }
00559 
00560 SharedDependencyGraph::NonHcfComponent::NonHcfComponent(const SharedDependencyGraph& dep, SharedContext& genCtx, uint32 scc, const VarVec& atoms, const VarVec& bodies) 
00561         : prg_(new SharedContext())
00562         , comp_(new ComponentMap()){
00563         Solver& generator = *genCtx.master();
00564         prg_->setConcurrency(genCtx.concurrency());
00565         prg_->setConfiguration(dep.nonHcfConfig(), false);
00566         comp_->addVars(generator, dep, atoms, bodies, *prg_);
00567         prg_->startAddConstraints();
00568         comp_->addAtomConstraints(*prg_);
00569         comp_->addBodyConstraints(generator, dep, scc, *prg_);
00570         prg_->enableStats(generator.stats.level());
00571         prg_->endInit(true);
00572 }
00573 
00574 SharedDependencyGraph::NonHcfComponent::~NonHcfComponent() { 
00575         delete prg_;
00576         delete comp_;
00577 }
00578 
00579 void SharedDependencyGraph::NonHcfComponent::update(const SharedContext& generator) {
00580         prg_->enableStats(generator.master()->stats.level());
00581         for (uint32 i = 0; generator.hasSolver(i); ++i) {
00582                 if (!prg_->hasSolver(i)) { prg_->attach(prg_->addSolver());   }
00583                 else                     { prg_->initStats(*prg_->solver(i)); }
00584         }
00585 }
00586 
00587 void SharedDependencyGraph::NonHcfComponent::assumptionsFromAssignment(const Solver& s, LitVec& assume) const {
00588         assert(s.sharedContext()->sccGraph.get() != 0);
00589         comp_->mapGeneratorAssignment(s, *s.sharedContext()->sccGraph, assume);
00590 }
00591 
00592 bool SharedDependencyGraph::NonHcfComponent::test(uint32 scc, const Solver& generator, const LitVec& assume, VarVec& unfoundedOut) const {
00593         assert(generator.id() < prg_->concurrency() && "Invalid id!");
00594         // Forwards to message handler of generator so that messages are 
00595         // handled during long running tests.
00596         struct Tester : MessageHandler {
00597                 Tester(Solver& s, MessageHandler* gen) : solver(&s), generator(gen) { if (gen) { s.addPost(this); } }
00598                 ~Tester() { if (generator) { solver->removePost(this); } }
00599                 bool handleMessages()                            { return generator->handleMessages(); }
00600                 bool propagateFixpoint(Solver&, PostPropagator*) { return Tester::handleMessages() || !terminate(); }
00601                 bool terminate()                                 { solver->setStopConflict(); return true; }
00602                 int test(const LitVec& assume) {
00603                         return int(BasicSolve(*solver).satisfiable(assume, solver->stats.choices == 0) == false);
00604                 }
00605                 Solver*         solver;
00606                 MessageHandler* generator;
00607         } tester(*prg_->solver(generator.id()), static_cast<MessageHandler*>(generator.getPost(PostPropagator::priority_reserved_msg)));
00608         SolveTestEvent ev(*tester.solver, scc, generator.numFreeVars() != 0);
00609         tester.solver->stats.addTest(ev.partial);
00610         generator.sharedContext()->report(ev);
00611         ev.time = ThreadTime::getTime();
00612         if ((ev.result = tester.test(assume)) == 0) {
00613                 tester.solver->stats.addModel(tester.solver->decisionLevel());
00614                 comp_->mapTesterModel(*tester.solver, unfoundedOut); 
00615         }
00616         ev.time = ThreadTime::getTime() - ev.time;
00617         tester.solver->stats.addCpuTime(ev.time);
00618         generator.sharedContext()->report(ev);
00619         return ev.result != 0;
00620 }
00621 }


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