Return choice functions for approximate values in get-value (#3304)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Wed, 25 Sep 2019 01:56:21 +0000 (20:56 -0500)
committerGitHub <noreply@github.com>
Wed, 25 Sep 2019 01:56:21 +0000 (20:56 -0500)
src/printer/smt2/smt2_printer.cpp
src/smt/smt_engine.cpp
src/theory/theory_model.cpp
test/regress/CMakeLists.txt
test/regress/regress0/nl/sqrt2-value.smt2 [new file with mode: 0644]

index e9e8f2ea08066b8c230b5c1d5f059d8c171bd021..37a73db2dc27ee87b57515a6e56684bc7a4bea99 100644 (file)
@@ -541,8 +541,7 @@ void Smt2Printer::toStream(std::ostream& out,
     return;
 
   case kind::LAMBDA:
-    out << smtKindString(k, d_variant) << " ";
-    break;
+  case kind::CHOICE: out << smtKindString(k, d_variant) << " "; break;
 
   // arith theory
   case kind::PLUS:
@@ -1026,6 +1025,7 @@ static string smtKindString(Kind k, Variant v)
 
   case kind::LAMBDA:
     return "lambda";
+  case kind::CHOICE: return "choice";
 
   // arith theory
   case kind::PLUS: return "+";
@@ -1345,15 +1345,8 @@ void Smt2Printer::toStream(std::ostream& out, const Model& m) const
   }
   //print the model
   out << "(model" << endl;
-  // print approximations
-  if (m.hasApproximations())
-  {
-    std::vector<std::pair<Expr, Expr> > approx = m.getApproximations();
-    for (unsigned i = 0, size = approx.size(); i < size; i++)
-    {
-      out << "(approximation " << approx[i].second << ")" << std::endl;
-    }
-  }
+  // don't need to print approximations since they are built into choice
+  // functions in the values of variables.
   this->Printer::toStream(out, m);
   out << ")" << endl;
   //print the heap model, if it exists
index fa318aaf17cb5f2b958609a373d99af600121d6b..305c36d13ed6bb6f63af0c50e014d22d7503e26b 100644 (file)
@@ -4212,8 +4212,10 @@ Expr SmtEngine::getValue(const Expr& ex) const
              || resultNode.getType().isSubtypeOf(expectedType),
          "Run with -t smt for details.");
 
-  // ensure it's a constant
-  Assert(resultNode.getKind() == kind::LAMBDA || resultNode.isConst());
+  // Ensure it's a constant, or a lambda (for uninterpreted functions), or
+  // a choice (for approximate values).
+  Assert(resultNode.getKind() == kind::LAMBDA
+         || resultNode.getKind() == kind::CHOICE || resultNode.isConst());
 
   if(options::abstractValues() && resultNode.getType().isArray()) {
     resultNode = d_private->mkAbstractValue(resultNode);
index e0798aa3c5bba6a9cae2a52e6880e7330c8555e9..f65d3a2033320e441c552b497e0dde2871ccb015 100644 (file)
@@ -256,6 +256,18 @@ Node TheoryModel::getModelValue(TNode n, bool hasBoundVars) const
     d_modelCache[n] = ret;
     return ret;
   }
+  // it might be approximate
+  std::map<Node, Node>::const_iterator ita = d_approximations.find(n);
+  if (ita != d_approximations.end())
+  {
+    // If the value of n is approximate based on predicate P(n), we return
+    // choice z. P(z).
+    Node v = nm->mkBoundVar(n.getType());
+    Node bvl = nm->mkNode(BOUND_VAR_LIST, v);
+    Node ret = nm->mkNode(CHOICE, bvl, ita->second.substitute(n, v));
+    d_modelCache[n] = ret;
+    return ret;
+  }
   // must rewrite the term at this point
   ret = Rewriter::rewrite(n);
   // return the representative of the term in the equality engine, if it exists
index a9767044667f9680b66fbafe27553684a8637db2..6dc44e3145e057484edb699e4dc901af5288a734 100644 (file)
@@ -540,6 +540,7 @@ set(regress_0_tests
   regress0/nl/nta/tan-rewrite.smt2
   regress0/nl/real-as-int.smt2
   regress0/nl/real-div-ufnra.smt2
+  regress0/nl/sqrt2-value.smt2
   regress0/nl/subs0-unsat-confirm.smt2
   regress0/nl/very-easy-sat.smt2
   regress0/nl/very-simple-unsat.smt2
diff --git a/test/regress/regress0/nl/sqrt2-value.smt2 b/test/regress/regress0/nl/sqrt2-value.smt2
new file mode 100644 (file)
index 0000000..649a792
--- /dev/null
@@ -0,0 +1,9 @@
+; SCRUBBER: sed -e 's/choice.*/choice/'
+; EXPECT: sat
+; EXPECT: ((x (choice
+(set-option :produce-models true)
+(set-logic ALL)
+(declare-fun x () Real)
+(assert (= (* x x) 2))
+(check-sat)
+(get-value (x))