Support sequences of fixed finite cardinality (#7371)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Tue, 19 Oct 2021 23:01:11 +0000 (18:01 -0500)
committerGitHub <noreply@github.com>
Tue, 19 Oct 2021 23:01:11 +0000 (18:01 -0500)
The only open case is dynamic cardinality types (e.g. uninterpreted sorts when FMF is enabled).

src/theory/incomplete_id.cpp
src/theory/incomplete_id.h
src/theory/strings/base_solver.cpp
test/regress/CMakeLists.txt
test/regress/regress1/strings/seq-cardinality.smt2 [new file with mode: 0644]

index a2a3baa0f60b5bb829be9075f8b8fddbe09b8f9f..c763fb9a05f77ceaa38c9e2cdd3f8f0906dc6bc5 100644 (file)
@@ -40,6 +40,8 @@ const char* toString(IncompleteId i)
     case IncompleteId::STRINGS_LOOP_SKIP: return "STRINGS_LOOP_SKIP";
     case IncompleteId::STRINGS_REGEXP_NO_SIMPLIFY:
       return "STRINGS_REGEXP_NO_SIMPLIFY";
+    case IncompleteId::SEQ_FINITE_DYNAMIC_CARDINALITY:
+      return "SEQ_FINITE_DYNAMIC_CARDINALITY";
     case IncompleteId::UF_HO_EXT_DISABLED: return "UF_HO_EXT_DISABLED";
     case IncompleteId::UF_CARD_DISABLED: return "UF_CARD_DISABLED";
     case IncompleteId::UF_CARD_MODE: return "UF_CARD_MODE";
index 951c2a94f9ebf2b9e54cee88faa229d9b35bc64d..aaa458d8e24624d40a4ac49d553011fe191af550 100644 (file)
@@ -52,6 +52,11 @@ enum class IncompleteId
   STRINGS_LOOP_SKIP,
   // we could not simplify a regular expression membership
   STRINGS_REGEXP_NO_SIMPLIFY,
+  // incomplete due to sequence of a dynamic finite type (e.g. a type that
+  // we know is finite, but its exact cardinality is not fixed. For example,
+  // when finite model finding is enabled, uninterpreted sorts have a
+  // cardinality that depends on their interpretation in the current model).
+  SEQ_FINITE_DYNAMIC_CARDINALITY,
   // HO extensionality axiom was disabled
   UF_HO_EXT_DISABLED,
   // UF+cardinality solver was disabled
index b675d24440cc8977b98feee914771e0c3fbc0ab3..9396e3e8797a60674cafbbfdd1820bc1b876374f 100644 (file)
@@ -17,6 +17,7 @@
 #include "theory/strings/base_solver.h"
 
 #include "expr/sequence.h"
+#include "options/quantifiers_options.h"
 #include "options/strings_options.h"
 #include "theory/rewriter.h"
 #include "theory/strings/theory_strings_utils.h"
@@ -539,8 +540,41 @@ void BaseSolver::checkCardinalityType(TypeNode tn,
       // infinite cardinality, we are fine
       return;
     }
-    // TODO (cvc4-projects #23): how to handle sequence for finite types?
-    return;
+    // we check the cardinality class of the type, assuming that FMF is
+    // disabled.
+    if (isCardinalityClassFinite(etn.getCardinalityClass(), false))
+    {
+      Cardinality c = etn.getCardinality();
+      bool smallCardinality = false;
+      if (!c.isLargeFinite())
+      {
+        Integer ci = c.getFiniteCardinality();
+        if (ci.fitsUnsignedInt())
+        {
+          smallCardinality = true;
+          typeCardSize = ci.toUnsignedInt();
+        }
+      }
+      if (!smallCardinality)
+      {
+        // if it is large finite, then there is no way we could have
+        // constructed that many terms in memory, hence there is nothing
+        // to do.
+        return;
+      }
+    }
+    else
+    {
+      Assert(options().quantifiers.finiteModelFind);
+      // we are in a case where the cardinality of the type is infinite
+      // if not FMF, and finite given the Env's option value for FMF. In this
+      // case, FMF must be true, and the cardinality is finite and dynamic
+      // (i.e. it depends on the model's finite interpretation for uninterpreted
+      // sorts). We do not know how to handle this case, we set incomplete.
+      // TODO (cvc4-projects #23): how to handle sequence for finite types?
+      d_im.setIncomplete(IncompleteId::SEQ_FINITE_DYNAMIC_CARDINALITY);
+      return;
+    }
   }
   // for each collection
   for (unsigned i = 0, csize = cols.size(); i < csize; ++i)
index 84f0ef408004ab421643bb7e056c2e6fe2a3857d..a0f6f79990c1a0ac1be83fa078f1699b3f302732 100644 (file)
@@ -2268,6 +2268,7 @@ set(regress_1_tests
   regress1/strings/rev-ex5.smt2
   regress1/strings/rew-020618.smt2
   regress1/strings/rew-check1.smt2
+  regress1/strings/seq-cardinality.smt2
   regress1/strings/seq-quant-infinite-branch.smt2
   regress1/strings/simple-re-consume.smt2
   regress1/strings/stoi-400million.smt2
diff --git a/test/regress/regress1/strings/seq-cardinality.smt2 b/test/regress/regress1/strings/seq-cardinality.smt2
new file mode 100644 (file)
index 0000000..93a4985
--- /dev/null
@@ -0,0 +1,11 @@
+(set-logic ALL)
+(set-info :status unsat)
+(declare-fun x () (Seq (_ BitVec 1)))
+(declare-fun y () (Seq (_ BitVec 1)))
+(declare-fun z () (Seq (_ BitVec 1)))
+
+(assert (= (seq.len x) 1))
+(assert (= (seq.len y) 1))
+(assert (= (seq.len z) 1))
+(assert (distinct x y z))
+(check-sat)