Frontend support for the choice operator (#4175)
authormudathirmahgoub <mudathir-mahgoubyahia@uiowa.edu>
Mon, 30 Mar 2020 14:04:52 +0000 (09:04 -0500)
committerGitHub <noreply@github.com>
Mon, 30 Mar 2020 14:04:52 +0000 (09:04 -0500)
Added the operator choice to Smt2.g and Cvc.g.
Removed the unused parameter hasBoundVars from TheoryModel::getModelValue

src/parser/cvc/Cvc.g
src/parser/smt2/Smt2.g
src/theory/builtin/theory_builtin.cpp
src/theory/builtin/theory_builtin.h
src/theory/theory_model.cpp
src/theory/theory_model.h
test/regress/CMakeLists.txt
test/regress/regress0/parser/choice.cvc [new file with mode: 0644]
test/regress/regress0/parser/choice.smt2 [new file with mode: 0644]

index 03338961067c4eac7d3e7f983cee3351612276e9..8b3b96cfdd5ecb138e4f1178c9e520382b41dfef 100644 (file)
@@ -114,6 +114,7 @@ tokens {
 
   FORALL_TOK = 'FORALL';
   EXISTS_TOK = 'EXISTS';
+  CHOICE_TOK = 'CHOICE';
   PATTERN_TOK = 'PATTERN';
 
   LAMBDA_TOK = 'LAMBDA';
@@ -343,7 +344,8 @@ int getOperatorPrecedence(int type) {
   case IMPLIES_TOK: return 30;// right-to-left
   case IFF_TOK: return 31;
   case FORALL_TOK:
-  case EXISTS_TOK: return 32;
+  case EXISTS_TOK:
+  case CHOICE_TOK: return 32;
   case ASSIGN_TOK:
   case IN_TOK: return 33;
 
@@ -1465,7 +1467,7 @@ prefixFormula[CVC4::api::Term& f]
   api::Term ipl;
 }
     /* quantifiers */
-  : ( FORALL_TOK { k = api::FORALL; } | EXISTS_TOK { k = api::EXISTS; } )
+  : ( FORALL_TOK { k = api::FORALL; } | EXISTS_TOK { k = api::EXISTS; } | CHOICE_TOK { k = api::CHOICE; } )
     { PARSER_STATE->pushScope(); } LPAREN
     boundVarDecl[ids,t]
     { for(std::vector<std::string>::const_iterator i = ids.begin(); i != ids.end(); ++i) {
index 0c42678aa31ba65cf7a2eb76601d395edc63678f..d0a73ce6a436171f30627520b92fa3a28bfdd905 100644 (file)
@@ -2312,6 +2312,7 @@ quantOp[CVC4::api::Kind& kind]
 }
   : EXISTS_TOK    { $kind = api::EXISTS; }
   | FORALL_TOK    { $kind = api::FORALL; }
+  | CHOICE_TOK    { $kind = api::CHOICE; }
   ;
 
 /**
@@ -2682,6 +2683,7 @@ ATTRIBUTE_INST_LEVEL : ':quant-inst-max-level';
 // operators (NOTE: theory symbols go here)
 EXISTS_TOK        : 'exists';
 FORALL_TOK        : 'forall';
+CHOICE_TOK        : { !PARSER_STATE->strictModeEnabled() }? 'choice';
 
 EMP_TOK : { PARSER_STATE->isTheoryEnabled(theory::THEORY_SEP) }? 'emp';
 TUPLE_CONST_TOK: { PARSER_STATE->isTheoryEnabled(theory::THEORY_DATATYPES) }? 'mkTuple';
index b819b883d9ac2113d46977c2dfae3efbaeb391a1..505aa503f5e5297e752e0e9defa78e60a4a44d65 100644 (file)
  **/
 
 #include "theory/builtin/theory_builtin.h"
-#include "theory/valuation.h"
+
 #include "expr/kind.h"
 #include "theory/theory_model.h"
+#include "theory/valuation.h"
 
 using namespace std;
 
@@ -25,6 +26,28 @@ namespace CVC4 {
 namespace theory {
 namespace builtin {
 
-}/* CVC4::theory::builtin namespace */
-}/* CVC4::theory */
-}/* CVC4 namespace */
+TheoryBuiltin::TheoryBuiltin(context::Context* c,
+                             context::UserContext* u,
+                             OutputChannel& out,
+                             Valuation valuation,
+                             const LogicInfo& logicInfo)
+    : Theory(THEORY_BUILTIN, c, u, out, valuation, logicInfo)
+{
+}
+
+std::string TheoryBuiltin::identify() const
+{
+  return std::string("TheoryBuiltin");
+}
+
+void TheoryBuiltin::finishInit()
+{
+  // choice nodes are not evaluated in getModelValue
+  TheoryModel* theoryModel = d_valuation.getModel();
+  Assert(theoryModel != nullptr);
+  theoryModel->setUnevaluatedKind(kind::CHOICE);
+}
+
+}  // namespace builtin
+}  // namespace theory
+}  // namespace CVC4
index 8a7d1bf7b0d88026f677cff96a86da54d9441614..6e99ef04049379b74cd34ea1a498fa34a67253d7 100644 (file)
@@ -25,17 +25,23 @@ namespace CVC4 {
 namespace theory {
 namespace builtin {
 
-class TheoryBuiltin : public Theory {
-public:
-  TheoryBuiltin(context::Context* c, context::UserContext* u,
-                OutputChannel& out, Valuation valuation,
-                const LogicInfo& logicInfo)
-      : Theory(THEORY_BUILTIN, c, u, out, valuation, logicInfo) {}
-  std::string identify() const override { return std::string("TheoryBuiltin"); }
-};/* class TheoryBuiltin */
-
-}/* CVC4::theory::builtin namespace */
-}/* CVC4::theory namespace */
-}/* CVC4 namespace */
+class TheoryBuiltin : public Theory
+{
+ public:
+  TheoryBuiltin(context::Context* c,
+                context::UserContext* u,
+                OutputChannel& out,
+                Valuation valuation,
+                const LogicInfo& logicInfo);
+
+  std::string identify() const override;
+
+  /** finish initialization */
+  void finishInit() override;
+}; /* class TheoryBuiltin */
+
+}  // namespace builtin
+}  // namespace theory
+}  // namespace CVC4
 
 #endif /* CVC4__THEORY__BUILTIN__THEORY_BUILTIN_H */
index 7bfb0e8f3ed9c8c7a9f23d33262293d965eb3844..dae7261e500d2937c7369b7583752e7bdd9e8e50 100644 (file)
@@ -147,7 +147,7 @@ Node TheoryModel::getValue(TNode n) const
   Node nn = d_substitutions.apply(n);
   Debug("model-getvalue-debug") << "[model-getvalue] getValue : substitute " << n << " to " << nn << std::endl;
   //get value in model
-  nn = getModelValue(nn, false);
+  nn = getModelValue(nn);
   if (nn.isNull()) return nn;
   if(options::condenseFunctionValues() || nn.getKind() != kind::LAMBDA) {
     //normalize
@@ -193,7 +193,7 @@ Cardinality TheoryModel::getCardinality( Type t ) const{
   }
 }
 
-Node TheoryModel::getModelValue(TNode n, bool hasBoundVars) const
+Node TheoryModel::getModelValue(TNode n) const
 {
   std::unordered_map<Node, Node, NodeHashFunction>::iterator it = d_modelCache.find(n);
   if (it != d_modelCache.end()) {
@@ -220,7 +220,7 @@ Node TheoryModel::getModelValue(TNode n, bool hasBoundVars) const
     std::vector<Node> children;
     if (n.getKind() == APPLY_UF)
     {
-      Node op = getModelValue(n.getOperator(), hasBoundVars);
+      Node op = getModelValue(n.getOperator());
       Debug("model-getvalue-debug") << "  operator : " << op << std::endl;
       children.push_back(op);
     }
@@ -231,7 +231,7 @@ Node TheoryModel::getModelValue(TNode n, bool hasBoundVars) const
     // evaluate the children
     for (unsigned i = 0, nchild = n.getNumChildren(); i < nchild; ++i)
     {
-      ret = getModelValue(n[i], hasBoundVars);
+      ret = getModelValue(n[i]);
       Debug("model-getvalue-debug")
           << "  " << n << "[" << i << "] is " << ret << std::endl;
       children.push_back(ret);
index d2ce63ac59e75d0eef3de988c53963e9a2ed801f..d984fbc6bf11c43954b949fff089ba1fcf5db99f 100644 (file)
@@ -390,9 +390,8 @@ public:
   /** Get model value function.
    *
    * This function is a helper function for getValue.
-   *   hasBoundVars is whether n may contain bound variables
    */
-  Node getModelValue(TNode n, bool hasBoundVars = false) const;
+  Node getModelValue(TNode n) const;
   /** add term internal
    *
    * This will do any model-specific processing necessary for n,
index a5acd62fb5ee7b6bff98d787161858bc552fc7a1..d843eb5ed8077632e76072e0fd7febb86c32fa54 100644 (file)
@@ -610,6 +610,8 @@ set(regress_0_tests
   regress0/parser/as.smt2
   regress0/parser/bv_arity_smt2.6.smt2
   regress0/parser/bv_nat.smt2
+  regress0/parser/choice.cvc
+  regress0/parser/choice.smt2
   regress0/parser/constraint.smt2
   regress0/parser/declarefun-emptyset-uf.smt2
   regress0/parser/force_logic_set_logic.smt2
diff --git a/test/regress/regress0/parser/choice.cvc b/test/regress/regress0/parser/choice.cvc
new file mode 100644 (file)
index 0000000..e0ebac0
--- /dev/null
@@ -0,0 +1,10 @@
+% EXPECT: sat
+
+a : INT;
+b : INT;
+c : INT;
+
+ASSERT (CHOICE(x: INT): x = a) = 1;
+ASSERT (CHOICE(x: INT): x = b) = 2;
+
+CHECKSAT;
\ No newline at end of file
diff --git a/test/regress/regress0/parser/choice.smt2 b/test/regress/regress0/parser/choice.smt2
new file mode 100644 (file)
index 0000000..19763e2
--- /dev/null
@@ -0,0 +1,10 @@
+(set-logic ALL)
+(set-info :status sat)
+(declare-fun a () Int)
+(declare-fun b () Int)
+(declare-fun c () Int)
+(assert (= (choice ((x Int)) (= x a)) 1))
+(assert (= (choice ((x Int)) (= x b)) 2))
+;(assert (let ((x (choice ((x Int)) true))) (and (distinct a b x)(= x c))))
+(check-sat)
+