dlvhex  2.5.0
src/MLPSolver.cpp
Go to the documentation of this file.
00001 /* dlvhex -- Answer-Set Programming with external interfaces.
00002  * Copyright (C) 2005-2007 Roman Schindlauer
00003  * Copyright (C) 2006-2015 Thomas Krennwallner
00004  * Copyright (C) 2009-2016 Peter Schüller
00005  * Copyright (C) 2011-2016 Christoph Redl
00006  * Copyright (C) 2015-2016 Tobias Kaminski
00007  * Copyright (C) 2015-2016 Antonius Weinzierl
00008  *
00009  * This file is part of dlvhex.
00010  *
00011  * dlvhex is free software; you can redistribute it and/or modify it
00012  * under the terms of the GNU Lesser General Public License as
00013  * published by the Free Software Foundation; either version 2.1 of
00014  * the License, or (at your option) any later version.
00015  *
00016  * dlvhex is distributed in the hope that it will be useful, but
00017  * WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  * Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with dlvhex; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00024  * 02110-1301 USA.
00025  */
00026 
00035 #ifdef HAVE_CONFIG_H
00036 #include "config.h"
00037 #endif                           // HAVE_CONFIG_H
00038 
00039 #ifdef HAVE_MLP
00040 
00041 #include "dlvhex2/MLPSolver.h"
00042 
00043 DLVHEX_NAMESPACE_BEGIN
00044 
00045 MLPSolver::MLPSolver(ProgramCtx& ctx1)
00046 {
00047     printLevel = 0;
00048     nASReturned = 0;
00049     forget = 0;
00050     instSplitting = 0;
00051     totalSizeInstOgatoms=0;
00052     ctx = ctx1;
00053     RegistryPtr R2(new Registry(*ctx.registry()) );
00054     registrySolver = R2;
00055     DBGLOG(DBG, "[MLPSolver::MLPSolver] constructor finished");
00056 }
00057 
00058 
00059 void MLPSolver::dataReset()
00060 {
00061     RegistryPtr R2(new Registry(*ctx.registry() ));
00062     registrySolver = R2;
00063     sTable.clear();
00064     moduleInstTable.clear();
00065     A.clear();
00066     M.reset( new Interpretation( registrySolver ));
00067     path.clear();
00068     totalSizeInstOgatoms = 0;
00069     instOgatoms.clear();
00070 }
00071 
00072 
00073 void MLPSolver::setNASReturned(int n)
00074 {
00075     if ( n>=0 ) {
00076         nASReturned = n;
00077     }
00078 }
00079 
00080 
00081 void MLPSolver::setForget(int n)
00082 {
00083     if ( n==0 || n==1 ) forget = n;
00084 }
00085 
00086 
00087 void MLPSolver::setInstSplitting(int n)
00088 {
00089     if ( n==0 || n==1 ) instSplitting = n;
00090 }
00091 
00092 
00093 void MLPSolver::setPrintLevel(int level)
00094 {
00095     printLevel = level;
00096 }
00097 
00098 
00099 bool MLPSolver::foundCinPath(const ValueCallsType& C, const std::vector<ValueCallsType>& path, ValueCallsType& CPrev, int& PiSResult)
00100 {                                // method to found if there exist a PiS in C that also occur in some Cprev in path
00101     bool result = false;
00102     VCAddressIndex::const_iterator itC = C.get<impl::AddressTag>().begin();
00103     VCAddressIndex::const_iterator itCend = C.get<impl::AddressTag>().end();
00104     // loop over all value calls in C
00105     while ( itC != itCend ) {
00106         // look over all Cprev in path
00107         std::vector<ValueCallsType>::const_iterator itP = path.begin();
00108         std::vector<ValueCallsType>::const_iterator itPend = path.end();
00109         while ( !(itP == itPend) && result == false ) {
00110             ValueCallsType Cprev = *itP;
00111             // *itC contain an index of PiS in moduleInstTable
00112             // now look in the Cprev if there is such PiS
00113             VCElementIndex::const_iterator itCprev = Cprev.get<impl::ElementTag>().find(*itC);
00114             if ( itCprev != Cprev.get<impl::ElementTag>().end() ) {
00115                 CPrev = Cprev;
00116                 PiSResult = *itC;
00117                 result = true;
00118             }
00119             itP++;
00120         }
00121         itC++;
00122     }
00123     return result;
00124 }
00125 
00126 
00127 int MLPSolver::extractS(int PiS)
00128 {
00129     // PiS is an index to moduleInstTable
00130     const ModuleInst& m = moduleInstTable.get<impl::AddressTag>().at(PiS);
00131     return m.idxS;
00132 }
00133 
00134 
00135 int MLPSolver::extractPi(int PiS)
00136 {
00137     // PiS is an index to moduleInstTable
00138     const ModuleInst& m = moduleInstTable.get<impl::AddressTag>().at(PiS);
00139     return m.idxModule;
00140 }
00141 
00142 
00143 bool MLPSolver::isEmptyInterpretation(int S)
00144 {
00145     // S is an index to sTable
00146     const Interpretation& IS = sTable.get<impl::AddressTag>().at(S);
00147     if ( IS.isClear() ) {
00148         DBGLOG(DBG, "[MLPSolver::isEmptyInterpretation] empty interpretation: " << IS);
00149         return true;
00150     }
00151     else {
00152         DBGLOG(DBG, "[MLPSolver::isEmptyInterpretation] not empty interpretation: " << IS);
00153         return false;
00154     }
00155 }
00156 
00157 
00158 bool MLPSolver::foundNotEmptyInst(const ValueCallsType& C)
00159 {                                //  loop over all PiS inside C, check is the S is not empty
00160     VCAddressIndex::const_iterator itC = C.get<impl::AddressTag>().begin();
00161     VCAddressIndex::const_iterator itCend = C.get<impl::AddressTag>().end();
00162     while ( itC != itCend ) {
00163         if ( !isEmptyInterpretation(extractS(*itC)) ) return true;
00164         itC++;
00165     }
00166     return false;
00167 }
00168 
00169 
00170 void MLPSolver::unionCtoFront(ValueCallsType& C, const ValueCallsType& C2)
00171 {                                // union C2 to C
00172     // loop over C2
00173     VCAddressIndex::const_iterator itC2 = C2.get<impl::AddressTag>().begin();
00174     VCAddressIndex::const_iterator itC2end = C2.get<impl::AddressTag>().end();
00175     while ( itC2 != itC2end ) {
00176         // insert
00177         C.get<impl::ElementTag>().insert(*itC2);
00178         itC2++;
00179     }
00180 }
00181 
00182 
00183 std::string MLPSolver::getAtomTextFromTuple(const Tuple& tuple)
00184 {
00185     std::stringstream ss;
00186     RawPrinter printer(ss, registrySolver);
00187     Tuple::const_iterator it = tuple.begin();
00188     printer.print(*it);
00189     std::string predInsideName = ss.str();
00190     it++;
00191     if( it != tuple.end() ) {
00192         ss << "(";
00193         printer.print(*it);
00194         it++;
00195         while(it != tuple.end()) {
00196             ss << ",";
00197             printer.print(*it);
00198             it++;
00199         }
00200         ss << ")";
00201     }
00202     return ss.str();
00203 }
00204 
00205 
00206 //  rewrite ordinary atom, for example p(a) -> m25___p(a)
00207 ID MLPSolver::rewriteOrdinaryAtom(ID oldAtomID, int idxMI)
00208 {
00209     // find the correct table: og/on
00210     OrdinaryAtomTable* tbl;
00211                                  // if ground atom
00212     if ( oldAtomID.isOrdinaryGroundAtom() ) {
00213         tbl = &registrySolver->ogatoms;
00214     }
00215     else {                       // if non-ground atoms
00216         tbl = &registrySolver->onatoms;
00217     }
00218     // create the new atom (so that we do not rewrite the original one
00219     OrdinaryAtom atomRnew = tbl->getByID(oldAtomID);
00220     // access the predicate name
00221     ID& predR = atomRnew.tuple.front();
00222     Predicate p = registrySolver->preds.getByID(predR);
00223     // rename the predicate name by <prefix> + <old name>
00224     std::stringstream ss;
00225     ss << "m" << idxMI << MODULEINSTSEPARATOR;
00226     p.symbol = ss.str() + p.symbol;
00227     DBGLOG(DBG, "[MLPSolver::rewriteOrdinaryAtom] " << p.symbol);
00228     // try to locate the new pred name
00229     ID predNew = registrySolver->preds.getIDByString(p.symbol);
00230     DBGLOG(DBG, "[MLPSolver::rewriteOrdinaryAtom] ID predNew = " << predNew);
00231     if ( predNew == ID_FAIL ) {
00232         predNew = registrySolver->preds.storeAndGetID(p);
00233         DBGLOG(DBG, "[MLPSolver::rewriteOrdinaryAtom] ID predNew after FAIL = " << predNew);
00234     }
00235     // rewrite the predicate inside atomRnew
00236     predR = predNew;
00237     DBGLOG(DBG, "[MLPSolver::rewriteOrdinaryAtom] new predR = " << predR);
00238     // replace the atom text
00239     atomRnew.text = getAtomTextFromTuple(atomRnew.tuple);
00240     // try to locate the new atom (the rewritten one)
00241     ID atomFind = tbl->getIDByString(atomRnew.text);
00242     DBGLOG(DBG, "[MLPSolver::rewriteOrdinaryAtom] ID atomFind = " << atomFind);
00243     if (atomFind == ID_FAIL) {
00244         atomFind = tbl->storeAndGetID(atomRnew);
00245         DBGLOG(DBG, "[MLPSolver::rewriteOrdinaryAtom] ID atomFind after FAIL = " << atomFind);
00246     }
00247     return atomFind;
00248 }
00249 
00250 
00251 // prefix only the input predicates (with PiS)
00252 ID MLPSolver::rewriteModuleAtom(const ModuleAtom& oldAtom, int idxMI)
00253 {
00254     // create the new atom (so that we do not rewrite the original one)
00255     DBGLOG(DBG, "[MLPSolver::rewriteModuleAtom] To be rewritten = " << oldAtom);
00256     ModuleAtom atomRnew = oldAtom;
00257     rewriteTuple(atomRnew.inputs, idxMI);
00258     DBGLOG(DBG, "[MLPSolver::rewriteModuleAtom] After rewriting = " << atomRnew);
00259     ID atomRnewID = registrySolver->matoms.getIDByElement(atomRnew.predicate, atomRnew.inputs, atomRnew.outputAtom);
00260     if ( atomRnewID == ID_FAIL ) {
00261         return registrySolver->matoms.storeAndGetID(atomRnew);
00262     }
00263     return atomRnewID;
00264 }
00265 
00266 
00267 ID MLPSolver::rewritePredicate(const Predicate& oldPred, int idxMI)
00268 {
00269     // create the new Predicate (so that we do not rewrite the original one)
00270     Predicate predRnew = oldPred;
00271     std::stringstream ss;
00272     ss << "m" << idxMI << MODULEINSTSEPARATOR;
00273     predRnew.symbol = ss.str() + predRnew.symbol;
00274     ID predFind = registrySolver->preds.getIDByString(predRnew.symbol);
00275     DBGLOG(DBG, "[MLPSolver::rewritePredicate] ID predFind = " << predFind);
00276     if (predFind == ID_FAIL) {
00277         predFind = registrySolver->preds.storeAndGetID(predRnew);
00278         DBGLOG(DBG, "[MLPSolver::rewritePredicate] ID predFind after FAIL = " << predFind);
00279     }
00280     return predFind;
00281 }
00282 
00283 
00284 void MLPSolver::rewriteTuple(Tuple& tuple, int idxMI)
00285 {
00286     Tuple::iterator it = tuple.begin();
00287     while ( it != tuple.end() ) {
00288         DBGLOG(DBG, "[MLPSolver::rewriteTuple] ID = " << *it);
00289         if ( it->isAtom() || it->isLiteral() ) {
00290             if ( it->isOrdinaryGroundAtom() ) {
00291                 DBGLOG(DBG, "[MLPSolver::rewriteTuple] Rewrite ordinary ground atom = " << *it);
00292                 if ( it->isLiteral() )
00293                     *it = ID::literalFromAtom(rewriteOrdinaryAtom(*it, idxMI), it->isNaf() );
00294                 else
00295                     *it = rewriteOrdinaryAtom(*it, idxMI);
00296 
00297             }
00298             else if ( it->isOrdinaryNongroundAtom() ) {
00299                 DBGLOG(DBG, "[MLPSolver::rewriteTuple] Rewrite ordinary non ground atom = " << *it );
00300                 if ( it->isLiteral() )
00301                     *it = ID::literalFromAtom( rewriteOrdinaryAtom(*it, idxMI), it->isNaf() );
00302                 else
00303                     *it = rewriteOrdinaryAtom(*it, idxMI);
00304             }
00305             else if ( it->isModuleAtom() ) {
00306                 DBGLOG(DBG, "[MLPSolver::rewriteTuple] Rewrite module atom = " << *it);
00307                 if ( it->isLiteral() )
00308                     *it = ID::literalFromAtom( rewriteModuleAtom(registrySolver->matoms.getByID(*it), idxMI), it->isNaf() );
00309                 else
00310                     *it = rewriteModuleAtom(registrySolver->matoms.getByID(*it), idxMI);
00311             }
00312         }
00313         else if ( it->isTerm() ) {
00314             if ( it->isPredicateTerm() ) {
00315                 DBGLOG(DBG, "[MLPSolver::rewriteTuple] Rewrite predicate term = " << *it);
00316                 *it = rewritePredicate(registrySolver->preds.getByID(*it), idxMI);
00317             }
00318         }
00319 
00320         it++;
00321     }
00322 }
00323 
00324 
00325 // instIdx: refer to the index of Mi/S in the moduleInstTable
00326 // intr: \bM
00327 // intrResult: Mi/S as the result
00328 void MLPSolver::createMiS(int instIdx, const InterpretationPtr& intr, InterpretationPtr& intrResult)
00329 {
00330     intrResult->clear();
00331     const Tuple& tuple = getOgatomsInInst(instIdx);
00332     Tuple::const_iterator it = tuple.begin();
00333     while ( it != tuple.end() ) {
00334         if ( intr->getFact((*it).address) ) {
00335             intrResult->setFact((*it).address);
00336         }
00337         it++;
00338     }
00339 }
00340 
00341 
00342 // part of the rewrite method
00343 // look for a module atom in the body of the rules
00344 // if the module atom is exist in the A replace with the outputAtom (prefixed)
00345 // add o with prefix PjT as fact
00346 void MLPSolver::replacedModuleAtoms(int instIdx, InterpretationPtr& edb, Tuple& idb)
00347 {
00348     DBGLOG(DBG, "[MLPSolver::replacedModuleAtoms] idb input = " << printvector(idb));
00349 
00350     // iterate over rules, check if there is a module atoms there
00351     Tuple::iterator itR = idb.begin();
00352     while ( itR != idb.end() ) {
00353         assert( itR->isRule() == true );
00354         // check if the rule contain at least a module atom
00355         if ( itR->doesRuleContainModatoms() == true ) {
00356             const Rule& r = registrySolver->rules.getByID(*itR);
00357             Rule rNew = r;
00358             // iterate over the body of rules
00359             Tuple::iterator itB = rNew.body.begin();
00360             while ( itB != rNew.body.end() ) {
00361                 if ( (*itB).isModuleAtom() && A.size() > instIdx ) {
00362                     // find the module atom in the AiS
00363                     IDSElementIndex::iterator itE = A.at(instIdx).get<impl::ElementTag>().find(*itB);
00364                     if ( itE !=  A.at(instIdx).get<impl::ElementTag>().end() ) {
00365                                  // if found
00366                         // create the PjT
00367                         // first, get the module atom
00368                         const ModuleAtom& ma = registrySolver->matoms.getByID(*itB);
00369                         // create the interpretation Mi/S
00370                         InterpretationPtr newM(new Interpretation( registrySolver ));
00371                         createMiS(instIdx, M, newM);
00372                         // get the module Pj using the predicate from the module input, get the formal input
00373                         const Module& m = registrySolver->moduleTable.getModuleByName(ma.actualModuleName);
00374                         const Tuple& formalInputs = registrySolver->inputList.at(m.inputList);
00375                         Tuple restrictT;
00376                         Tuple newT;
00377                                  //  Mi/S restrict by p rename to q
00378                         restrictionAndRenaming( *(newM), ma.inputs, formalInputs, restrictT, newT);
00379                         Interpretation intrNewT;
00380                         createInterpretationFromTuple(newT, intrNewT);
00381                         int idxPjT = addOrGetModuleIstantiation(m.moduleName, intrNewT);
00382 
00383                         // get the outputAtom
00384                         ID outputAtom = ma.outputAtom;
00385                         OrdinaryAtomTable* tbl;
00386                         if ( outputAtom.isOrdinaryGroundAtom() ) {
00387                             tbl = &registrySolver->ogatoms;
00388                         }
00389                         else
00390                             tbl = &registrySolver->onatoms;
00391                         const OrdinaryAtom& atomR = tbl->getByID(outputAtom);
00392                         // create the new one
00393                         OrdinaryAtom newOutputAtom = atomR;
00394                         ID& predR = newOutputAtom.tuple.front();
00395                         Predicate p = registrySolver->preds.getByID(predR);
00396                         // remove the p1__
00397                         p.symbol = p.symbol.substr( p.symbol.find(MODULEPREFIXSEPARATOR) + 2);
00398                         // prefix it with m PjT___ + p2__
00399                         std::stringstream ss;
00400                         ss << "m" << idxPjT << MODULEINSTSEPARATOR << m.moduleName << MODULEPREFIXSEPARATOR << p.symbol;
00401                         p.symbol = ss.str();
00402                         DBGLOG(DBG, "[MLPSolver::replacedModuleAtoms] p.symbol new = " << p.symbol);
00403                         // try to locate the new pred name
00404                         ID predNew = registrySolver->preds.getIDByString(p.symbol);
00405                         DBGLOG(DBG, "[MLPSolver::replacedModuleAtoms] ID predNew = " << predNew);
00406                         if ( predNew == ID_FAIL ) {
00407                             predNew = registrySolver->preds.storeAndGetID(p);
00408                             DBGLOG(DBG, "[MLPSolver::replacedModuleAtoms] ID predNew after FAIL = " << predNew);
00409                         }
00410                         // rewrite the predicate inside atomRnew
00411                         predR = predNew;
00412                         DBGLOG(DBG, "[MLPSolver::replacedModuleAtoms] new predR = " << predR);
00413                         // replace the atom text
00414                         newOutputAtom.text = getAtomTextFromTuple(newOutputAtom.tuple);
00415                         // try to locate the new atom (the rewritten one)
00416                         ID atomFind = tbl->getIDByString(newOutputAtom.text);
00417                         DBGLOG(DBG, "[MLPSolver::replacedModuleAtoms] ID atomFind = " << atomFind);
00418                         if (atomFind == ID_FAIL) {
00419                             atomFind = tbl->storeAndGetID(newOutputAtom);
00420                             DBGLOG(DBG, "[MLPSolver::replacedModuleAtoms] ID atomFind after FAIL = " << atomFind);
00421                         }
00422 
00423                         // replace the module atom with this newOutputAtom
00424                         // *itB = atomFind;
00425                         *itB = ID::literalFromAtom( atomFind, itB->isNaf() );
00426 
00427                         // put Mj/T as a facts if not nil
00428                         DBGLOG(DBG, "[MLPSolver::replacedModuleAtoms] idxPjT = " << idxPjT);
00429                         DBGLOG(DBG, "[MLPSolver::replacedModuleAtoms] M = " << *M);
00430                         InterpretationPtr MjT(new Interpretation());
00431                         createMiS(idxPjT, M, MjT);
00432                         Interpretation::Storage MjTAtoms = MjT->getStorage();
00433                         Interpretation::Storage::enumerator itMjTAtoms = MjTAtoms.first();
00434                         while ( itMjTAtoms != MjTAtoms.end() ) {
00435                             // if the atoms is set
00436                             const OrdinaryAtom& atomGround = registrySolver->ogatoms.getByAddress(*itMjTAtoms);
00437                             DBGLOG(DBG, "[MLPSolver::replacedModuleAtoms] atomGround inspected = " << atomGround);
00438                             if (atomGround.tuple.front() == newOutputAtom.tuple.front() ) {
00439                                  // if the predicate = newOutputAtom, if yes:  edb->setFact(*itMjTAtoms);
00440                                 DBGLOG(DBG, "[MLPSolver::replacedModuleAtoms] before set fact = " << *edb);
00441                                 edb->setFact(*itMjTAtoms);
00442                                 DBGLOG(DBG, "[MLPSolver::replacedModuleAtoms] after set fact = " << *edb);
00443                             }
00444                             itMjTAtoms++;
00445                         }
00446                     }
00447                 }
00448                 itB++;
00449             }
00450             // TODO: optimize the bool (and the loop) here
00451             // check if there is still a module atom left
00452             bool stillAModuleAtom = false;
00453             itB = rNew.body.begin();
00454             while ( itB != rNew.body.end() && stillAModuleAtom == false) {
00455                 if ( (*itB).isAtom() || (*itB).isLiteral() ) {
00456                     if ( (*itB).isModuleAtom() ) stillAModuleAtom = true;
00457                 }
00458                 itB++;
00459             }
00460             // if no module atom left, take out the property rule mod atoms
00461             if (stillAModuleAtom == false) {
00462                 rNew.kind &= ID::PROPERTY_RULE_UNMODATOMS;
00463             }
00464             ID rNewID = registrySolver->rules.getIDByElement(rNew);
00465             if ( rNewID == ID_FAIL ) {
00466                 rNewID = registrySolver->storeRule(rNew);
00467             }
00468             // collect it in the idbResult
00469             *itR = rNewID;
00470         }
00471         itR++;
00472     }
00473 }
00474 
00475 
00476 void MLPSolver::rewrite(const ValueCallsType& C, InterpretationPtr& edbResult, Tuple& idbResult)
00477 {
00478     DBGLOG(DBG, "[MLPSolver::rewrite] enter ");
00479     // prepare edbResult
00480     edbResult.reset(new Interpretation( registrySolver ) );
00481     // prepare idbResult
00482     idbResult.clear();
00483     // loop over C
00484     VCAddressIndex::const_iterator itC = C.get<impl::AddressTag>().begin();
00485     VCAddressIndex::const_iterator itCend = C.get<impl::AddressTag>().end();
00486     while ( itC != itCend ) {
00487         // check if idx *itC has been made in Top
00488         bool usingTop = false;
00489         if ( instSplitting == 1 && *itC < Top.size() ) {
00490                                  // if yes,
00491             IDSet top = Top.at(*itC);
00492             if ( containFin(A, *itC) ) {
00493                 // add nothing
00494                 usingTop = true;
00495             } else
00496             if (top.size()>0 /*|| containFin(A, *itC) */ ) {
00497             Tuple idbResultTemp;
00498             IDSetToTuple(top, idbResultTemp);
00499             idbResult.insert(idbResult.end(), idbResultTemp.begin(), idbResultTemp.end());
00500             usingTop = true;
00501             DBGLOG(DBG, "[MLPSolver::rewrite] Get top["<< *itC <<"]: ");
00502             if ( printProgramInformation == true )
00503                 printIdb(registrySolver, idbResult);
00504         }
00505         else {
00506             DBGLOG(DBG, "Interpretation M: " << *M);
00507             DBGLOG(DBG, "Top[" << *itC << "].size = 0--");
00508         }
00509     }
00510     if ( usingTop == false ) {
00511         // get the module idx and idx S
00512         int idxM = extractPi(*itC);
00513         int idxS = extractS(*itC);
00514         const Module& m = registrySolver->moduleTable.getByAddress(idxM);
00515         // rewrite the edb, get the edb pointed by m.edb
00516         DBGLOG(DBG, "[MLPSolver::rewrite] rewrite edb ");
00517         InterpretationPtr edbTemp( new Interpretation(registrySolver) );
00518         edbTemp->add(*ctx.edbList.at(m.edb));
00519         // add S (from the instantiation) to the edb
00520         edbTemp->add( sTable.get<impl::AddressTag>().at(idxS) );
00521         // iterate over edb
00522         Interpretation::Storage bits = edbTemp->getStorage();
00523         Interpretation::Storage::enumerator it = bits.first();
00524         while ( it!=bits.end() ) {
00525             // get the atom that is pointed by *it (element of the edb)
00526             ID atomRID(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_ORDINARYG, *it);
00527             // rewrite the atomR, resulting in a new atom with prefixed predicate name, change: the registry in ctxSolver
00528             ID atomRewrite = rewriteOrdinaryAtom(atomRID, *itC);
00529             edbResult->setFact(atomRewrite.address);
00530             it++;
00531         }
00532 
00533         // rewrite the idb
00534         DBGLOG(DBG, "[MLPSolver::rewrite] rewrite idb");
00535         Tuple idbTemp;
00536         idbTemp.insert(idbTemp.end(), ctx.idbList.at(m.idb).begin(), ctx.idbList.at(m.idb).end());
00537         // loop over the rules
00538         Tuple::iterator itT = idbTemp.begin();
00539         while (itT != idbTemp.end()) {
00540             const Rule& r = registrySolver->rules.getByID(*itT);
00541             Rule rNew = r;
00542             // for each rule: body and head, rewrite it
00543             rewriteTuple(rNew.head, *itC);
00544             rewriteTuple(rNew.body, *itC);
00545 
00546             ID rNewID = registrySolver->rules.getIDByElement(rNew);
00547             if ( rNewID == ID_FAIL ) {
00548                 rNewID = registrySolver->storeRule(rNew);
00549             }
00550             // collect it in the idbResult
00551             idbResult.push_back(rNewID);
00552             itT++;
00553         }
00554     }
00555 
00556     // put Mi/S as a facts if not nil
00557     DBGLOG(DBG, "[MLPSolver::rewrite] Mi/S as a facts if not nil");
00558     InterpretationPtr MiS(new Interpretation() );
00559     createMiS(*itC, M, MiS);
00560     Interpretation::Storage MiSAtoms = MiS->getStorage();
00561     Interpretation::Storage::enumerator itMiSAtoms = MiSAtoms.first();
00562     while ( itMiSAtoms != MiSAtoms.end() ) {
00563         edbResult->setFact(*itMiSAtoms);
00564         itMiSAtoms++;
00565     }
00566 
00567     // inpect module atoms, replace with o, remove module rule property
00568     // add o as facts prefixed by Pj/T
00569     DBGLOG(DBG, "[MLPSolver::rewrite] replaced module atoms");
00570     replacedModuleAtoms( *itC, edbResult, idbResult);
00571 
00572     itC++;
00573 }
00574 
00575 
00576 }
00577 
00578 bool MLPSolver::isOrdinary(const Tuple& idb)
00579 {
00580     Tuple::const_iterator itT = idb.begin();
00581     while ( itT != idb.end() ) {
00582         assert( itT->isRule() == true );
00583         // check if the rule contain at least a module atom
00584         if ( itT->doesRuleContainModatoms() == true ) {
00585             return false;
00586         }
00587         itT++;
00588     }
00589     return true;
00590 }
00591 
00592 
00593 std::vector<int> MLPSolver::foundMainModules()
00594 {
00595     std::vector<int> result;
00596     ModuleTable::AddressIterator itBegin, itEnd;
00597     boost::tie(itBegin, itEnd) = registrySolver->moduleTable.getAllByAddress();
00598     int ctr = 0;
00599     while ( itBegin != itEnd ) {
00600         Module module = *itBegin;
00601         if ( registrySolver->inputList.at(module.inputList).size() == 0 ) {
00602             result.push_back(ctr);
00603         }
00604         itBegin++;
00605         ctr++;
00606     }
00607     DBGLOG(DBG, "[MLPSolver::foundMainModules] finished");
00608     return result;
00609 }
00610 
00611 
00612 // to be used only in the beginning
00613 MLPSolver::ValueCallsType MLPSolver::createValueCallsMainModule(int idxModule)
00614 {
00615     // create a new, empty interpretation s
00616     InterpretationType s(registrySolver);
00617     // find [] in the sTable
00618     MLPSolver::ITElementIndex::iterator itIndex = sTable.get<impl::ElementTag>().find(s);
00619     // if it is not exist, insert [] into the sTable
00620     if ( itIndex == sTable.get<impl::ElementTag>().end() ) {
00621         DBGLOG(DBG, "[MLPSolver::createValueCallsMainModule] inserting empty interpretation...");
00622         sTable.get<impl::ElementTag>().insert(s);
00623     }
00624     // get the []
00625     MLPSolver::ITElementIndex::iterator itS = sTable.get<impl::ElementTag>().find(s);
00626     // set m.idxModule and m.idxS
00627     ModuleInst PiS(idxModule, sTable.project<impl::AddressTag>(itS) - sTable.get<impl::AddressTag>().begin() );
00628 
00629     DBGLOG(DBG, "[MLPSolver::createValueCallsMainModule] PiS.idxModule = " << PiS.idxModule);
00630     DBGLOG(DBG, "[MLPSolver::createValueCallsMainModule] PiS.idxS = " << PiS.idxS);
00631 
00632     moduleInstTable.get<impl::ElementTag>().insert( PiS );
00633     MLPSolver::MIElementIndex::iterator itM = moduleInstTable.get<impl::ElementTag>().find( boost::make_tuple(PiS.idxModule, PiS.idxS) );
00634     int idxMI = moduleInstTable.project<impl::AddressTag>( itM ) - moduleInstTable.get<impl::AddressTag>().begin();
00635     DBGLOG( DBG, "[MLPSolver::createValueCallsMainModule] store PiS at index = " << idxMI );
00636 
00637     ValueCallsType C;
00638     C.push_back(idxMI);
00639     return C;
00640 }
00641 
00642 
00643 void MLPSolver::assignFin(IDSet& t)
00644 {
00645     t.clear();
00646     t.get<impl::ElementTag>().insert(ID_FAIL);
00647 }
00648 
00649 
00650 void MLPSolver::findAllModulesAtom(const Tuple& newRules, Tuple& result)
00651 {
00652     result.clear();
00653     DBGLOG(DBG, "[MLPSolver::findAllModulesAtom] enter");
00654     Tuple::const_iterator it = newRules.begin();
00655     while ( it != newRules.end() ) {
00656         if ( it->doesRuleContainModatoms() == true ) {
00657                                  // get the rule only if it contains module atoms
00658             const Rule& r = registrySolver->rules.getByID(*it);
00659             // iterate over body, assume that the module atom only exist in the body
00660             Tuple::const_iterator lit = r.body.begin();
00661             while ( lit != r.body.end() ) {
00662                 if ( lit->isModuleAtom() ) {
00663                     result.push_back(*lit);
00664                     DBGLOG(DBG, "[MLPSolver::findAllModulesAtom] push_back: " << *lit);
00665                 }
00666                 lit++;
00667             }
00668         }
00669         it++;
00670     }
00671 }
00672 
00673 
00674 ID MLPSolver::getPredIDFromAtomID(const ID& atomID)
00675 {
00676     assert( atomID.isAtom() || (atomID).isLiteral()  );
00677     if ( atomID.isOrdinaryGroundAtom() ) {
00678         const OrdinaryAtom& atom = registrySolver->ogatoms.getByID(atomID);
00679         return atom.tuple.front();
00680     }
00681     else if ( atomID.isOrdinaryNongroundAtom() ) {
00682         const OrdinaryAtom& atom = registrySolver->onatoms.getByID(atomID);
00683         return atom.tuple.front();
00684     }
00685     return ID_FAIL;
00686 }
00687 
00688 
00689 // look if in the tuple, contain an atom with the same predicate name
00690 // as in id
00691 bool MLPSolver::containsPredName(const Tuple& tuple, const ID& id)
00692 {
00693     Tuple::const_iterator itRH = tuple.begin();
00694     while ( itRH != tuple.end() ) {
00695         // *itRH = id of an ordinary atom
00696         if ( (*itRH).isAtom() ) {
00697             if ( id == getPredIDFromAtomID(*itRH) ) return true;
00698         }
00699         itRH++;
00700     }
00701     return false;
00702 }
00703 
00704 
00705 // predicate: predicate to be searched for
00706 // rules: the base rule to inspect
00707 // predsSearched: list of predicate searched so far
00708 // rules result: ID of rule that has been the result so far
00709 void MLPSolver::collectAllRulesDefined(ID predicate, const Tuple& rules, Tuple& predsSearched, Tuple& rulesResult)
00710 {
00711     DBGLOG(DBG, "[MLPSolver::collectAllRulesDefined] enter, to find pred: " << predicate);
00712     Tuple::iterator location = std::find(predsSearched.begin(), predsSearched.end(), predicate);
00713     // if not found, push_back this predicate; if found do nothing
00714     if ( location == predsSearched.end() ) {
00715         predsSearched.push_back(predicate);
00716         // look for rule in rules that defined this predicate
00717         Tuple::const_iterator it = rules.begin();
00718         while ( it != rules.end() ) {
00719             const Rule& r = registrySolver->rules.getByID(*it);
00720             if ( containsPredName(r.head, predicate) ) {
00721                                  // if this rule defined the predicate,
00722                 // look into the result, if not found, push it;
00723                 location = std::find(rulesResult.begin(), rulesResult.end(), *it);
00724                 if ( location == rulesResult.end() ) {
00725                     rulesResult.push_back(*it);
00726                 }
00727                 Tuple::const_iterator itB = r.body.begin();
00728                 while ( itB != r.body.end() ) {
00729                                  //  search for the predicate in the body
00730                     OrdinaryAtomTable* tbl;
00731                     if ( itB->isOrdinaryAtom() ) {
00732                         if (itB->isOrdinaryGroundAtom() ) {
00733                             tbl = &registrySolver->ogatoms;
00734                         }
00735                         else {
00736                             tbl = &registrySolver->onatoms;
00737                         }
00738                         const OrdinaryAtom& oa = tbl->getByID(*itB);
00739                         collectAllRulesDefined(oa.tuple.front(), rules, predsSearched, rulesResult);
00740                     }
00741                     else {
00742                         DBGLOG(DBG, "[MLPSolver::collectAllRulesDefined] found not an Ordinary atom: " << *itB);
00743                     }
00744                     *itB++;
00745                 }
00746                 itB = r.head.begin();
00747                 while ( itB != r.head.end() ) {
00748                                  //  search for the predicate in the body
00749                     OrdinaryAtomTable* tbl;
00750                     if ( itB->isOrdinaryAtom() ) {
00751                         if (itB->isOrdinaryGroundAtom() ) {
00752                             tbl = &registrySolver->ogatoms;
00753                         }
00754                         else {
00755                             tbl = &registrySolver->onatoms;
00756                         }
00757                         const OrdinaryAtom& oa = tbl->getByID(*itB);
00758                         collectAllRulesDefined(oa.tuple.front(), rules, predsSearched, rulesResult);
00759                     }
00760                     else {
00761                         DBGLOG(DBG, "[MLPSolver::collectAllRulesDefined] found not an Ordinary atom: " << *itB);
00762                     }
00763                     *itB++;
00764                 }
00765             }
00766             it++;
00767         }
00768     }
00769 }
00770 
00771 
00772 // test if the input preds of this moduleAtom are all prepared
00773 bool MLPSolver::allPrepared(const ID& moduleAtom, const Tuple& rules)
00774 {
00775     DBGLOG(DBG, "[MLPSolver::allPrepared] enter with module atom: " << moduleAtom);
00776     const ModuleAtom& m = registrySolver->matoms.getByID(moduleAtom);
00777 
00778     Tuple predsSearched;
00779     Tuple result;
00780     Tuple::const_iterator itPred = m.inputs.begin();
00781     // iterate over the input preds
00782     while ( itPred != m.inputs.end() ) {
00783                                  // collect all rules that defined this input
00784         collectAllRulesDefined(*itPred, rules, predsSearched, result);
00785         itPred++;
00786     }
00787     // iterate over the resulting rules
00788     Tuple::iterator itRules = result.begin();
00789     while ( itRules != result.end() ) {
00790         if ( itRules->doesRuleContainModatoms() == true ) return false;
00791         itRules++;
00792     }
00793     return true;
00794 }
00795 
00796 
00797 // looking for which module atoms has the smallest ill
00798 ID MLPSolver::smallestILL(const Tuple& newRules)
00799 {
00800     DBGLOG(DBG, "[MLPSolver::smallestILL] enter to find the smallest ILL in: ");
00801     if ( printProgramInformation == true ) printIdb(registrySolver, newRules);
00802 
00803     Tuple modAtoms;
00804     findAllModulesAtom(newRules, modAtoms);
00805     Tuple::iterator it = modAtoms.begin();
00806     while ( it != modAtoms.end() ) {
00807         if ( allPrepared(*it, newRules) ) {
00808             return *it;
00809         }
00810         it++;
00811     }
00812     return ID_FAIL;
00813 }
00814 
00815 
00816 bool MLPSolver::defined(const Tuple& preds, const Tuple& ruleHead)
00817 {
00818     DBGLOG(DBG, "[MLPSolver::defined] enter");
00819     Tuple::const_iterator itPred = preds.begin();
00820     while ( itPred != preds.end() ) {
00821         // *itPred = the predicate names (yes the names only, the ID is belong to term predicate)
00822         if ( containsPredName(ruleHead, *itPred) == true ) return true;
00823         itPred++;
00824 
00825     }
00826     return false;
00827 }
00828 
00829 
00830 void MLPSolver::addHeadOfModuleAtom(const Tuple& rules, IDSet& predsForbid, IDSet& rulesForbid)
00831 {
00832     Tuple::const_iterator it = rules.begin();
00833     while ( it != rules.end() ) {
00834         if ( it->doesRuleContainModatoms() == true ) {
00835                                  // add rule id to rulesForbid
00836             rulesForbid.get<impl::ElementTag>().insert(*it);
00837             const Rule& r = registrySolver->rules.getByID(*it);
00838             addTuplePredNameToIDSet(r.head, predsForbid);
00839         }
00840         it++;
00841     }
00842 }
00843 
00844 
00845 // from tuple, get the atom, get the predicate name, locate the id
00846 // add the ID into idSet
00847 void MLPSolver::addTuplePredNameToIDSet(const Tuple& tuple, IDSet& idSet)
00848 {
00849     Tuple::const_iterator it = tuple.begin();
00850     while ( it != tuple.end() ) {
00851         if ( (*it).isAtom() || (*it).isLiteral() )
00852             idSet.get<impl::ElementTag>().insert( getPredIDFromAtomID(*it) );
00853         it++;
00854     }
00855 }
00856 
00857 
00858 bool MLPSolver::tupleContainPredNameIDSet(const Tuple& tuple, const IDSet& idset)
00859 {
00860     Tuple::const_iterator it = tuple.begin();
00861     while ( it != tuple.end() ) {
00862         DBGLOG(DBG, "[MLPSolver::tupleContainPredNameIDSet] id on inspection: " << *it);
00863         if ( (*it).isAtom() || (*it).isLiteral() ) {
00864             if ( containID( getPredIDFromAtomID(*it) , idset) == true ) return true;
00865             DBGLOG(DBG, "[MLPSolver::tupleContainPredNameIDSet] is an atom or literal");
00866         }
00867         else {
00868             DBGLOG(DBG, "[MLPSolver::tupleContainPredNameIDSet] is not an atom or literal");
00869         }
00870         it++;
00871     }
00872     return false;
00873 }
00874 
00875 
00876 bool MLPSolver::containID(ID id, const IDSet& idSet)
00877 {
00878     MLPSolver::IDSElementIndex::const_iterator it = idSet.get<impl::ElementTag>().find(id);
00879     if ( it != idSet.get<impl::ElementTag>().end() ) return true;
00880     else return false;
00881 }
00882 
00883 
00884 void MLPSolver::addHeadPredsForbid(const Tuple& rules, IDSet& predsForbid, IDSet& rulesForbid)
00885 {
00886     bool stop = false;
00887     while ( stop == false ) {
00888         stop = true;
00889         Tuple::const_iterator it = rules.begin();
00890         while ( it != rules.end() ) {
00891             // if the rule is not contained in rulesForbid, inspect:
00892             if ( containID(*it, rulesForbid) == false ) {
00893                 const Rule& r = registrySolver->rules.getByID(*it);
00894                 // if the body contains pred forbid
00895                 DBGLOG(DBG, "[MLPSolver::addHeadPredsForbid] rules on inspection: " << r);
00896                 if ( tupleContainPredNameIDSet(r.body, predsForbid) == true ) {
00897                     addTuplePredNameToIDSet(r.head, predsForbid);
00898                     rulesForbid.get<impl::ElementTag>().insert(*it);
00899                     stop = false;
00900                 }
00901                 // if disjunctive head
00902                 if ( r.head.size()>1) {
00903                     addTuplePredNameToIDSet(r.head, predsForbid);
00904                     rulesForbid.get<impl::ElementTag>().insert(*it);
00905                     stop = false;
00906                 }
00907             }
00908             it++;
00909         }
00910     }
00911 }
00912 
00913 
00914 void MLPSolver::IDSetToTuple(const IDSet& idSet, Tuple& result)
00915 {
00916     result.clear();
00917     MLPSolver::IDSAddressIndex::const_iterator it = idSet.get<impl::AddressTag>().begin();
00918     while ( it != idSet.get<impl::AddressTag>().end() ) {
00919         result.push_back(*it);
00920         it++;
00921     }
00922 }
00923 
00924 
00925 void MLPSolver::collectLargestBottom(const ModuleAtom& moduleAtom, const Tuple& rulesSource, Tuple& bottom, Tuple& top)
00926 {
00927     DBGLOG(DBG, "[MLPSolver::collectLargestBottom] enter");
00928     // first, get the bottom of input splitting set
00929     bottom.clear();
00930     collectBottom(moduleAtom, rulesSource, bottom);
00931     Tuple rules;
00932                                  // rulesSource  - bottom = rules
00933     tupleMinus(rulesSource, bottom, rules);
00934 
00935     // collect rules forbid
00936     IDSet predsForbid;
00937     IDSet rulesForbid;
00938     // the head of the rule that contain module atom in the body is forbidden
00939     addHeadOfModuleAtom(rules, predsForbid, rulesForbid);
00940 
00941     if ( printProgramInformation == true ) {
00942         DBGLOG(DBG, "[MLPSolver::collectLargestBottom] after addHeadOfModuleAtom, predsForbid: ");
00943         Tuple predsForbidTuple;
00944         IDSetToTuple(predsForbid, predsForbidTuple);
00945         printIdb(registrySolver, predsForbidTuple);
00946 
00947         DBGLOG(DBG, "[MLPSolver::collectLargestBottom] after addHeadOfModuleAtom, rulesForbid: ");
00948         Tuple rulesForbidTuple;
00949         IDSetToTuple(rulesForbid, rulesForbidTuple);
00950         printIdb(registrySolver, rulesForbidTuple);
00951     }
00952     // if there is something that is forbidden
00953     if ( predsForbid.size() > 0 ) {
00954         addHeadPredsForbid(rules, predsForbid, rulesForbid);
00955         DBGLOG(DBG, "[MLPSolver::collectLargestBottom] after addHeadPredsForbid, rulesForbid: ");
00956         if ( printProgramInformation == true ) {
00957             Tuple rulesForbidTuple;
00958             IDSetToTuple(rulesForbid, rulesForbidTuple);
00959             printIdb(registrySolver, rulesForbidTuple);
00960         }
00961     }
00962     // substract rules forbid from the original rules
00963     Tuple::const_iterator it = rules.begin();
00964     while ( it != rules.end() ) {
00965         if ( containID(*it, rulesForbid) == false )
00966             bottom.push_back(*it);
00967         it++;
00968     }
00969     IDSetToTuple(rulesForbid, top);
00970 }
00971 
00972 
00973 void MLPSolver::tupleMinus(const Tuple& source, const Tuple& minusTuple, Tuple& result)
00974 {
00975     DBGLOG(DBG, "[MLPSolver::tupleMinus] enter");
00976     IDSet temp;
00977     // insert into one ID set
00978     Tuple::const_iterator it = minusTuple.begin();
00979     while ( it != minusTuple.end() ) {
00980         temp.get<impl::ElementTag>().insert(*it);
00981         it++;
00982     }
00983     // loop over source
00984     it = source.begin();
00985     while ( it != source.end() ) {
00986                                  // if not in minusTuple, put in the result
00987         if ( ! containID(*it, temp) ) result.push_back(*it);
00988         it++;
00989     }
00990 }
00991 
00992 
00993 // get the bottom of input splitting set
00994 void MLPSolver::collectBottom(const ModuleAtom& moduleAtom, const Tuple& rules, Tuple& result)
00995 {
00996     DBGLOG(DBG, "[MLPSolver::collectBottom] enter");
00997     result.clear();
00998     Tuple predsSearched;
00999     Tuple::const_iterator itPred = moduleAtom.inputs.begin();
01000     while ( itPred != moduleAtom.inputs.end() ) {
01001         collectAllRulesDefined(*itPred, rules, predsSearched, result);
01002         itPred++;
01003     }
01004 }
01005 
01006 
01007 // actualInputs: Tuple of predicate name (predicate term) in the module atom (caller)
01008 // formalInputs: Tuple of predicate name (predicate term) in the module list (module header)
01009 void MLPSolver::restrictionAndRenaming(const Interpretation& intr, const Tuple& actualInputs, const Tuple& formalInputs, Tuple& resultRestriction, Tuple& resultRenaming)
01010 {
01011     DBGLOG(DBG,"[MLPSolver::restrictionAndRenaming] enter ");
01012     resultRestriction.clear();
01013     resultRenaming.clear();
01014     if ( intr.isClear() ) {
01015         return;
01016     }
01017     // collect all of the atoms in the interpretation
01018     Interpretation::Storage bits = intr.getStorage();
01019     Interpretation::Storage::enumerator it = bits.first();
01020     while ( it!=bits.end() ) {
01021         const OrdinaryAtom& atomR = registrySolver->ogatoms.getByAddress(*it);
01022         DBGLOG(DBG,"[MLPSolver::restrictionAndRenaming] atom in the interpretation: " << atomR);
01023         // get the predicate name of the atom
01024         ID predName = atomR.tuple.front();
01025         // try to find in the actual inputs restriction
01026         Tuple::const_iterator itA = actualInputs.begin();
01027         bool found = false;
01028         int ctr = 0;
01029         while ( itA != actualInputs.end() && found == false) {
01030             if (*itA == predName) {
01031                                  // if found in the actual input restriction
01032                 resultRestriction.push_back(registrySolver->ogatoms.getIDByString(atomR.text));
01033                 OrdinaryAtom atomRnew = atomR;
01034                 DBGLOG(DBG, "[MLPSolver::restrictionAndRenaming] atomR: " << atomR);
01035                 DBGLOG(DBG, "[MLPSolver::restrictionAndRenaming] atomRnew: " << atomRnew);
01036                 // rename!
01037                 atomRnew.tuple.front() = formalInputs.at(ctr);
01038                 atomRnew.text = getAtomTextFromTuple(atomRnew.tuple);
01039                 DBGLOG(DBG, "[MLPSolver::restrictionAndRenaming] atomRnew after renaming: " << atomRnew);
01040                 // store in the ogatoms
01041                 ID id = registrySolver->ogatoms.getIDByTuple(atomRnew.tuple);
01042                 DBGLOG(DBG, "[MLPSolver::restrictionAndRenaming] id found: " << id);
01043                 if ( id == ID_FAIL ) {
01044                     id = registrySolver->ogatoms.storeAndGetID(atomRnew);
01045                     DBGLOG(DBG, "[MLPSolver::restrictionAndRenaming] id after storing: " << id);
01046                 }
01047                 resultRenaming.push_back(id);
01048                 found = true;
01049             }
01050             itA++;
01051             ctr++;
01052         }
01053         it++;
01054     }
01055 }
01056 
01057 
01058 void MLPSolver::createInterpretationFromTuple(const Tuple& tuple, Interpretation& result)
01059 {
01060     result.setRegistry(registrySolver);
01061     result.clear();
01062     // iterate over the tuple of fact, create a new interpretation s
01063     Tuple::const_iterator it = tuple.begin();
01064     while ( it != tuple.end() ) {
01065         result.setFact((*it).address);
01066         it++;
01067     }
01068 }
01069 
01070 
01071 int MLPSolver::addOrGetModuleIstantiation(const std::string& moduleName, const Interpretation& s)
01072 {
01073     DBGLOG(DBG, "[MLPSolver::addOrGetModuleIstantiation] got interpretation: " << s);
01074 
01075     // look up s in the sTable
01076     MLPSolver::ITElementIndex::iterator itIndex = sTable.get<impl::ElementTag>().find(s);
01077     if ( itIndex == sTable.get<impl::ElementTag>().end() ) {
01078         sTable.get<impl::ElementTag>().insert(s);
01079         DBGLOG(DBG, "[MLPSolver::addOrGetModuleIstantiation] insert into sTable: " << s);
01080     }
01081     MLPSolver::ITElementIndex::iterator itS = sTable.get<impl::ElementTag>().find(s);
01082 
01083     // get the module index
01084     int idxModule = registrySolver->moduleTable.getAddressByName(moduleName);
01085     ModuleInst PiS(idxModule, sTable.project<impl::AddressTag>(itS) - sTable.get<impl::AddressTag>().begin() );
01086 
01087     DBGLOG(DBG, "[MLPSolver::addOrGetModuleIstantiation] PiS.idxModule = " << PiS.idxModule);
01088     DBGLOG(DBG, "[MLPSolver::addOrGetModuleIstantiation] PiS.idxS = " << PiS.idxS);
01089 
01090     // try to locate the module instantiation => idxModule and idxS
01091     MLPSolver::MIElementIndex::iterator itMI = moduleInstTable.get<impl::ElementTag>().find( boost::make_tuple(PiS.idxModule, PiS.idxS) );
01092     if ( itMI == moduleInstTable.get<impl::ElementTag>().end() ) {
01093                                  // if not found, insert
01094         moduleInstTable.get<impl::ElementTag>().insert( PiS );
01095     }
01096     itMI = moduleInstTable.get<impl::ElementTag>().find( boost::make_tuple(PiS.idxModule, PiS.idxS) );
01097     int idxMI = moduleInstTable.project<impl::AddressTag>( itMI ) - moduleInstTable.get<impl::AddressTag>().begin();
01098     DBGLOG(DBG, "[MLPSolver::addOrGetModuleIstantiation] return value idxMI = " << idxMI);
01099     return idxMI;
01100 }
01101 
01102 
01103 // resize A if the size <= idxPjT
01104 void MLPSolver::resizeIfNeededA(int idxPjT)
01105 {
01106     if (A.size() <= idxPjT) {
01107         A.resize(idxPjT+1);
01108     }
01109 }
01110 
01111 
01112 // we treat Fin as ID_FAIL
01113 bool MLPSolver::containFin(const std::vector<IDSet>& VectorOfIDSet, int idxPjT)
01114 {
01115     IDSet Ai = VectorOfIDSet.at(idxPjT);
01116     MLPSolver::IDSElementIndex::iterator itAi = Ai.get<impl::ElementTag>().find( ID_FAIL );
01117     if ( itAi == Ai.get<impl::ElementTag>().end() ) return false;
01118     else return true;
01119 }
01120 
01121 
01122 int MLPSolver::getInstIndexOfRule(const Rule& r)
01123 {
01124     assert(r.head.size()>0 || r.body.size()>0);
01125     ID atomID = ID_FAIL;
01126     // try get an atom from the head
01127     if ( r.head.size()>0 ) {
01128         int i = 0;
01129         bool found = false;
01130         while ( i<r.head.size() && found == false ) {
01131             atomID=r.head.at(i);
01132             if ( atomID.isAtom() || atomID.isLiteral() ) found = true;
01133             i++;
01134         }
01135     }
01136     // if did not find any atom, try the body:
01137     if ( atomID == ID_FAIL && r.body.size()>0 ) {
01138         int i = 0;
01139         bool found = false;
01140         while ( i<r.body.size() && found == false ) {
01141             atomID=r.body.at(i);
01142             if ( atomID.isAtom() || atomID.isLiteral() ) found = true;
01143             i++;
01144         }
01145     }
01146     // if an atom is found, extract the predicate name
01147     if ( atomID != ID_FAIL ) {
01148         ID predID = getPredIDFromAtomID( atomID );
01149         const Predicate& p = registrySolver->preds.getByID(predID);
01150         int separator = p.symbol.find(MODULEINSTSEPARATOR);
01151         return atoi( p.symbol.substr(1, separator-1).c_str() );
01152     }
01153     return -1;                   // means no head and no body? what kind of rules is this?
01154 }
01155 
01156 
01157 void MLPSolver::updateTop(std::vector<IDSet>& Top, const Tuple& top)
01158 {
01159     bm::bvector<> clearance;     // to remember which instantiation that has been cleared
01160     clearance.clear();
01161     Tuple::const_iterator it = top.begin();
01162     while ( it != top.end() ) {
01163         // get the instantiation index for each rule
01164         const Rule& r = registrySolver->rules.getByID(*it);
01165         int n = getInstIndexOfRule(r);
01166         DBGLOG(DBG, "[MLPSolver::updateTop] inst Index of rules: " << n);
01167         // get the Top_i/S
01168         IDSet& rSet = Top.at(n);
01169         // if has never been cleared before, clear it!
01170         if ( clearance.get_bit(n) == false ) {
01171             clearance.set(n);
01172             rSet.clear();
01173         }
01174         rSet.get<impl::ElementTag>().insert(*it);
01175         it++;
01176     }
01177 }
01178 
01179 
01180 // comp() from the paper
01181 bool MLPSolver::comp(ValueCallsType C)
01182 {
01183 
01184     //recording time for rewrite
01185     struct timeval timeStruct;
01186     double startTimeRewrite = 0.0;
01187     double endTimeRewrite = 0.0;
01188     double startTimePartB = 0.0;
01189     double endTimePartB = 0.0;
01190     double startTimePartC = 0.0;
01191     double endTimePartC = 0.0;
01192     double startTimePost = 0.0;
01193     double endTimePost = 0.0;
01194     double startTimeCallDLV = 0.0;
01195     double endTimeCallDLV = 0.0;
01196     double startTimePushBack = 0.0;
01197     double endTimePushBack = 0.0;
01198     double startTimeCPathA = 0.0;
01199     double endTimeCPathA = 0.0;
01200     double startTimePartA = 0.0;
01201     double endTimePartA = 0.0;
01202     double startTimeUpdateTop = 0.0;
01203     double endTimeUpdateTop = 0.0;
01204 
01205     // for ASPSolver
01206     //...ASPSolver::DLVSoftware::Configuration configDLV;
01207     //...ASPSolver::ClingoSoftware::Configuration configClingo;
01208     ASPSolverManager mgr;
01209 
01210     std::ostringstream oss;
01211 
01212     // declare the stack
01213     std::vector< int > stackStatus;
01214     std::vector< ASPSolverManager::ResultsPtr > stackAnsRes;
01215     std::vector< InterpretationPtr > stackAns;
01216     std::vector< ValueCallsType > stackC;
01217     std::vector< std::vector<ValueCallsType> > stackPath;
01218     std::vector< InterpretationPtr > stackM;
01219     std::vector< std::vector<IDSet> > stackA;
01220     std::vector< std::vector<IDSet> > stackTop;
01221                                  // remove this? No.
01222     std::vector< RegistryPtr > stackRegistry;
01223                                  // remove this? No.
01224     std::vector< ModuleInstTable > stackMInst;
01225     std::vector< ID > stackModuleSrcAtom;
01226 
01227     std::vector< Graph > stackCallGraph;
01228     std::vector< std::vector<std::string> > stackEdgeName;
01229 
01230     stackStatus.push_back(0);
01231     stackC.push_back(C);
01232     int status = 0;              //status=0 for the first time
01233     ID idAlpha;
01234     int maxStackSize = 0;
01235     while (stackC.size()>0) {
01236         if ( stackC.size() > maxStackSize ) maxStackSize = stackC.size();
01237 
01238         C = stackC.back();
01239         status = stackStatus.back();
01240 
01241         // recording time for post processing ans bu
01242         if ( recordingTime == 1 ) {
01243             gettimeofday(&timeStruct, NULL);
01244             startTimePost = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01245         }
01246 
01247                                  // 1 = from part b, 2 = from part c
01248         if ( status == 1 || status == 2) {
01249             path = stackPath.back();
01250             *M = *stackM.back();
01251             A = stackA.back();
01252             if ( instSplitting == 1 ) Top = stackTop.back();
01253             if ( forget == 1 ) { // if forget is activated
01254                 RegistryPtr R2(new Registry(*stackRegistry.back() ));
01255                 registrySolver = R2;
01256                 moduleInstTable = stackMInst.back();
01257             }
01258             M->setRegistry(registrySolver);
01259             if (status == 2) idAlpha = stackModuleSrcAtom.back();
01260             Interpretation currAns = *stackAns.back();
01261             DBGLOG(DBG,"[MLPSolver::comp] got an answer set from ans(b(R))" << currAns);
01262             DBGLOG(DBG,"[MLPSolver::comp] M before integrate answer " << *M);
01263 
01264             // union M and N
01265             M->add( currAns );
01266             ctrASFromDLV++;
01267             if ( (printLevel & Logger::INFO) != 0 ) {
01268                 callGraph = stackCallGraph.back();
01269                 edgeName = stackEdgeName.back();
01270             }
01271             stackAns.erase(stackAns.end()-1);
01272             AnswerSet::Ptr ansBack = stackAnsRes.back()->getNextAnswerSet();
01273             if ( ansBack != 0 ) {
01274                 stackAns.push_back((ansBack->interpretation));
01275             }
01276             else {
01277                 stackStatus.erase(stackStatus.end()-1);
01278                 stackAnsRes.erase(stackAnsRes.end()-1);
01279                 stackC.erase(stackC.end()-1);
01280                 stackPath.erase(stackPath.end()-1);
01281                 stackM.erase(stackM.end()-1);
01282                 stackA.erase(stackA.end()-1);
01283                 if ( instSplitting == 1 ) stackTop.erase(stackTop.end()-1);
01284                 if ( forget == 1 ) {
01285                     stackRegistry.erase(stackRegistry.end()-1);
01286                     stackMInst.erase(stackMInst.end()-1);
01287                 }
01288                 if ( (printLevel & Logger::INFO) != 0 ) {
01289                     stackCallGraph.erase(stackCallGraph.end()-1);
01290                     stackEdgeName.erase(stackEdgeName.end()-1);
01291                 }
01292                 if ( status == 2) stackModuleSrcAtom.erase(stackModuleSrcAtom.end()-1);
01293             }
01294             if ( status == 1 ) {
01295                                  // from: recursion from part b
01296             }
01297             else if ( status == 2 ) {
01298                                  // from: recursion from part c
01299                 // restriction and renaming
01300                 // get the formal input paramater, tuple of predicate term
01301                 const ModuleAtom& alpha = registrySolver->matoms.getByID( idAlpha);
01302                 const Module& alphaJ = registrySolver->moduleTable.getModuleByName(alpha.actualModuleName);
01303                 const Tuple& formalInputs = registrySolver->inputList.at(alphaJ.inputList);
01304                 Tuple restrictT;
01305                 Tuple newT;
01306                 restrictionAndRenaming( currAns, alpha.inputs, formalInputs, restrictT, newT);
01307                 DBGLOG(DBG,"[MLPSolver::comp] newT: " << printvector(newT));
01308 
01309                 // defining Pj T
01310                 InterpretationType intrNewT;
01311                 createInterpretationFromTuple(newT, intrNewT);
01312                 int idxPjT = addOrGetModuleIstantiation(alphaJ.moduleName, intrNewT);
01313 
01314                 // next: defining the new C and path
01315                                  // resize if A size <=idxPjT
01316                 resizeIfNeededA(idxPjT);
01317 
01318                 if (  containFin(A, idxPjT) ) {
01319             }
01320             else {
01321                 if ( (printLevel & Logger::INFO) != 0 ) {
01322                     // add the call graph here:
01323                     const VCAddressIndex& idx = C.get<impl::AddressTag>();
01324                     VCAddressIndex::const_iterator it = idx.begin();
01325                     while ( it != idx.end() ) {
01326                         boost::add_edge(*it, idxPjT, callGraph);
01327                         // add edge name T here
01328                         InterpretationType intrRestrictT;
01329                         createInterpretationFromTuple(restrictT, intrRestrictT);
01330                         oss.str("");
01331                         intrRestrictT.setRegistry(registrySolver);
01332                         intrRestrictT.printWithoutPrefix(oss);
01333                         edgeName.push_back(oss.str());
01334                         it++;
01335                     }
01336                 }
01337                 path.push_back(C);
01338                 C.clear();
01339                 C.push_back(idxPjT);
01340             }
01341         }                        // if status==2
01342     }                            // if status == 1 || status == 2
01343     else if ( status == 0 ) {
01344                                  // from the beginnning
01345         stackC.erase(stackC.end()-1);
01346     }
01347     // recording time for post processing ans bu
01348     if ( recordingTime == 1 ) {
01349         gettimeofday(&timeStruct, NULL);
01350         endTimePost = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01351         totalTimePost = totalTimePost + endTimePost - startTimePost;
01352     }
01353 
01354     // print the C:
01355     if ( (printLevel & Logger::INFO) != 0 ) {
01356         DBGLOG(INFO,"[MLPSolver::comp] Enter comp with C: ");
01357         oss.str("");
01358         printValueCallsType(oss, registrySolver, C);
01359         DBGLOG(INFO,oss.str());
01360         // print the path:
01361         DBGLOG(INFO,"[MLPSolver::comp] with path: ");
01362         oss.str("");
01363         printPath(oss,registrySolver, path);
01364         DBGLOG(INFO,oss.str());
01365         // print the M:
01366         DBGLOG(INFO,"[MLPSolver::comp] with M: " << *M);
01367         // print the A:
01368         DBGLOG(INFO,"[MLPSolver::comp] with A: ");
01369         oss.str("");
01370         printA(oss,registrySolver, A);
01371         DBGLOG(INFO,oss.str());
01372     }
01373 
01374     // part a
01375 
01376     //recording time part a
01377     if ( recordingTime == 1 ) {
01378         gettimeofday(&timeStruct, NULL);
01379         startTimePartA = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01380     }
01381 
01382     ValueCallsType CPrev;
01383     int PiSResult;
01384     bool wasInLoop = false;
01385     if ( foundCinPath(C, path, CPrev, PiSResult) ) {
01386         DBGLOG(DBG, "[MLPSolver::comp] found value-call-loop in value calls");
01387         /* not needed for i-stratified
01388         if ( foundNotEmptyInst(C) )
01389           {
01390             DBGLOG(DBG, "[MLPSolver::comp] not ic-stratified program because foundNotEmptyInst(C)");
01391         DBGLOG(DBG, "[MLPSolver::comp] path: ");
01392         oss.str("");
01393         printPath(oss,ctxSolver, path);
01394         DBGLOG(DBG, oss.str());
01395         throw FatalError("[MLPSolver::comp] Error: not c stratified program ");
01396             return false;
01397           }
01398         */
01399         DBGLOG(DBG, "[MLPSolver::comp] ic-stratified test 1 passed");
01400         ValueCallsType C2;
01401         do {
01402             C2 = path.back();
01403             path.erase(path.end()-1);
01404             /* not needed for i-stratified
01405             if ( foundNotEmptyInst(C2) )
01406               {
01407                 DBGLOG(DBG, "[MLPSolver::comp] not ic-stratified program because foundNotEmptyInst(C2)");
01408             throw FatalError("[MLPSolver::comp] Error: not c stratified program ");
01409                 return false;
01410               }
01411             */
01412             DBGLOG(DBG, "[MLPSolver::comp] ic-stratified test 2 passed");
01413             unionCtoFront(C, C2);
01414             DBGLOG(DBG, "[MLPSolver::comp] C size after union: " << C.size());
01415         }
01416         while ( C2 != CPrev );
01417         wasInLoop = true;
01418     }                            // if ( foundCinPath....
01419     else {
01420         DBGLOG(DBG, "[MLPSolver::comp] found no value-call-loop in value calls");
01421     }
01422 
01423     //finish recording time part a
01424     if ( recordingTime == 1 ) {
01425         gettimeofday(&timeStruct, NULL);
01426         endTimePartA = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01427         totalTimePartA = totalTimePartA + endTimePartA - startTimePartA;
01428     }
01429 
01430     //recording time rewrite
01431     if ( recordingTime == 1 ) {
01432         gettimeofday(&timeStruct, NULL);
01433         startTimeRewrite = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01434     }
01435 
01436     InterpretationPtr edbRewrite;
01437     Tuple idbRewrite;
01438     rewrite(C, edbRewrite, idbRewrite);
01439 
01440     if ( recordingTime == 1 ) {
01441         gettimeofday(&timeStruct, NULL);
01442         endTimeRewrite = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01443         totalTimeRewrite = totalTimeRewrite + endTimeRewrite - startTimeRewrite;
01444     }
01445 
01446     DBGLOG(DBG, "[MLPSolver::comp] after rewrite: ");
01447     if ( printProgramInformation == true )
01448         printEdbIdb(registrySolver, edbRewrite, idbRewrite);
01449 
01450     if ( isOrdinary(idbRewrite) ) {
01451         // start recording time part b
01452         //...int cint;
01453         //...std::cin >> cint;
01454 
01455         countB++;
01456         if ( recordingTime == 1 ) {
01457             gettimeofday(&timeStruct, NULL);
01458             startTimePartB = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01459         }
01460 
01461         DBGLOG(DBG, "[MLPSolver::comp] enter isOrdinary");
01462         if ( path.size() == 0 ) {
01463             //printProgram(ctxSolver,edbRewrite, idbRewrite);
01464             DBGLOG(DBG, "[MLPSolver::comp] enter path size empty");
01465             // try to get the answer set:
01466 
01467             ASPSolverManager::ResultsPtr res;
01468             OrdinaryASPProgram program(registrySolver, idbRewrite, edbRewrite, 0);
01469 
01470             // recording time to call DLV
01471             if ( recordingTime == 1 ) {
01472                 gettimeofday(&timeStruct, NULL);
01473                 startTimeCallDLV = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01474             }
01475 
01476             //staticSolver res = mgr.solve(config, program);
01477             res = mgr.solve(*ctx.getASPSoftware(), program);
01478             ctrCallToDLV++;
01479 
01480             if ( recordingTime == 1 ) {
01481                 gettimeofday(&timeStruct, NULL);
01482                 endTimeCallDLV = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01483                 totalTimeCallDLV = totalTimeCallDLV + endTimeCallDLV - startTimeCallDLV;
01484             }
01485 
01486             AnswerSet::Ptr int0 = res->getNextAnswerSet();
01487 
01488             while (int0 !=0 ) {
01489 
01490                 InterpretationPtr M2(new Interpretation(registrySolver));
01491                 *M2 = *M;
01492                 // integrate the answer
01493                 M2->add( *(int0->interpretation) );
01494                 ctrASFromDLV++;
01495 
01496                 // collect the full answer set
01497                 ctrAS++;
01498                 oss.str("");
01499                 DBGLOG(INFO, "[MLPSolver::comp] Got an answer set" << std::endl << "ANSWER SET" << std::endl << ctrAS);
01500                 printASinSlot(oss, registrySolver, M2);
01501                 std::string asString = oss.str();
01502                 std::cout << asString << std::endl;
01503                 //std::cout << ctrAS << std::endl;
01504                 struct timeval currentTimeStruct;
01505                 gettimeofday(&currentTimeStruct, NULL);
01506                 double currentTime = currentTimeStruct.tv_sec+(currentTimeStruct.tv_usec/1000000.0);
01507                 DBGLOG(STATS, std::endl << ctrAS << std::endl << moduleInstTable.size() << std::endl << registrySolver->ogatoms.getSize() << std::endl << ctrASFromDLV << std::endl << ctrCallToDLV << std::endl << (currentTime - startTime));
01508                 if ( (printLevel & Logger::INFO) != 0) {
01509                     // print the call graph
01510                     oss.str("");
01511                     printCallGraph(oss, callGraph, asString);
01512                     DBGLOG(INFO, std::endl << " ==== call graph begin here ==== " << std::endl << ctrAS << ".dot" << std::endl << oss.str() << std::endl << " ==== call graph end here ==== ");
01513                     DBGLOG(INFO, "Instantiation information: ");
01514                     std::ostringstream oss;
01515                     for (int i=0; i<moduleInstTable.size(); i++) {
01516                         oss.str("");
01517                         oss << "m" << i << ": ";
01518                         printModuleInst(oss, registrySolver, i);
01519                         DBGLOG(INFO, oss.str());
01520                     }
01521                     DBGLOG(INFO, "Registry information: ");
01522                     DBGLOG(INFO, *registrySolver);
01523                 }
01524 
01525                 if ( nASReturned > 0 && ctrAS == nASReturned) return true;
01526 
01527                 // get the next answer set
01528                 int0 = res->getNextAnswerSet();
01529             }                    // while (int0...
01530         }                        // if path.size == 0 ...
01531         else {
01532                                  // part b, if path is not empty...
01533             ValueCallsType C2 = path.back();
01534             if ( (printLevel & Logger::DBG) != 0 ) {
01535                 DBGLOG(DBG,"[MLPSolver::comp] path before erase: ");
01536                 oss.str("");
01537                 printPath(oss, registrySolver, path);
01538                 DBGLOG(DBG,oss.str());
01539             }
01540             path.erase(path.end()-1);
01541             if ( (printLevel & Logger::DBG) != 0 ) {
01542                 DBGLOG(DBG,"[MLPSolver::comp] path after erase: ");
01543                 oss.str("");
01544                 printPath(oss, registrySolver, path);
01545                 DBGLOG(DBG,oss.str());
01546             }
01547             const VCAddressIndex& idx = C.get<impl::AddressTag>();
01548             VCAddressIndex::const_iterator it = idx.begin();
01549             while ( it != idx.end() ) {
01550                 IDSet& a = A.at(*it);
01551                 assignFin(a);
01552                 it++;
01553             }
01554             if ( instSplitting == 1 ) {
01555                 it = idx.begin();
01556                 while ( it != idx.end() ) {
01557                     if (Top.size() > *it) {
01558                         IDSet& t = Top.at(*it);
01559                         t.clear();
01560                     }
01561                     it++;
01562                 }
01563             }
01564 
01565             // for all ans(newCtx) here
01566             // try to get the answer set:
01567 
01568             ASPSolverManager::ResultsPtr res;
01569             OrdinaryASPProgram program(registrySolver, idbRewrite, edbRewrite, 0);
01570 
01571             // recording time to call DLV
01572             if ( recordingTime == 1 ) {
01573                 gettimeofday(&timeStruct, NULL);
01574                 startTimeCallDLV = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01575             }
01576 
01577             //staticSolver res = mgr.solve(config, program);
01578             res = mgr.solve(*ctx.getASPSoftware(), program);
01579             ctrCallToDLV++;
01580 
01581             if ( recordingTime == 1 ) {
01582                 gettimeofday(&timeStruct, NULL);
01583                 endTimeCallDLV = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01584                 totalTimeCallDLV = totalTimeCallDLV + endTimeCallDLV - startTimeCallDLV;
01585             }
01586 
01587             // for the recursion part b
01588             AnswerSet::Ptr int0 = res->getNextAnswerSet();
01589             if ( int0!=0 ) {
01590 
01591                 // start recording time for push back part b
01592                 if ( recordingTime == 1 ) {
01593                     gettimeofday(&timeStruct, NULL);
01594                     startTimePushBack = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01595                 }
01596 
01597                 stackAns.push_back((int0->interpretation));
01598                 stackAnsRes.push_back(res);
01599                 stackStatus.push_back(1);
01600 
01601                 if ( recordingTime == 1 ) {
01602                     gettimeofday(&timeStruct, NULL);
01603                     startTimeCPathA = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01604                 }
01605 
01606                 stackC.push_back(C2);
01607                 stackPath.push_back(path);
01608                 stackA.push_back(A);
01609                 if ( instSplitting == 1 ) stackTop.push_back(Top);
01610                 if ( recordingTime == 1 ) {
01611                     gettimeofday(&timeStruct, NULL);
01612                     endTimeCPathA = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01613                     totalTimeCPathA = totalTimeCPathA + endTimeCPathA - startTimeCPathA;
01614                 }
01615 
01616                 InterpretationPtr M2(new Interpretation(registrySolver));
01617                 *M2 = *M;
01618                 stackM.push_back(M2);
01619                 if ( forget == 1 ) {
01620                     RegistryPtr R2(new Registry(*registrySolver) );
01621                     stackRegistry.push_back( R2 );
01622                     stackMInst.push_back(moduleInstTable);
01623                 }
01624                 if ( (printLevel & Logger::INFO) != 0 ) {
01625                     stackCallGraph.push_back(callGraph);
01626                     stackEdgeName.push_back(edgeName);
01627                 }
01628 
01629                 // ending recording time for push back part b
01630                 if ( recordingTime == 1 ) {
01631                     gettimeofday(&timeStruct, NULL);
01632                     endTimePushBack = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01633                     totalTimePushBack = totalTimePushBack + endTimePushBack - startTimePushBack;
01634                 }
01635 
01636             }
01637         }                        // else if path size = 0, else
01638         // finish recording time part b
01639         if ( recordingTime == 1 ) {
01640             gettimeofday(&timeStruct, NULL);
01641             endTimePartB = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01642             totalTimePartB = totalTimePartB + endTimePartB - startTimePartB;
01643         }
01644     }                            // if isOrdinary ( idb...
01645     else {                       // if not ordinary
01646                                  // part c
01647         countC++;
01648                                  // start recording time part c
01649         if ( recordingTime == 1 ) {
01650             gettimeofday(&timeStruct, NULL);
01651             startTimePartC = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01652         }
01653         DBGLOG(DBG, "[MLPSolver::comp] enter not ordinary part");
01654         ID idAlpha = smallestILL(idbRewrite);
01655         if ( idAlpha == ID_FAIL ) {
01656                                  // not i-stratified
01657             throw FatalError("[MLPSolver::comp] Error: not i stratified program; cannot find an all-prepared-input module atom");
01658             return false;
01659         }
01660         const ModuleAtom& alpha = registrySolver->matoms.getByID(idAlpha);
01661         DBGLOG(DBG, "[MLPSolver::comp] smallest ill by: " << idAlpha);
01662         // check the size of A
01663         DBGLOG(DBG, "[MLPSolver::comp] moduleInstTable size: " << moduleInstTable.size());
01664         DBGLOG(DBG, "[MLPSolver::comp] A size: " << A.size());
01665         if ( A.size() < moduleInstTable.size() )  A.resize( moduleInstTable.size() );
01666 
01667         // loop over PiS in C, insert id into AiS
01668         const VCAddressIndex& idx = C.get<impl::AddressTag>();
01669         VCAddressIndex::const_iterator it = idx.begin();
01670         while ( it != idx.end() ) {
01671             A.at(*it).get<impl::ElementTag>().insert(idAlpha);
01672             it++;
01673         }
01674 
01675         Tuple bottom;
01676         if ( instSplitting == 0 ) {
01677             //...Tuple top;
01678             //...collectLargestBottom(idbRewrite, bottom, top);
01679             collectBottom(alpha, idbRewrite, bottom);
01680             if ( printProgramInformation == true ) {
01681                 DBGLOG(DBG, "[MLPSolver::comp] Edb Idb after collect bottom for id: " << idAlpha);
01682                 printEdbIdb(registrySolver, edbRewrite, bottom);
01683             }
01684             //...int cint;
01685             //...std::cin >> cint;
01686             //...std::cout << "[MLPSolver::comp] Edb Idb after collect bottom for id: " << idAlpha << std::endl;
01687             //...printEdbIdb(registrySolver, edbRewrite, bottom);
01688         }
01689         else if ( instSplitting == 1 ) {
01690             Tuple top;
01691             //...collectBottom(alpha, idbRewrite, bottom);
01692             //...tupleMinus(idbRewrite, bottom, top);
01693             //...DBGLOG(DBG, "[MLPSolver::comp] Edb Idb after collect bottom for id: " << idAlpha);
01694             collectLargestBottom(alpha, idbRewrite, bottom, top);
01695             if ( printProgramInformation == true ) {
01696                 DBGLOG(DBG, "[MLPSolver::comp] Edb Idb after collect largest bottom: ");
01697                 printEdbIdb(registrySolver, edbRewrite, bottom);
01698             }
01699             //...int cint;
01700             //...std::cin >> cint;
01701             //...std::cout << "[MLPSolver::comp] Edb Idb after collect largest bottom: " << std::endl;
01702             //...printEdbIdb(registrySolver, edbRewrite, bottom);
01703             // here add rmlpize
01704             if ( Top.size() < moduleInstTable.size() ) Top.resize( moduleInstTable.size() );
01705 
01706                                  // record time for updateTop
01707             if ( recordingTime == 1 ) {
01708                 gettimeofday(&timeStruct, NULL);
01709                 startTimeUpdateTop = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01710             }
01711             updateTop(Top, top);
01712             if ( recordingTime == 1 ) {
01713                 gettimeofday(&timeStruct, NULL);
01714                 endTimeUpdateTop = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01715                 totalTimeUpdateTop = totalTimeUpdateTop + endTimeUpdateTop - startTimeUpdateTop;
01716             }
01717 
01718             if ( (printLevel & Logger::INFO) != 0 ) {
01719                 oss.str("");
01720                 printA(oss, registrySolver, Top);
01721                 DBGLOG(INFO,"[MLPSolver::comp] with M: " << *M);
01722                 DBGLOG(DBG, "[MLPSolver::comp] after updateTop: " << oss.str());
01723             }
01724         }
01725         // get the module name
01726         const Module& alphaJ = registrySolver->moduleTable.getModuleByName(alpha.actualModuleName);
01727         if (alphaJ.moduleName=="") {
01728             DBGLOG(DBG,"[MLPSolver::comp] Error: Looking for module "<< alpha.actualModuleName << " got an empty module: " << alphaJ);
01729             return false;
01730         }
01731         DBGLOG(DBG,"[MLPSolver::comp] alphaJ: " << alphaJ);
01732 
01733         // for all N in ans(bu(R))
01734         // try to get the answer of the bottom:
01735 
01736         ASPSolverManager::ResultsPtr res;
01737 
01738         OrdinaryASPProgram program(registrySolver, bottom, edbRewrite, 0);
01739 
01740         // recording time to call DLV
01741         if ( recordingTime == 1 ) {
01742             gettimeofday(&timeStruct, NULL);
01743             startTimeCallDLV = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01744         }
01745 
01746         //staticSolver res = mgr.solve(config, program);
01747         res = mgr.solve(*ctx.getASPSoftware(), program);
01748         ctrCallToDLV++;
01749 
01750         if ( recordingTime == 1 ) {
01751             gettimeofday(&timeStruct, NULL);
01752             endTimeCallDLV = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01753             totalTimeCallDLV = totalTimeCallDLV + endTimeCallDLV - startTimeCallDLV;
01754         }
01755 
01756         AnswerSet::Ptr int0 = res->getNextAnswerSet();
01757 
01758         if ( int0!=0 ) {
01759             // recording time for push back part c
01760             if ( recordingTime == 1 ) {
01761                 gettimeofday(&timeStruct, NULL);
01762                 startTimePushBack = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01763             }
01764 
01765             stackAns.push_back((int0->interpretation));
01766             stackAnsRes.push_back(res);
01767             stackStatus.push_back(2);
01768 
01769             if ( recordingTime == 1 ) {
01770                 gettimeofday(&timeStruct, NULL);
01771                 startTimeCPathA = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01772             }
01773 
01774             stackC.push_back(C);
01775             stackPath.push_back(path);
01776             stackA.push_back(A);
01777             if ( instSplitting == 1 ) stackTop.push_back(Top);
01778             if ( recordingTime == 1 ) {
01779                 gettimeofday(&timeStruct, NULL);
01780                 endTimeCPathA = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01781                 totalTimeCPathA = totalTimeCPathA + endTimeCPathA - startTimeCPathA;
01782             }
01783 
01784             InterpretationPtr M2(new Interpretation(registrySolver));
01785             *M2 = *M;
01786             stackM.push_back(M2);
01787             if ( forget == 1 ) {
01788                 RegistryPtr R2(new Registry(*registrySolver) );
01789                 stackRegistry.push_back( R2 );
01790                 stackMInst.push_back(moduleInstTable);
01791             }
01792             stackModuleSrcAtom.push_back(idAlpha);
01793             if ( (printLevel & Logger::INFO) != 0 ) {
01794                 stackCallGraph.push_back(callGraph);
01795                 stackEdgeName.push_back(edgeName);
01796             }
01797 
01798             // recording time for push back part c
01799             if ( recordingTime == 1 ) {
01800                 gettimeofday(&timeStruct, NULL);
01801                 endTimePushBack = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01802                 totalTimePushBack = totalTimePushBack + endTimePushBack - startTimePushBack;
01803             }
01804 
01805         }
01806         // finish recording time part c
01807         if ( recordingTime == 1 ) {
01808             gettimeofday(&timeStruct, NULL);
01809             endTimePartC = timeStruct.tv_sec+(timeStruct.tv_usec/1000000.0);
01810             totalTimePartC = totalTimePartC + endTimePartC - startTimePartC;
01811         }
01812 
01813     }                            // else  (if ordinary ... else ...)
01814 
01815 }                                // while stack is not empty
01816 
01817 
01818 DBGLOG(DBG, "[MLPSolver::comp] finished");
01819 
01820 return true;
01821 }
01822 
01823 
01824 bool MLPSolver::solve()
01825 {
01826     recordingTime = 0;
01827     if ( (printLevel & Logger::ANALYZE) != 0 ) recordingTime = 1;
01828     totalTimePost = 0.0;
01829     totalTimePartA = 0.0;
01830     totalTimeRewrite = 0.0;
01831     totalTimePartB = 0.0;
01832     totalTimePartC = 0.0;
01833     totalTimeCallDLV = 0.0;
01834     totalTimePushBack = 0.0;
01835     totalTimeCPathA = 0.0;
01836     countB = 0;
01837     countC = 0;
01838     printProgramInformation = false;
01839     DBGLOG(STATS, "1st row: '80'-> ignore this; 2nd row: ctrAS; 3rd row: #moduleInstantiation, 4th row: #ordinaryGroundAtoms, 5th row: #ASFromDLV, 6th row: #callToDLV, 7th row: TimeElapsed");
01840     DBGLOG(DBG, "[MLPSolver::solve] started");
01841     // find all main modules in the program
01842     std::vector<int> mainModules = foundMainModules();
01843     std::vector<int>::const_iterator it = mainModules.begin();
01844     int i = 0;
01845     dataReset();
01846 
01847     // to record time
01848     struct timeval startTimeStruct;
01849     gettimeofday(&startTimeStruct, NULL);
01850     startTime = startTimeStruct.tv_sec+(startTimeStruct.tv_usec/1000000.0);
01851 
01852     ctrAS = 0;
01853     ctrCallToDLV = 0;
01854     ctrASFromDLV = 0;
01855 
01856     //recording time for comp
01857     double compStartTime;
01858     double compEndTime;
01859     if ( recordingTime ==1 ) {
01860         gettimeofday(&startTimeStruct, NULL);
01861         compStartTime = startTimeStruct.tv_sec+(startTimeStruct.tv_usec/1000000.0);
01862     }
01863     while ( it != mainModules.end() ) {
01864         A.clear();
01865         Top.clear();
01866         M->clear();
01867         RegistryPtr R2(new Registry( *ctx.registry() ));
01868         registrySolver = R2;
01869         moduleInstTable.clear();
01870         DBGLOG(INFO, " ");
01871         DBGLOG(INFO, "[MLPSolver::solve] ==================== main module solve ctr: ["<< i << "] ==================================");
01872         DBGLOG(INFO, "[MLPSolver::solve] main module id inspected: " << *it);
01873         if ( comp(createValueCallsMainModule(*it)) == false ) {
01874             throw FatalError("MLP solve: comp() return false");
01875             return false;
01876         }
01877         i++;
01878         it++;
01879     }
01880     gettimeofday(&startTimeStruct, NULL);
01881     //recording time...
01882     if ( recordingTime ==1 ) {
01883         compEndTime = startTimeStruct.tv_sec+(startTimeStruct.tv_usec/1000000.0);
01884         std::cerr << "Total comp time: " << compEndTime-compStartTime << std::endl;
01885         std::cerr << "Post process ans(bu) Time: " << totalTimePost << std::endl;
01886         std::cerr << "Part A time: " << totalTimePartA << std::endl;
01887         std::cerr << "Rewrite Time: " << totalTimeRewrite << ", countRwr: " << countB+countC << ", avgtimeRwr: " << totalTimeRewrite/(countB+countC) << std::endl;
01888         std::cerr << "Part B time: " << totalTimePartB << ", countB: " << countB << ", avgtimeB: " << totalTimePartB/countB << std::endl;
01889         std::cerr << "Part C time: " << totalTimePartC << ", countC: " << countC << ", avgtimeC: " << totalTimePartC/countC << std::endl;
01890         std::cerr << "UpdateTop time: " << totalTimeUpdateTop << ", countUpdateTop: " << countC << ", avgtimeUpdateTop: " << totalTimeUpdateTop/countC << std::endl;
01891         std::cerr << "Call DLV time: " << totalTimeCallDLV << ", countCallDLV: " << ctrCallToDLV << ", avgtimeCallDLV: " << totalTimeCallDLV/ctrCallToDLV << std::endl;
01892         std::cerr << "Push back time: " << totalTimePushBack << std::endl;
01893         std::cerr << "PushBack CPathA Time: " << totalTimeCPathA << std::endl;
01894     }
01895     DBGLOG(INFO, "Total answer set: " << ctrAS);
01896     /*
01897       DBGLOG(INFO, "Instantiation information: ");
01898       std::ostringstream oss;
01899       for (int i=0; i<moduleInstTable.size(); i++)
01900         {
01901           oss.str("");
01902           oss << "m" << i << ": ";
01903           printModuleInst(oss, registrySolver, i);
01904           DBGLOG(INFO, oss.str());
01905         }
01906 
01907       DBGLOG(INFO, "Registry information: ");
01908       DBGLOG(INFO, *registrySolver);
01909     */
01910     DBGLOG(INFO, "[MLPSolver::solve] finished");
01911 
01912     return true;
01913 }
01914 
01915 
01916 void MLPSolver::printValueCallsType(std::ostringstream& oss, const RegistryPtr& reg1, const ValueCallsType& C) const
01917 {
01918     oss << "{ ";
01919     const VCAddressIndex& idx = C.get<impl::AddressTag>();
01920     VCAddressIndex::const_iterator it = idx.begin();
01921     bool first = true;
01922     while ( it != idx.end() ) {
01923         ModuleInst mi = moduleInstTable.at(*it);
01924         std::string moduleName = reg1->moduleTable.getByAddress(mi.idxModule).moduleName;
01925         Interpretation s = sTable.at(mi.idxS);
01926         s.setRegistry(reg1);
01927         if ( first == false ) oss << ", ";
01928         oss << moduleName << "[" << s << "]";
01929         it++;
01930         first = false;
01931     }
01932     oss << " }";
01933 }
01934 
01935 
01936 void MLPSolver::printPath(std::ostringstream& oss, const RegistryPtr& reg1, const std::vector<ValueCallsType>& path) const
01937 {
01938     std::vector<ValueCallsType>::const_iterator it = path.begin();
01939     while ( it != path.end() ) {
01940         printValueCallsType(oss, reg1, *it);
01941         it++;
01942         if (it != path.end() ) oss << std::endl;
01943     }
01944 }
01945 
01946 
01947 void MLPSolver::printA(std::ostringstream& oss, const RegistryPtr& reg1, const std::vector<IDSet>& A) const
01948 {
01949     RawPrinter printer(oss, reg1);
01950 
01951     std::vector<IDSet>::const_iterator it = A.begin();
01952     int i=0;
01953     bool first;
01954     while ( it != A.end() ) {
01955         oss << "A[" << i << "][size:" << (*it).size() << "]: ";
01956         IDSAddressIndex::const_iterator itIDSet = (*it).begin();
01957         first = true;
01958         while ( itIDSet != (*it).end() ) {
01959             // print here
01960             if (first == false) oss << ", ";
01961             if ( *itIDSet == ID_FAIL )
01962                 oss << "fin";
01963             else {
01964                 printer.print(*itIDSet);
01965             }
01966 
01967             itIDSet++;
01968             first = false;
01969         }
01970         oss << std::endl;
01971         i++;
01972         it++;
01973     }
01974 }
01975 
01976 
01977 // print the text of module instantiation, given the module index (index to the instantiation table)
01978 // example: p1[{q(a),q(b)}]
01979 void MLPSolver::printModuleInst(std::ostream& out, const RegistryPtr& reg, int moduleInstIdx)
01980 {
01981     // get the module index
01982     int idxM = extractPi(moduleInstIdx);
01983     out << reg->moduleTable.getByAddress(idxM).moduleName ;
01984 
01985     // get the interpetretation index
01986     int idxS = extractS(moduleInstIdx);
01987     Interpretation intrS = sTable.get<impl::AddressTag>().at(idxS);
01988     intrS.setRegistry( reg );
01989     out << "[";
01990     intrS.printWithoutPrefix(out);
01991     out << "]";
01992 }
01993 
01994 
01995 void MLPSolver::printASinSlot(std::ostream& out, const RegistryPtr& reg, const InterpretationPtr& intr)
01996 {
01997     //  Interpretation newIntr( reg );
01998     InterpretationPtr newIntr (new Interpretation(reg) );
01999     out << "(";
02000     bool first = true;
02001     for (int i=0; i<moduleInstTable.size();i++) {
02002         createMiS(i, intr, newIntr);
02003         if ( !( newIntr->isClear() ) ) {
02004             if (first == false) out << ", ";
02005             printModuleInst(out,reg,i);
02006             out << "=";
02007             newIntr->printWithoutPrefix(out);
02008             first = false;
02009 
02010         }
02011     }
02012     out << ")";
02013 }
02014 
02015 
02016 void MLPSolver::printCallGraph(std::ostream& oss, const Graph& graph, const std::string& graphLabel)
02017 {
02018     // produce all module instantiation table
02019     std::ostringstream ss;
02020     std::vector<std::string>  vertexName(moduleInstTable.size());
02021     for (int i=0;i<moduleInstTable.size();i++) {
02022         ss.str("");
02023         printModuleInst(ss, registrySolver, i);
02024         vertexName[i] = ss.str();
02025     }
02026     // print the preliminary
02027     oss << std::endl;
02028     oss << "digraph G {" << std::endl;
02029     // get the maximum number of vertex
02030     VertexIterator itg, itg_end;
02031     boost::tie(itg, itg_end) = boost::vertices(callGraph);
02032     oss << *itg_end << "[label=\"" << graphLabel << "\", shape=box];" << std::endl;
02033 
02034     // print the edge
02035     EdgeIterator ite, ite_end;
02036     boost::tie(ite, ite_end) = boost::edges(callGraph);
02037     int ie=0;
02038     std::vector<std::string>::const_iterator itEN = edgeName.begin();
02039     while (ite != ite_end ) {
02040         if ( itEN == edgeName.end() ) {
02041             DBGLOG(ERROR, "Not sync edge and edge name");
02042             return;
02043         }
02044         oss << boost::source(*ite,callGraph) << "->" << boost::target(*ite,callGraph) << "[label=\"" << *itEN << "\"];" << std::endl;
02045         oss << boost::source(*ite,callGraph) << "[label=\"" << vertexName[boost::source(*ite,callGraph)] << "\"];" << std::endl;
02046         oss << boost::target(*ite,callGraph) << "[label=\"" << vertexName[boost::target(*ite,callGraph)] << "\"];" << std::endl;
02047         itEN++;
02048         ite++;
02049         ie++;
02050     }
02051     oss << "}" << std::endl;
02052     // boost::write_graphviz(ofsGraph, callGraph, boost::make_label_writer(vertexName));
02053 }
02054 
02055 
02056 void MLPSolver::printProgram(const RegistryPtr& reg1, const InterpretationPtr& edb, const Tuple& idb)
02057 {
02058     DBGLOG(DBG, *reg1);
02059     RawPrinter printer(std::cerr, reg1);
02060     Interpretation::Storage bits = edb->getStorage();
02061     Interpretation::Storage::enumerator it = bits.first();
02062     while ( it!=bits.end() ) {
02063         DBGLOG(DBG, "[MLPSolver::printProgram] address: " << *it);
02064         it++;
02065     }
02066     std::cerr << "edb = " << *edb << std::endl;
02067     DBGLOG(DBG, "idb begin");
02068     printer.printmany(idb,"\n");
02069     std::cerr << std::endl;
02070     DBGLOG(DBG, "idb end");
02071 }
02072 
02073 
02074 void MLPSolver::printIdb(const RegistryPtr& reg1, const Tuple& idb)
02075 {
02076     RawPrinter printer(std::cerr, reg1);
02077     DBGLOG(DBG, "idb begin");
02078     printer.printmany(idb,"\n");
02079     std::cerr << std::endl;
02080     DBGLOG(DBG, "idb end");
02081 }
02082 
02083 
02084 void MLPSolver::printEdbIdb(const RegistryPtr& reg1, const InterpretationPtr& edb, const Tuple& idb)
02085 {
02086     std::cerr << "edb = " << *edb << std::endl;
02087     RawPrinter printer(std::cerr, reg1);
02088     DBGLOG(DBG, "idb begin");
02089     printer.printmany(idb,"\n");
02090     std::cerr << std::endl;
02091     DBGLOG(DBG, "idb end");
02092 }
02093 
02094 
02095 const Tuple& MLPSolver::getOgatomsInInst(int instIdx)
02096 {
02097     // check the size of ogatoms,
02098     // whether we should update our indexing mechanisms
02099     if ( registrySolver->ogatoms.getSize() > totalSizeInstOgatoms ) {
02100         // update instOgatoms
02101         instOgatoms.resize( moduleInstTable.size() );
02102         for (int i=totalSizeInstOgatoms; i<registrySolver->ogatoms.getSize();i++ ) {
02103             const OrdinaryAtom& oa = registrySolver->ogatoms.getByAddress(i);
02104             int n = oa.text.find( MODULEINSTSEPARATOR );
02105             if ( n != std::string::npos ) {
02106                 // MODULEINSTSEPARATOR found
02107                 std::string pref = oa.text.substr(0, n);
02108                 pref = pref.substr( 1 );
02109                 int instIdx = atoi( pref.c_str() );
02110                 instOgatoms.at(instIdx).push_back( ID(oa.kind, i) );
02111             }
02112 
02113         }
02114         totalSizeInstOgatoms = registrySolver->ogatoms.getSize();
02115     }
02116     return instOgatoms.at(instIdx);
02117 }
02118 
02119 
02120 DLVHEX_NAMESPACE_END
02121 #endif
02122 
02123 
02124 // vim:expandtab:ts=4:sw=4:
02125 // mode: C++
02126 // End: