Adding a heuristic to more eagerly split bounded integer variables.
authorTim King <taking@cs.nyu.edu>
Thu, 31 Jan 2013 21:34:12 +0000 (16:34 -0500)
committerTim King <taking@cs.nyu.edu>
Thu, 31 Jan 2013 21:34:25 +0000 (16:34 -0500)
src/theory/arith/options
src/theory/arith/theory_arith.cpp
src/theory/arith/theory_arith.h

index ab377c8a1dc0fb78e6f281042ecc248b62799db2..719c826ae60012bb7ae87a20af2e4e958476c577 100644 (file)
@@ -55,4 +55,9 @@ option arithMLTrick --enable-miplib-trick/--disable-miplib-trick bool :default f
  turns on the preprocessing step of attempting to infer bounds on miplib problems
 /turns off the preprocessing step of attempting to infer bounds on miplib problems
 
+option doCutAllBounded --enable-cut-all-bounded/--disable-cut-all-bounded bool :default false :read-write
+ turns on the integer solving step of periodically cutting all integer variables that have both upper and lower bounds
+/ turns off the integer solving step of periodically cutting all integer variables that have both upper and lower bounds
+
+
 endmodule
index 39ded799124c4ea9b0c4c384f5842085e9728314..52f2341293cb916da1678c505efe0e6726ddd371 100644 (file)
@@ -88,6 +88,7 @@ TheoryArith::TheoryArith(context::Context* c, context::UserContext* u, OutputCha
   d_deltaComputeCallback(this),
   d_basicVarModelUpdateCallBack(d_simplex),
   d_DELTA_ZERO(0),
+  d_fullCheckCounter(0),
   d_statistics()
 {
 }
@@ -1730,6 +1731,20 @@ void TheoryArith::check(Effort effortLevel){
   }
   Assert( d_currentPropagationList.empty());
 
+  if(!emmittedConflictOrSplit && fullEffort(effortLevel)){
+    ++d_fullCheckCounter;
+  }
+  static const int CUT_ALL_BOUNDED_PERIOD = 10;
+  if(!emmittedConflictOrSplit && fullEffort(effortLevel) &&
+     d_fullCheckCounter % CUT_ALL_BOUNDED_PERIOD == 1){
+    vector<Node> lemmas = cutAllBounded();
+    //output the lemmas
+    for(vector<Node>::const_iterator i = lemmas.begin(); i != lemmas.end(); ++i){
+      d_out->lemma(*i);
+      ++(d_statistics.d_externalBranchAndBounds);
+    }
+    emmittedConflictOrSplit = lemmas.size() > 0;
+  }
 
   if(!emmittedConflictOrSplit && fullEffort(effortLevel)){
     emmittedConflictOrSplit = splitDisequalities();
@@ -1776,6 +1791,55 @@ void TheoryArith::check(Effort effortLevel){
   Debug("arith") << "TheoryArith::check end" << std::endl;
 }
 
+Node TheoryArith::branchIntegerVariable(ArithVar x) const {
+  const DeltaRational& d = d_partialModel.getAssignment(x);
+  Assert(!d.isIntegral());
+  const Rational& r = d.getNoninfinitesimalPart();
+  const Rational& i = d.getInfinitesimalPart();
+  Trace("integers") << "integers: assignment to [[" << d_arithvarNodeMap.asNode(x) << "]] is " << r << "[" << i << "]" << endl;
+
+  Assert(! (r.getDenominator() == 1 && i.getNumerator() == 0));
+  Assert(!d.isIntegral());
+  TNode var = d_arithvarNodeMap.asNode(x);
+  Integer floor_d = d.floor();
+
+  Node ub = Rewriter::rewrite(NodeManager::currentNM()->mkNode(kind::LEQ, var, mkRationalNode(floor_d)));
+  Node lb = ub.notNode();
+
+
+  Node lem = NodeManager::currentNM()->mkNode(kind::OR, ub, lb);
+  Trace("integers") << "integers: branch & bound: " << lem << endl;
+  if(d_valuation.isSatLiteral(lem[0])) {
+    Debug("integers") << "    " << lem[0] << " == " << d_valuation.getSatValue(lem[0]) << endl;
+  } else {
+    Debug("integers") << "    " << lem[0] << " is not assigned a SAT literal" << endl;
+  }
+  if(d_valuation.isSatLiteral(lem[1])) {
+    Debug("integers") << "    " << lem[1] << " == " << d_valuation.getSatValue(lem[1]) << endl;
+    } else {
+    Debug("integers") << "    " << lem[1] << " is not assigned a SAT literal" << endl;
+  }
+  return lem;
+}
+
+std::vector<Node> TheoryArith::cutAllBounded() const{
+  vector<Node> lemmas;
+  if(options::doCutAllBounded() && getNumberOfVariables() > 0){
+    for(ArithVar iter = 0; iter != getNumberOfVariables(); ++iter){
+    //Do not include slack variables
+      const DeltaRational& d = d_partialModel.getAssignment(iter);
+      if(isInteger(iter) && !isSlackVariable(iter) &&
+         d_partialModel.hasUpperBound(iter) &&
+         d_partialModel.hasLowerBound(iter) &&
+         !d.isIntegral()){
+        Node lem = branchIntegerVariable(iter);
+        lemmas.push_back(lem);
+      }
+    }
+  }
+  return lemmas;
+}
+
 /** Returns true if the roundRobinBranching() issues a lemma. */
 Node TheoryArith::roundRobinBranch(){
   if(hasIntegerModel()){
@@ -1785,36 +1849,40 @@ Node TheoryArith::roundRobinBranch(){
 
     Assert(isInteger(v));
     Assert(!isSlackVariable(v));
-
-    const DeltaRational& d = d_partialModel.getAssignment(v);
-    const Rational& r = d.getNoninfinitesimalPart();
-    const Rational& i = d.getInfinitesimalPart();
-    Trace("integers") << "integers: assignment to [[" << d_arithvarNodeMap.asNode(v) << "]] is " << r << "[" << i << "]" << endl;
-
-    Assert(! (r.getDenominator() == 1 && i.getNumerator() == 0));
-    Assert(!d.isIntegral());
-
-    TNode var = d_arithvarNodeMap.asNode(v);
-    Integer floor_d = d.floor();
-    Integer ceil_d = d.ceiling();
-
-    Node leq = Rewriter::rewrite(NodeManager::currentNM()->mkNode(kind::LEQ, var, mkRationalNode(floor_d)));
-    Node geq = Rewriter::rewrite(NodeManager::currentNM()->mkNode(kind::GEQ, var, mkRationalNode(ceil_d)));
-
-
-    Node lem = NodeManager::currentNM()->mkNode(kind::OR, leq, geq);
-    Trace("integers") << "integers: branch & bound: " << lem << endl;
-    if(d_valuation.isSatLiteral(lem[0])) {
-      Debug("integers") << "    " << lem[0] << " == " << d_valuation.getSatValue(lem[0]) << endl;
-    } else {
-      Debug("integers") << "    " << lem[0] << " is not assigned a SAT literal" << endl;
-    }
-    if(d_valuation.isSatLiteral(lem[1])) {
-      Debug("integers") << "    " << lem[1] << " == " << d_valuation.getSatValue(lem[1]) << endl;
-    } else {
-      Debug("integers") << "    " << lem[1] << " is not assigned a SAT literal" << endl;
-    }
-    return lem;
+    return branchIntegerVariable(v);
+
+    // Assert(isInteger(v));
+    // Assert(!isSlackVariable(v));
+
+    // const DeltaRational& d = d_partialModel.getAssignment(v);
+    // const Rational& r = d.getNoninfinitesimalPart();
+    // const Rational& i = d.getInfinitesimalPart();
+    // Trace("integers") << "integers: assignment to [[" << d_arithvarNodeMap.asNode(v) << "]] is " << r << "[" << i << "]" << endl;
+
+    // Assert(! (r.getDenominator() == 1 && i.getNumerator() == 0));
+    // Assert(!d.isIntegral());
+
+    // TNode var = d_arithvarNodeMap.asNode(v);
+    // Integer floor_d = d.floor();
+    // Integer ceil_d = d.ceiling();
+
+    // Node leq = Rewriter::rewrite(NodeManager::currentNM()->mkNode(kind::LEQ, var, mkRationalNode(floor_d)));
+    // Node geq = Rewriter::rewrite(NodeManager::currentNM()->mkNode(kind::GEQ, var, mkRationalNode(ceil_d)));
+
+
+    // Node lem = NodeManager::currentNM()->mkNode(kind::OR, leq, geq);
+    // Trace("integers") << "integers: branch & bound: " << lem << endl;
+    // if(d_valuation.isSatLiteral(lem[0])) {
+    //   Debug("integers") << "    " << lem[0] << " == " << d_valuation.getSatValue(lem[0]) << endl;
+    // } else {
+    //   Debug("integers") << "    " << lem[0] << " is not assigned a SAT literal" << endl;
+    // }
+    // if(d_valuation.isSatLiteral(lem[1])) {
+    //   Debug("integers") << "    " << lem[1] << " == " << d_valuation.getSatValue(lem[1]) << endl;
+    // } else {
+    //   Debug("integers") << "    " << lem[1] << " is not assigned a SAT literal" << endl;
+    // }
+    // return lem;
   }
 }
 
index 7d1150fb15f889044de0eda99d644240cfb0bd5a..31f9bfcafead6367bee70e88db63003b250dd5e2 100644 (file)
@@ -537,6 +537,11 @@ private:
   /** Debugging only routine. Prints the model. */
   void debugPrintModel();
 
+  /** Counts the number of fullCheck calls to arithmetic. */
+  uint32_t d_fullCheckCounter;
+  std::vector<Node> cutAllBounded() const;
+  Node branchIntegerVariable(ArithVar x) const;
+
   /** These fields are designed to be accessible to TheoryArith methods. */
   class Statistics {
   public: