double Clause::getConstantTuples(const Domain* const & domain, const Database* const & db, Array<int>* const & mlnClauseTermIds, const Clause* const & varClause, PredicateTermToVariable * const & ptermToVar, ClauseToSuperClauseMap* const & clauseToSuperClause, bool useImplicit) { bool ignoreActivePreds = true; double numTrueGndings = 0; //initialize the constants tuple with the var Ids - we will fill them in //with constants as we go along Array<int> *constants = new Array<int>(*mlnClauseTermIds); //Copy the literals so that their original order in the clause is //not affected by the subsequent sorting cout<<"***************************************************************"<<endl; cout<<"Came to process the clause : "<<endl; print(cout, domain); cout<<endl; createVarIdToVarsGroundedType(domain); Array<Predicate*>* origClauseLits = new Array<Predicate*>(*predicates_); // Array of partially grounded clauses achieved by using the inverted // index Array<Array<Predicate*>* > partGroundedClauses; //Assign to each variable in clause, the corresponding variable class //(stores the list of indexed constants). It is accessed through the //predicates appearing in the clause PredicateTermToVariable::iterator itr; PredicateTerm *pterm; Predicate *pred; const Term *term; Array<Variable *> *eqVars = new Array<Variable *>(); eqVars->growToSize(mlnClauseTermIds->size()); //initialize with NULL for (int i = 0; i < eqVars->size(); i++) (*eqVars)[i] = NULL; if (useImplicit) { for (int predno = 0; predno < varClause->getNumPredicates(); predno++) { pred = varClause->getPredicate(predno); int predId = pred->getId(); for (int termno = 0; termno < pred->getNumTerms(); termno++) { term = pred->getTerm(termno); assert(!term->isConstant()); int termId = term->getId(); pterm = new PredicateTerm(predId, termno); itr = ptermToVar->find(pterm); assert(itr != ptermToVar->end()); assert(-termId < eqVars->size()); (*eqVars)[-termId] = itr->second; delete pterm; } } } if (useInverseIndex) { // Put the indexable literals first and ground them sortLiteralsByNegationAndArity(*origClauseLits, ignoreActivePreds, db); groundIndexableLiterals(domain, db, *origClauseLits, partGroundedClauses, ignoreActivePreds); } else { //Sort preds in decreasing order of #TrueGndOfLiteral/#numOfGroundings. //The larger the number of true groundings of a literal, the more likely //it is to be true, so put it in front so that we can decide whether the //clause is true early.The larger the number of groundings of the //literal, the larger the savings when we decide that preceding literals //are true. sortLiteralsByTrueDivTotalGroundings(*origClauseLits, domain, db); // Put the original clause as the only clause into partGroundedClauses Array<Predicate*>* clauseLitsCopy = new Array<Predicate*>; clauseLitsCopy->growToSize(origClauseLits->size()); for (int i = 0; i < origClauseLits->size(); i++) (*clauseLitsCopy)[i] = new Predicate(*(*origClauseLits)[i]); partGroundedClauses.append(clauseLitsCopy); } // At this point partGroundedClauses holds the nodes of the branch and // bound algorithm. This means nothing more is indexed and we must ground // out the rest of the predicates if (clausedebug) { cout << "Partially grounded clauses to be completed: " << endl; for (int pgcIdx = 0; pgcIdx < partGroundedClauses.size(); pgcIdx++) { cout << "\t"; for (int i = 0; i < partGroundedClauses[pgcIdx]->size(); i++) { (*partGroundedClauses[pgcIdx])[i]->printWithStrVar(cout, domain); cout << " "; } cout << endl; } } bool skip; // Go through each clause in partGroundedClauses (nodes of the branch and // bound algorithm if using inverted index; otherwise, the original // clause), ground them out and check truth values for (int pgcIdx = 0; pgcIdx < partGroundedClauses.size(); pgcIdx++) { //intially, the list of constants is simply the mln term ids constants->copyFrom(*mlnClauseTermIds); skip = false; // clauseLits is a sorted copy of predicates_ Array<Predicate*> clauseLits = *(partGroundedClauses[pgcIdx]); assert(clauseLits.size() == origClauseLits->size()); // Set the var to groundings in this clause to be those in clauseLits Array<int>* origVarIds = new Array<int>; for (int i = 0; i < clauseLits.size(); i++) { assert(clauseLits[i]->getNumTerms() == (*origClauseLits)[i]->getNumTerms()); // Ground variables throughout clause for (int j = 0; j < (*origClauseLits)[i]->getNumTerms(); j++) { const Term* oldTerm = (*origClauseLits)[i]->getTerm(j); const Term* newTerm = clauseLits[i]->getTerm(j); if (oldTerm->getType() == Term::VARIABLE) { int varId = oldTerm->getId(); origVarIds->append(varId); if (newTerm->getType() == Term::CONSTANT) { int constId = newTerm->getId(); assert(constId >= 0); Array<Term*>& vars = (*varIdToVarsGroundedType_)[-varId]->vars; assert(constants->size() >= (-varId+1)); if (useImplicit) { int implicitIndex = (*eqVars)[-varId]->getImplicitIndex(constId); if (implicitIndex < 0) { (*constants)[-varId] = constId; } else { if (isRepresentativePartialTuple(constants, implicitIndex, eqVars, varId)) { (*constants)[-varId] = constId; } else { skip = true; } } } else { (*constants)[-varId] = constId; } for (int k = 0; k < vars.size(); k++) vars[k]->setId(constId); } } } // Set the preds in clauseLits to point to the original predicates_ delete clauseLits[i]; clauseLits[i] = (*origClauseLits)[i]; } if (!skip) { //simulate a stack, back/front corresponds to top/bottom //ivg stands for index, varIds, groundings Array<LitIdxVarIdsGndings*> ivgArr; createAllLitIdxVarsGndings(clauseLits, ivgArr, domain, true); int ivgArrIdx = 0; //store current position in ivgArr bool lookAtNextLit = false; // while stack is not empty while (ivgArrIdx >= 0) { // get variable groundings at top of stack LitIdxVarIdsGndings* ivg = ivgArr[ivgArrIdx]; Predicate* lit = (*origClauseLits)[ivg->litIdx]; Array<int>& varIds = ivg->varIds; ArraysAccessor<int>& varGndings = ivg->varGndings; bool& litUnseen = ivg->litUnseen; bool hasComb; if (clausedebug) { cout << "Looking at lit: "; lit->printWithStrVar(cout, domain); cout << endl; } bool gotoNextComb = false; // while there are groundings of literal's variables while ((hasComb = varGndings.hasNextCombination()) || litUnseen) { // there may be no combinations if the literal is fully grounded if (litUnseen) litUnseen = false; if (hasComb) { //replace back the variables into the constants array for (int v = 0; v < varIds.size(); v++) { (*constants)[-varIds[v]] = varIds[v]; } //ground the literal's variables throughout the clause int constId; int v = 0; // index of varIds //for each variable in literal gotoNextComb = false; while (varGndings.nextItemInCombination(constId)) { int varId = varIds[v]; Array<Term*>& vars = (*varIdToVarsGroundedType_)[-varId]->vars; //store the assignment to this variable assert(constants->size() >= (-varId+1)); if (useImplicit) { int implicitIndex = (*eqVars)[-varId]->getImplicitIndex(constId); if (implicitIndex < 0) { (*constants)[-varId] = constId; } else { //in case of implicit constant, proceed only if //substitution of this constant //will form a representative tuple - see the body of the //function for the details of //what a representative tuple is if (isRepresentativePartialTuple(constants, implicitIndex, eqVars, varId)) { (*constants)[-varId] = constId; } else { gotoNextComb = true; } } } else { (*constants)[-varId] = constId; } v++; for (int i = 0; i < vars.size(); i++) vars[i]->setId(constId); } //a sanity check - for debugging purposes assert(varIds.size() == v); } //removeRedundantPredicates(); if (clausedebug) { cout << "Clause is now: "; printWithWtAndStrVar(cout, domain); cout << endl; } if (gotoNextComb) continue; if (literalOrSubsequentLiteralsAreTrue(lit, ivg->subseqGndLits, db)) { if (clausedebug) cout << "Clause satisfied" << endl; //count the number of combinations of remaining variables double numComb = 1; for (int i = ivgArrIdx + 1; i < ivgArr.size(); i++) { int numVar = ivgArr[i]->varGndings.getNumArrays(); for (int j = 0; j < numVar; j++) numComb *= ivgArr[i]->varGndings.getArray(j)->size(); } numTrueGndings += numComb; } else { // if there are more literals if (ivgArrIdx + 1 < ivgArr.size()) { if (clausedebug) cout << "Moving to next literal" << endl; lookAtNextLit = true; ivgArrIdx++; // move up stack break; } //At this point all the literals are grounded, and they are //either unknown or false (have truth values opposite of their //senses). //- this so that it matches the hypercube representation. //There is no real need to simplify the clause! if (false) { ++numTrueGndings; } else { //Create a new constant tuple addConstantTuple(domain, db, varClause, constants, eqVars, clauseToSuperClause, useImplicit); } } } //while there are groundings of literal's variables //if we exit the while loop in order to look at next literal //(i.e. without considering all groundings of current literal) if (lookAtNextLit) { lookAtNextLit = false; } //mv down stack else { varGndings.reset(); litUnseen = true; ivgArrIdx--; //replace back the variables into the constants array for (int v = 0; v < varIds.size(); v++) { (*constants)[-varIds[v]] = varIds[v]; } } } // while stack is not empty deleteAllLitIdxVarsGndings(ivgArr); } //end skip // Restore variables for (int i = 0; i < origVarIds->size(); i++) { int varId = (*origVarIds)[i]; assert(varId < 0); Array<Term*>& vars = (*varIdToVarsGroundedType_)[-varId]->vars; for (int j = 0; j < vars.size(); j++) vars[j]->setId(varId); (*varIdToVarsGroundedType_)[-varId]->isGrounded = false; } delete origVarIds; delete partGroundedClauses[pgcIdx]; } delete origClauseLits; delete constants; return numTrueGndings; }
/** * Creates and adds a ground active clause. * * @param activeGroundClauses If not NULL, then active GroundClauses are * accumulated here. * @param seenGndPreds GroundPredicates which have been seen before. Used when * accumulating GroundClauses. * @param db Database used to check truth values and evidence status of * predicates. * @param getSatisfied If true, satisfied clauses are also retrieved. */ bool Clause::createAndAddActiveClause( Array<GroundClause *> * const & activeGroundClauses, GroundPredicateHashArray* const& seenGndPreds, const Database* const & db, bool const & getSatisfied) { bool accumulateClauses = activeGroundClauses; Predicate *cpred; PredicateSet predSet; // used to detect duplicates PredicateSet::iterator iter; GroundClause *groundClause; Clause* clause = NULL; bool isEmpty = true; for (int i = 0; i < predicates_->size(); i++) { Predicate* predicate = (*predicates_)[i]; assert(predicate); assert(predicate->isGrounded()); if ( (iter = predSet.find(predicate)) != predSet.end() ) { // The two gnd preds are of opp sense, so clause must be satisfied // and no point in adding it if (wt_ >= 0 && !getSatisfied && (*iter)->getSense() != predicate->getSense()) { if (clause) delete clause; return false; } // Since the two gnd preds are identical, no point adding a dup continue; } else predSet.insert(predicate); bool isEvidence = db->getEvidenceStatus(predicate); if (clausedebug >= 2) { cout << "isEvidence " << isEvidence << endl; predicate->printWithStrVar(cout, db->getDomain()); cout << endl; } if (!isEvidence) isEmpty = false; // True evidence in a neg. clause: Discard clause if (wt_ < 0 && isEvidence && !getSatisfied && db->sameTruthValueAndSense(db->getValue(predicate), predicate->getSense())) { if (clause) delete clause; return false; } // Add only non-evidence prdicates if (accumulateClauses && !isEvidence) { if (!clause) clause = new Clause(); cpred = new Predicate(*predicate, clause); assert(cpred); if (clausedebug >= 2) { cout << "Appending pred "; predicate->printWithStrVar(cout, db->getDomain()); cout << " to clause "; clause->print(cout, db->getDomain()); cout << endl; } clause->appendPredicate(cpred); if (clausedebug >= 2) cout << "Appended pred to clause" << endl; } } // If the clause is empty after taking evidence into account, it should // be discarded if (isEmpty) { if (clausedebug >= 2) cout << "Clause is empty" << endl; assert(!clause); return false; } // Came to this point means that the clause is active (and hence nonEmpty) else { // Add the corresponding ground clause if accumulateClauses is true if (accumulateClauses) { assert(clause); if (clausedebug >= 2) cout << "Canonicalizing clause" << endl; clause->canonicalizeWithoutVariables(); groundClause = new GroundClause(clause, seenGndPreds); if (isHardClause_) groundClause->setWtToHardWt(); if (clausedebug >= 2) cout << "Appending ground clause to active set" << endl; activeGroundClauses->appendUnique(groundClause); delete clause; } return true; } }