コード例 #1
0
ファイル: clause.cpp プロジェクト: Artemid/alchemy-2
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;
}
コード例 #2
0
ファイル: clause.cpp プロジェクト: Artemid/alchemy-2
/**
 * 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;
  } 
}