Front end support for integer AND (#4717)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Fri, 10 Jul 2020 20:51:25 +0000 (15:51 -0500)
committerGitHub <noreply@github.com>
Fri, 10 Jul 2020 20:51:25 +0000 (13:51 -0700)
NEWS
src/api/cvc4cpp.cpp
src/api/cvc4cppkind.h
src/parser/smt2/smt2.cpp
src/printer/smt2/smt2_printer.cpp
test/regress/CMakeLists.txt
test/regress/regress1/nl/iand-native-1.smt2 [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index ee01b52129a00196de154f65bde33e55251696ac..b34d9b116aca902c88ff959e1d25e325a84c8f0c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,8 @@ New Features:
   syntax for sequences used by Z3.
 * Arrays: Added support for an `eqrange` predicate. `(eqrange a b i j)` is true
   if arrays `a` and `b` are equal on all indices within indices `i` and `j`.
+* Support for an integer operator `(_ iand n)` that returns the bitwise `and`
+  of two integers, seen as integers modulo n.
 
 Improvements:
 * New API: Added functions to retrieve the heap/nil term when using separation
index a04b5cf8580e5f40b1792eed1c319a331dd59a4f..ebafc3cc8ea3873c8258cabbac044a52ab0ff8da 100644 (file)
@@ -98,6 +98,7 @@ const static std::unordered_map<Kind, CVC4::Kind, KindHashFunction> s_kinds{
     /* Arithmetic ---------------------------------------------------------- */
     {PLUS, CVC4::Kind::PLUS},
     {MULT, CVC4::Kind::MULT},
+    {IAND, CVC4::Kind::IAND},
     {MINUS, CVC4::Kind::MINUS},
     {UMINUS, CVC4::Kind::UMINUS},
     {DIVISION, CVC4::Kind::DIVISION},
@@ -348,6 +349,7 @@ const static std::unordered_map<CVC4::Kind, Kind, CVC4::kind::KindHashFunction>
         /* Arithmetic ------------------------------------------------------ */
         {CVC4::Kind::PLUS, PLUS},
         {CVC4::Kind::MULT, MULT},
+        {CVC4::Kind::IAND, IAND},
         {CVC4::Kind::MINUS, MINUS},
         {CVC4::Kind::UMINUS, UMINUS},
         {CVC4::Kind::DIVISION, DIVISION},
@@ -593,6 +595,7 @@ const static std::unordered_map<CVC4::Kind, Kind, CVC4::kind::KindHashFunction>
 const static std::unordered_set<Kind, KindHashFunction> s_indexed_kinds(
     {RECORD_UPDATE,
      DIVISIBLE,
+     IAND,
      BITVECTOR_REPEAT,
      BITVECTOR_ZERO_EXTEND,
      BITVECTOR_SIGN_EXTEND,
@@ -1262,6 +1265,7 @@ uint32_t Op::getIndices() const
       i = d_expr->getConst<BitVectorRotateRight>().d_rotateRightAmount;
       break;
     case INT_TO_BITVECTOR: i = d_expr->getConst<IntToBitVector>().d_size; break;
+    case IAND: i = d_expr->getConst<IntAnd>().d_size; break;
     case FLOATINGPOINT_TO_UBV:
       i = d_expr->getConst<FloatingPointToUBV>().bvs.d_size;
       break;
@@ -4019,6 +4023,11 @@ Op Solver::mkOp(Kind kind, uint32_t arg) const
                *mkValHelper<CVC4::IntToBitVector>(CVC4::IntToBitVector(arg))
                     .d_expr.get());
       break;
+    case IAND:
+      res = Op(this,
+               kind,
+               *mkValHelper<CVC4::IntAnd>(CVC4::IntAnd(arg)).d_expr.get());
+      break;
     case FLOATINGPOINT_TO_UBV:
       res = Op(
           this,
index b3e88c98c34acdf95365a6842175c90b22ffebfd..1f23d0e8d0b5f60483fd62df3f5761910501a6df 100644 (file)
@@ -319,6 +319,23 @@ enum CVC4_PUBLIC Kind : int32_t
    *   mkTerm(Kind kind, const std::vector<Term>& children)
    */
   MULT,
+  /**
+   * Operator for Integer AND
+   * Parameter: 1
+   *   -[1]: Size of the bit-vector that determines the semantics of the IAND
+   * Create with:
+   *   mkOp(Kind kind, uint32_t param).
+   *
+   * Apply integer conversion to bit-vector.
+   * Parameters: 2
+   *   -[1]: Op of kind IAND
+   *   -[2]: Integer term
+   *   -[3]: Integer term
+   * Create with:
+   *   mkTerm(Op op, Term child1, Term child2)
+   *   mkTerm(Op op, const std::vector<Term>& children)
+   */
+  IAND,
 #if 0
   /* Synonym for MULT.  */
   NONLINEAR_MULT,
index 46a2e2c594bf0ca0cdae896e5a40498cff11531c..ec2009cc36799fb5d014d1e1cf10aba990a7c7f3 100644 (file)
@@ -639,6 +639,11 @@ Command* Smt2::setLogic(std::string name, bool fromCommand)
       defineVar("real.pi", d_solver->mkTerm(api::PI));
       addTranscendentalOperators();
     }
+    if (!strictModeEnabled())
+    {
+      // integer version of AND
+      addIndexedOperator(api::IAND, api::IAND, "iand");
+    }
   }
 
   if(d_logic.isTheoryEnabled(theory::THEORY_ARRAYS)) {
index 6077601bc0c813dad0d088b284679df6e7eb4b54..773c733d65e7a84ac1e45dc30df9edfc6b0161d8 100644 (file)
@@ -601,6 +601,10 @@ void Smt2Printer::toStream(std::ostream& out,
     parametricTypeChildren = true;
     out << smtKindString(k, d_variant) << " ";
     break;
+  case kind::IAND:
+    out << "(_ iand " << n.getOperator().getConst<IntAnd>().d_size << ") ";
+    stillNeedToPrintParams = false;
+    break;
 
   case kind::DIVISIBLE:
     out << "(_ divisible " << n.getOperator().getConst<Divisible>().k << ")";
@@ -1031,6 +1035,7 @@ static string smtKindString(Kind k, Variant v)
   case kind::PLUS: return "+";
   case kind::MULT:
   case kind::NONLINEAR_MULT: return "*";
+  case kind::IAND: return "iand";
   case kind::EXPONENTIAL: return "exp";
   case kind::SINE: return "sin";
   case kind::COSINE: return "cos";
index 00aa786ae6fe23468321c5ea9ef76cbe8e9aaa98..dd48b1ffff16a55208b492716f9c14756c0c9d20 100644 (file)
@@ -1402,6 +1402,7 @@ set(regress_1_tests
   regress1/nl/exp1-lb.smt2
   regress1/nl/exp_monotone.smt2
   regress1/nl/factor_agg_s.smt2
+  regress1/nl/iand-native-1.smt2
   regress1/nl/issue3300-approx-sqrt-witness.smt2
   regress1/nl/issue3441.smt2
   regress1/nl/issue3617.smt2
diff --git a/test/regress/regress1/nl/iand-native-1.smt2 b/test/regress/regress1/nl/iand-native-1.smt2
new file mode 100644 (file)
index 0000000..685922f
--- /dev/null
@@ -0,0 +1,12 @@
+; COMMAND-LINE: --iand-mode=value
+; EXPECT: sat
+(set-logic QF_NIA)
+(set-info :status sat)
+(declare-fun x () Int)
+(declare-fun y () Int)
+
+(assert (and (<= 0 x) (< x 16)))
+(assert (and (<= 0 y) (< y 16)))
+(assert (> ((_ iand 4) x y) 0))
+
+(check-sat)