Пример #1
0
SatLiteral BVMinisatSatSolver::toSatLiteral(BVMinisat::Lit lit) {
  if (lit == BVMinisat::lit_Undef) {
    return undefSatLiteral;
  }

  return SatLiteral(SatVariable(BVMinisat::var(lit)),
                    BVMinisat::sign(lit));
}
Пример #2
0
SatValue DecisionEngine::getPolarity(SatVariable var)
{
    Debug("decision") << "getPolarity(" << var <<")" << std::endl;
    if(d_relevancyStrategy != NULL) {
        Assert(isRelevant(var));
        return d_relevancyStrategy->getPolarity( d_cnfStream->getNode(SatLiteral(var)) );
    } else {
        return SAT_VALUE_UNKNOWN;
    }
}
Пример #3
0
bool DecisionEngine::isRelevant(SatVariable var)
{
    Debug("decision") << "isRelevant(" << var <<")" << std::endl;
    if(d_relevancyStrategy != NULL) {
        //Assert(d_cnfStream->hasNode(var));
        return d_relevancyStrategy->isRelevant( d_cnfStream->getNode(SatLiteral(var)) );
    } else {
        return true;
    }
}
Пример #4
0
bool JustificationHeuristic::findSplitterRec(TNode node, 
                                             SatValue desiredVal,
                                             SatLiteral* litDecision)
{
  /**
   * Main idea
   *
   * Given a boolean formula "node", the goal is to try to make it
   * evaluate to "desiredVal" (true/false). for instance if "node" is a AND
   * formula we want to make it evaluate to true, we'd like one of the
   * children to be true. this is done recursively.
   */

  Trace("jh-findSplitterRec") 
    << "findSplitterRec(" << node << ", " 
    << desiredVal << ", .. )" << std::endl; 

  /* Handle NOT as a special case */
  while (node.getKind() == kind::NOT) {
    desiredVal = invertValue(desiredVal);
    node = node[0];
  }

  if(Debug.isOn("decision")) {
    if(checkJustified(node))
      Debug("decision") << "  justified, returning" << std::endl; 
  }

  /* Base case */
  if (checkJustified(node)) {
    return false;
  }

#if defined CVC4_ASSERTIONS || defined CVC4_DEBUG
  // We don't always have a sat literal, so remember that. Will need
  // it for some assertions we make.
  bool litPresent = d_decisionEngine->hasSatLiteral(node);
  if(Debug.isOn("decision")) {
    if(!litPresent) {
      Debug("decision") << "no sat literal for this node" << std::endl;
    }
  }
  //Assert(litPresent); -- fails
#endif

  // Get value of sat literal for the node, if there is one
  SatValue litVal = tryGetSatValue(node);

  /* You'd better know what you want */
  Assert(desiredVal != SAT_VALUE_UNKNOWN, "expected known value");

  /* Good luck, hope you can get what you want */
  // if(not (litVal == desiredVal || litVal == SAT_VALUE_UNKNOWN)) {
  //   Warning() << "WARNING: IMPORTANT: Please look into this. Sat solver is asking for a decision" << std::endl
  //             << "when the assertion we are trying to justify is already unsat. OR there is a bug" << std::endl;
  //   GiveUpException();
  // }
  Assert(litVal == desiredVal || litVal == SAT_VALUE_UNKNOWN,
         "invariant violated");

  /* What type of node is this */
  Kind k = node.getKind();	
  theory::TheoryId tId = theory::kindToTheoryId(k);

  /* Some debugging stuff */
  Debug("jh-findSplitterRec") << "kind = " << k << std::endl;
  Debug("jh-findSplitterRec") << "theoryId = " << tId << std::endl;
  Debug("jh-findSplitterRec") << "node = " << node << std::endl;
  Debug("jh-findSplitterRec") << "litVal = " << litVal << std::endl;

  /**
   * If not in theory of booleans, and not a "boolean" EQUAL (IFF),
   * then check if this is something to split-on.
   */
  if(tId != theory::THEORY_BOOL
     //      && !(k == kind::EQUAL && node[0].getType().isBoolean()) 
     ) {

    // if node has embedded ites -- which currently happens iff it got
    // replaced during ite removal -- then try to resolve that first
    const IteList& l = getITEs(node);
    Trace("jh-ite") << " ite size = " << l.size() << std::endl;
    /*d_visited.insert(node);*/
    for(IteList::const_iterator i = l.begin(); i != l.end(); ++i) {
      if(d_visited.find(i->first) == d_visited.end()) {
        d_visited.insert(i->first);
        Debug("jh-ite") << "jh-ite: adding visited " << i->first << std::endl;
        if(findSplitterRec(i->second, SAT_VALUE_TRUE, litDecision))
          return true;
        Debug("jh-ite") << "jh-ite: removing visited " << i->first << std::endl;
        d_visited.erase(i->first);
      } else {
        Debug("jh-ite") << "jh-ite: already visited " << i->first << std::endl;
      }
    }

    if(litVal != SAT_VALUE_UNKNOWN) {
      setJustified(node);
      return false;
    } else {
      Assert(d_decisionEngine->hasSatLiteral(node));
      /* if(not d_decisionEngine->hasSatLiteral(node))
         throw GiveUpException(); */
      Assert(d_decisionEngine->hasSatLiteral(node));
      SatVariable v = d_decisionEngine->getSatLiteral(node).getSatVariable();
      *litDecision = SatLiteral(v, desiredVal != SAT_VALUE_TRUE );
      Trace("decision") << "decision " << *litDecision << std::endl;
      Trace("decision") << "Found something to split. Glad to be able to serve you." << std::endl;
      return true;
    }
  }

  SatValue valHard = SAT_VALUE_FALSE;
  switch (k) {

  case kind::CONST_BOOLEAN:
    Assert(node.getConst<bool>() == false || desiredVal == SAT_VALUE_TRUE);
    Assert(node.getConst<bool>() == true || desiredVal == SAT_VALUE_FALSE);
    setJustified(node);
    return false;

  case kind::AND:
    valHard = SAT_VALUE_TRUE;

  case kind::OR:
    if (desiredVal == valHard) {
      int n = node.getNumChildren();
      for(int i = 0; i < n; ++i) {
        if (findSplitterRec(node[i], valHard, litDecision)) {
          return true;
        }
      }
      Assert(litPresent == false || litVal == valHard,
             "Output should be justified");
      setJustified(node);
      return false;
    }
    else {
      SatValue valEasy = invertValue(valHard);
      int n = node.getNumChildren();
      for(int i = 0; i < n; ++i) {
        Debug("jh-findSplitterRec") << " node[i] = " << node[i] << " " 
                                 << tryGetSatValue(node[i]) << std::endl;
        if ( tryGetSatValue(node[i]) != valHard) {
          Debug("jh-findSplitterRec") << "hi"<< std::endl;
          if (findSplitterRec(node[i], valEasy, litDecision)) {
            return true;
          }
          Assert(litPresent == false || litVal == valEasy, "Output should be justified");
          setJustified(node);
          return false;
        }
      }
      if(Debug.isOn("jh-findSplitterRec")) {
        Debug("jh-findSplitterRec") << " * ** " << std::endl;
        Debug("jh-findSplitterRec") << node.getKind() << " "
                                    << node << std::endl;
        for(unsigned i = 0; i < node.getNumChildren(); ++i) 
        Debug("jh-findSplitterRec") << "child: " << tryGetSatValue(node[i]) 
                                    << std::endl;
        Debug("jh-findSplitterRec") << "node: " << tryGetSatValue(node)
                                    << std::endl;
      }
      Assert(false, "No controlling input found (2)");
    }
    break;

  case kind::IMPLIES:
    //throw GiveUpException();
    Assert(node.getNumChildren() == 2, "Expected 2 fanins");
    if (desiredVal == SAT_VALUE_FALSE) {
      if (findSplitterRec(node[0], SAT_VALUE_TRUE, litDecision)) {
        return true;
      }
      if (findSplitterRec(node[1], SAT_VALUE_FALSE, litDecision)) {
        return true;
      }
      Assert(litPresent == false || litVal == SAT_VALUE_FALSE, 
             "Output should be justified");
      setJustified(node);
      return false;
    }
    else {
      if (tryGetSatValue(node[0]) != SAT_VALUE_TRUE) {
        if (findSplitterRec(node[0], SAT_VALUE_FALSE, litDecision)) {
          return true;
        }
        Assert(litPresent == false || litVal == SAT_VALUE_TRUE, 
               "Output should be justified");
        setJustified(node);
        return false;
      }
      if (tryGetSatValue(node[1]) != SAT_VALUE_FALSE) {
        if (findSplitterRec(node[1], SAT_VALUE_TRUE, litDecision)) {
          return true;
        }
        Assert(litPresent == false || litVal == SAT_VALUE_TRUE, 
               "Output should be justified");
        setJustified(node);
        return false;
      }
      Assert(false, "No controlling input found (3)");
    }
    break;

  case kind::IFF: 
    //throw GiveUpException();
    {
    SatValue val = tryGetSatValue(node[0]);
    if (val != SAT_VALUE_UNKNOWN) {
      if (findSplitterRec(node[0], val, litDecision)) {
        return true;
      }
      if (desiredVal == SAT_VALUE_FALSE) val = invertValue(val);

      if (findSplitterRec(node[1], val, litDecision)) {
        return true;
      }
      Assert(litPresent == false || litVal == desiredVal, 
             "Output should be justified");
      setJustified(node);
      return false;
    }
    else {
      val = tryGetSatValue(node[1]);
      if (val == SAT_VALUE_UNKNOWN) val = SAT_VALUE_FALSE;
      if (desiredVal == SAT_VALUE_FALSE) val = invertValue(val);
      if (findSplitterRec(node[0], val, litDecision)) {
        return true;
      }
      Assert(false, "Unable to find controlling input (4)");
    }
    break;
  }
    
  case kind::XOR:
    //throw GiveUpException();
    {
    SatValue val = tryGetSatValue(node[0]);
    if (val != SAT_VALUE_UNKNOWN) {
      if (findSplitterRec(node[0], val, litDecision)) {
        return true;
      }
      if (desiredVal == SAT_VALUE_TRUE) val = invertValue(val);

      if (findSplitterRec(node[1], val, litDecision)) {
        return true;
      }
      Assert(litPresent == false || litVal == desiredVal, 
             "Output should be justified");
      setJustified(node);
      return false;
    }
    else {
      SatValue val = tryGetSatValue(node[1]);
      if (val == SAT_VALUE_UNKNOWN) val = SAT_VALUE_FALSE;
      if (desiredVal == SAT_VALUE_TRUE) val = invertValue(val);
      if (findSplitterRec(node[0], val, litDecision)) {
        return true;
      }
      Assert(false, "Unable to find controlling input (5)");
    }
    break;
  }

  case kind::ITE: {
    //[0]: if, [1]: then, [2]: else
    SatValue ifVal = tryGetSatValue(node[0]);
    if (ifVal == SAT_VALUE_UNKNOWN) {
      
      // are we better off trying false? if not, try true
      SatValue ifDesiredVal = 
        (tryGetSatValue(node[2]) == desiredVal ||
	 tryGetSatValue(node[1]) == invertValue(desiredVal))
	? SAT_VALUE_FALSE : SAT_VALUE_TRUE;

      if(findSplitterRec(node[0], ifDesiredVal, litDecision)) {
	return true;
      }
      Assert(false, "No controlling input found (6)");
    } else {

      // Try to justify 'if'
      if (findSplitterRec(node[0], ifVal, litDecision)) {
	return true;
      }

      // If that was successful, we need to go into only one of 'then'
      // or 'else'
      int ch = (ifVal == SAT_VALUE_TRUE) ? 1 : 2;
      int chVal = tryGetSatValue(node[ch]);
      if( (chVal == SAT_VALUE_UNKNOWN || chVal == desiredVal)
	  && findSplitterRec(node[ch], desiredVal, litDecision) ) {
	return true;
      }
    }
    Assert(litPresent == false || litVal == desiredVal,
	   "Output should be justified");
    setJustified(node);
    return false;
  }

  default:
    Assert(false, "Unexpected Boolean operator");
    break;
  }//end of switch(k)

  Unreachable();
}/* findRecSplit method */
Пример #5
0
void TheoryProxy::variableNotify(SatVariable var) {
  d_theoryEngine->preRegister(getNode(SatLiteral(var)));
}
Пример #6
0
bool Relevancy::findSplitterRec(TNode node, 
                                SatValue desiredVal)
{
  Trace("decision") 
    << "findSplitterRec([" << node.getId() << "]" << node << ", " 
    << desiredVal << ", .. )" << std::endl; 

  ++d_expense;

  /* Handle NOT as a special case */
  while (node.getKind() == kind::NOT) {
    desiredVal = invertValue(desiredVal);
    node = node[0];
  }

  /* Avoid infinite loops */
  if(d_visited.find(node) != d_visited.end()) {
    Debug("decision") << " node repeated. kind was " << node.getKind() << std::endl;
    Assert(false);
    Assert(node.getKind() == kind::ITE);
    return false;
  }

  /* Base case */
  if(checkJustified(node)) {
    return false;
  }

  /**
   * If we have already explored the subtree for some desiredVal, we
   * skip this and continue exploring the rest
   */
  if(d_polarityCache.find(node) == d_polarityCache.end()) {
    d_polarityCache[node] = desiredVal;
  } else {
    Assert(d_multipleBacktrace || options::decisionComputeRelevancy());
    return true;
  }

  d_visited.insert(node);

#if defined CVC4_ASSERTIONS || defined CVC4_TRACING
  // We don't always have a sat literal, so remember that. Will need
  // it for some assertions we make.
  bool litPresent = d_decisionEngine->hasSatLiteral(node);
  if(Trace.isOn("decision")) {
    if(!litPresent) {
      Trace("decision") << "no sat literal for this node" << std::endl;
    }
  }
  //Assert(litPresent); -- fails
#endif

  // Get value of sat literal for the node, if there is one
  SatValue litVal = tryGetSatValue(node);

  /* You'd better know what you want */
  Assert(desiredVal != SAT_VALUE_UNKNOWN, "expected known value");

  /* Good luck, hope you can get what you want */
  Assert(litVal == desiredVal || litVal == SAT_VALUE_UNKNOWN, 
         "invariant violated");

  /* What type of node is this */
  Kind k = node.getKind();	
  theory::TheoryId tId = theory::kindToTheoryId(k);

  /* Some debugging stuff */
  Trace("jh-findSplitterRec") << "kind = " << k << std::endl;
  Trace("jh-findSplitterRec") << "theoryId = " << tId << std::endl;
  Trace("jh-findSplitterRec") << "node = " << node << std::endl;
  Trace("jh-findSplitterRec") << "litVal = " << litVal << std::endl;

  /**
   * If not in theory of booleans, and not a "boolean" EQUAL (IFF),
   * then check if this is something to split-on.
   */
  if(tId != theory::THEORY_BOOL
     //      && !(k == kind::EQUAL && node[0].getType().isBoolean()) 
     ) {

    // if node has embedded ites -- which currently happens iff it got
    // replaced during ite removal -- then try to resolve that first
    const IteList& l = getITEs(node);
    Debug("jh-ite") << " ite size = " << l.size() << std::endl;
    for(unsigned i = 0; i < l.size(); ++i) {
      Assert(l[i].getKind() == kind::ITE, "Expected ITE");
      Debug("jh-ite") << " i = " << i 
                      << " l[i] = " << l[i] << std::endl;
      if(d_visited.find(node) != d_visited.end() ) continue;
      if(findSplitterRec(l[i], SAT_VALUE_TRUE)) {
        d_visited.erase(node);
        return true;
      }
    }
    Debug("jh-ite") << " ite done " << l.size() << std::endl;

    if(litVal != SAT_VALUE_UNKNOWN) {
      d_visited.erase(node);
      setJustified(node);
      return false;
    } else {
      /* if(not d_decisionEngine->hasSatLiteral(node))
         throw GiveUpException(); */
      Assert(d_decisionEngine->hasSatLiteral(node));
      SatVariable v = d_decisionEngine->getSatLiteral(node).getSatVariable();
      *d_curDecision = SatLiteral(v, desiredVal != SAT_VALUE_TRUE );
      Trace("decision") << "decision " << *d_curDecision << std::endl;
      Trace("decision") << "Found something to split. Glad to be able to serve you." << std::endl;
      d_visited.erase(node);
      return true;
    }
  }

  bool ret = false;
  SatValue flipCaseVal = SAT_VALUE_FALSE;
  switch (k) {

  case kind::CONST_BOOLEAN:
    Assert(node.getConst<bool>() == false || desiredVal == SAT_VALUE_TRUE);
    Assert(node.getConst<bool>() == true  || desiredVal == SAT_VALUE_FALSE);
    break;

  case kind::AND:
    if (desiredVal == SAT_VALUE_FALSE) ret = handleOrTrue(node, SAT_VALUE_FALSE);
    else                               ret = handleOrFalse(node, SAT_VALUE_TRUE);
    break;

  case kind::OR:
    if (desiredVal == SAT_VALUE_FALSE) ret = handleOrFalse(node, SAT_VALUE_FALSE);
    else                               ret = handleOrTrue(node, SAT_VALUE_TRUE);
    break;

  case kind::IMPLIES:
    Assert(node.getNumChildren() == 2, "Expected 2 fanins");
    if (desiredVal == SAT_VALUE_FALSE) {
      ret = findSplitterRec(node[0], SAT_VALUE_TRUE);
      if(ret) break;
      ret = findSplitterRec(node[1], SAT_VALUE_FALSE);
      break;
    }
    else {
      if (tryGetSatValue(node[0]) != SAT_VALUE_TRUE) {
        ret = findSplitterRec(node[0], SAT_VALUE_FALSE);
        //if(!ret || !d_multipleBacktrace) 
          break;
      }
      if (tryGetSatValue(node[1]) != SAT_VALUE_FALSE) {
        ret = findSplitterRec(node[1], SAT_VALUE_TRUE);
        break;
      }
      Assert(d_multipleBacktrace, "No controlling input found (3)");
    }
    break;

  case kind::XOR:
    flipCaseVal = SAT_VALUE_TRUE;
  case kind::IFF: {
    SatValue val = tryGetSatValue(node[0]);
    if (val != SAT_VALUE_UNKNOWN) {
      ret = findSplitterRec(node[0], val);
      if (ret) break;
      if (desiredVal == flipCaseVal) val = invertValue(val);
      ret = findSplitterRec(node[1], val);
    }
    else {
      val = tryGetSatValue(node[1]);
      if (val == SAT_VALUE_UNKNOWN) val = SAT_VALUE_FALSE;
      if (desiredVal == flipCaseVal) val = invertValue(val);
      ret = findSplitterRec(node[0], val);
      if(ret) break;
      Assert(false, "Unable to find controlling input (4)");
    }
    break;
  }

  case kind::ITE:
    ret = handleITE(node, desiredVal);
    break;

  default:
    Assert(false, "Unexpected Boolean operator");
    break;
  }//end of switch(k)

  d_visited.erase(node);
  if(ret == false) {
    Assert(litPresent == false || litVal ==  desiredVal,
           "Output should be justified");
    setJustified(node);
  }
  return ret;

  Unreachable();
}/* findRecSplit method */