Add identifiers for sources of incompleteness (#6311)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Thu, 8 Apr 2021 14:15:31 +0000 (09:15 -0500)
committerGitHub <noreply@github.com>
Thu, 8 Apr 2021 14:15:31 +0000 (14:15 +0000)
This PR classifies all internal kinds of incompleteness as identifiers.

It makes it so TheoryEngine records an identifier when its incomplete flag is set.

The next step will be to possibly communicate this value to the user.

34 files changed:
src/CMakeLists.txt
src/theory/arith/nl/nonlinear_extension.cpp
src/theory/arith/theory_arith.cpp
src/theory/engine_output_channel.cpp
src/theory/engine_output_channel.h
src/theory/incomplete_id.cpp [new file with mode: 0644]
src/theory/incomplete_id.h [new file with mode: 0644]
src/theory/inference_id.h
src/theory/output_channel.h
src/theory/quantifiers/cegqi/inst_strategy_cegqi.cpp
src/theory/quantifiers/cegqi/inst_strategy_cegqi.h
src/theory/quantifiers/fmf/model_engine.cpp
src/theory/quantifiers/fmf/model_engine.h
src/theory/quantifiers/instantiate.cpp
src/theory/quantifiers/instantiate.h
src/theory/quantifiers/quant_module.h
src/theory/quantifiers/quant_util.h
src/theory/quantifiers/sygus/synth_conjecture.cpp
src/theory/quantifiers_engine.cpp
src/theory/sep/theory_sep.cpp
src/theory/sets/theory_sets_private.cpp
src/theory/sets/theory_sets_private.h
src/theory/strings/core_solver.cpp
src/theory/strings/inference_manager.cpp
src/theory/strings/inference_manager.h
src/theory/strings/regexp_solver.cpp
src/theory/theory_engine.cpp
src/theory/theory_engine.h
src/theory/theory_inference_manager.cpp
src/theory/theory_inference_manager.h
src/theory/uf/cardinality_extension.cpp
src/theory/uf/ho_extension.cpp
src/theory/uf/theory_uf.cpp
test/unit/test_smt.h

index 4db7b202ecbfdb5215240fa4a2eac85a3b024be0..918c5a45aeb7db90c1e5b6fb69e2755a4b85f788 100644 (file)
@@ -632,6 +632,8 @@ libcvc4_add_sources(
   theory/fp/theory_fp_type_rules.cpp
   theory/fp/type_enumerator.h
   theory/interrupted.h
+  theory/incomplete_id.cpp
+  theory/incomplete_id.h
   theory/inference_id.cpp
   theory/inference_id.h
   theory/inference_manager_buffered.cpp
index 03563006b1421a418a5525220f49697175fb3bf4..16142886f67609d81061509bfc0fe2c6f4b1ed09 100644 (file)
@@ -489,7 +489,7 @@ Result::Sat NonlinearExtension::modelBasedRefinement(const std::set<Node>& termS
         Trace("nl-ext") << "...failed to send lemma in "
                            "NonLinearExtension, set incomplete"
                         << std::endl;
-        d_containing.getOutputChannel().setIncomplete();
+        d_containing.getOutputChannel().setIncomplete(IncompleteId::ARITH_NL);
         return Result::Sat::SAT_UNKNOWN;
       }
     }
index e68ff7d11d7a0fcbaa75664040f110a2f1cf879f..2c339cd0c32b7fcd57d290da78625bed50de15ec 100644 (file)
@@ -206,7 +206,7 @@ void TheoryArith::postCheck(Effort level)
     else if (d_internal->foundNonlinear())
     {
       // set incomplete
-      d_im.setIncomplete();
+      d_im.setIncomplete(IncompleteId::ARITH_NL_DISABLED);
     }
   }
 }
index 08fa0164b2704ee6cfd66d200ef50c8088894d63..709ecbfa17e4a6b36f2e3caa5462c300ec79150c 100644 (file)
@@ -139,10 +139,10 @@ void EngineOutputChannel::requirePhase(TNode n, bool phase)
   d_engine->getPropEngine()->requirePhase(n, phase);
 }
 
-void EngineOutputChannel::setIncomplete()
+void EngineOutputChannel::setIncomplete(IncompleteId id)
 {
-  Trace("theory") << "setIncomplete()" << std::endl;
-  d_engine->setIncomplete(d_theory);
+  Trace("theory") << "setIncomplete(" << id << ")" << std::endl;
+  d_engine->setIncomplete(d_theory, id);
 }
 
 void EngineOutputChannel::spendResource(ResourceManager::Resource r)
index 8b497547bc7a7e632add85369c9737f15d3fa86c..a9bae38a379c4da523f6dddf1fe0170e811a56d0 100644 (file)
@@ -58,7 +58,7 @@ class EngineOutputChannel : public theory::OutputChannel
 
   void requirePhase(TNode n, bool phase) override;
 
-  void setIncomplete() override;
+  void setIncomplete(IncompleteId id) override;
 
   void spendResource(ResourceManager::Resource r) override;
 
diff --git a/src/theory/incomplete_id.cpp b/src/theory/incomplete_id.cpp
new file mode 100644 (file)
index 0000000..340e2c2
--- /dev/null
@@ -0,0 +1,55 @@
+/*********************                                                        */
+/*! \file incomplete_id.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ **   Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ ** in the top-level source directory and their institutional affiliations.
+ ** All rights reserved.  See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Implementation of incompleteness enumeration.
+ **/
+
+#include "theory/incomplete_id.h"
+
+#include <iostream>
+
+namespace cvc5 {
+namespace theory {
+
+const char* toString(IncompleteId i)
+{
+  switch (i)
+  {
+    case IncompleteId::ARITH_NL_DISABLED: return "ARITH_NL_DISABLED";
+    case IncompleteId::ARITH_NL: return "ARITH_NL";
+    case IncompleteId::QUANTIFIERS: return "QUANTIFIERS";
+    case IncompleteId::QUANTIFIERS_SYGUS_NO_VERIFY:
+      return "QUANTIFIERS_SYGUS_NO_VERIFY";
+    case IncompleteId::QUANTIFIERS_CEGQI: return "QUANTIFIERS_CEGQI";
+    case IncompleteId::QUANTIFIERS_FMF: return "QUANTIFIERS_FMF";
+    case IncompleteId::QUANTIFIERS_RECORDED_INST:
+      return "QUANTIFIERS_RECORDED_INST";
+    case IncompleteId::SEP: return "SEP";
+    case IncompleteId::SETS_RELS_CARD: return "SETS_RELS_CARD";
+    case IncompleteId::STRINGS_LOOP_SKIP: return "STRINGS_LOOP_SKIP";
+    case IncompleteId::STRINGS_REGEXP_NO_SIMPLIFY:
+      return "STRINGS_REGEXP_NO_SIMPLIFY";
+    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";
+    case IncompleteId::UNKNOWN: return "UNKNOWN";
+    default: return "?IncompleteId?";
+  }
+}
+
+std::ostream& operator<<(std::ostream& out, IncompleteId i)
+{
+  out << toString(i);
+  return out;
+}
+
+}  // namespace theory
+}  // namespace cvc5
diff --git a/src/theory/incomplete_id.h b/src/theory/incomplete_id.h
new file mode 100644 (file)
index 0000000..67754b6
--- /dev/null
@@ -0,0 +1,83 @@
+/*********************                                                        */
+/*! \file incomplete_id.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ **   Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ ** in the top-level source directory and their institutional affiliations.
+ ** All rights reserved.  See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Incompleteness enumeration.
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef CVC4__THEORY__INCOMPLETE_ID_H
+#define CVC4__THEORY__INCOMPLETE_ID_H
+
+#include <iosfwd>
+
+namespace cvc5 {
+namespace theory {
+
+/**
+ * Reasons for incompleteness in CVC4.
+ */
+enum class IncompleteId
+{
+  // the non-linear arithmetic solver was disabled
+  ARITH_NL_DISABLED,
+  // the non-linear arithmetic solver was incomplete
+  ARITH_NL,
+  // incomplete due to lack of a complete quantifiers strategy
+  QUANTIFIERS,
+  // we failed to verify the correctness of a candidate solution in SyGuS
+  QUANTIFIERS_SYGUS_NO_VERIFY,
+  // incomplete due to counterexample-guided instantiation not being complete
+  QUANTIFIERS_CEGQI,
+  // incomplete due to finite model finding not being complete
+  QUANTIFIERS_FMF,
+  // incomplete due to explicitly recorded instantiations
+  QUANTIFIERS_RECORDED_INST,
+  // incomplete due to separation logic
+  SEP,
+  // relations were used in combination with set cardinality constraints
+  SETS_RELS_CARD,
+  // we skipped processing a looping word equation
+  STRINGS_LOOP_SKIP,
+  // we could not simplify a regular expression membership
+  STRINGS_REGEXP_NO_SIMPLIFY,
+  // HO extensionality axiom was disabled
+  UF_HO_EXT_DISABLED,
+  // UF+cardinality solver was disabled
+  UF_CARD_DISABLED,
+  // UF+cardinality solver used in an incomplete mode
+  UF_CARD_MODE,
+
+  //-------------------------------------- unknown
+  UNKNOWN
+};
+
+/**
+ * Converts an incompleteness id to a string.
+ *
+ * @param i The incompleteness identifier
+ * @return The name of the incompleteness identifier
+ */
+const char* toString(IncompleteId i);
+
+/**
+ * Writes an incompleteness identifier to a stream.
+ *
+ * @param out The stream to write to
+ * @param i The incompleteness identifier to write to the stream
+ * @return The stream
+ */
+std::ostream& operator<<(std::ostream& out, IncompleteId i);
+
+}  // namespace theory
+}  // namespace cvc5
+
+#endif /* CVC4__THEORY__INCOMPLETE_ID_H */
index 89957ded6287a0433170fdf280d04c9e72ceae69..3e91bff44341fa009bb50e8fb836606330ae7dae 100644 (file)
 
 #include "cvc4_private.h"
 
-#include <iosfwd>
-
 #ifndef CVC4__THEORY__INFERENCE_ID_H
 #define CVC4__THEORY__INFERENCE_ID_H
 
+#include <iosfwd>
+
 namespace cvc5 {
 namespace theory {
 
index b86a4d647366f69d125a1a9a005b4ca1142df33b..0a3fa39043f8de372365866dfa2c837008c72270 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef CVC4__THEORY__OUTPUT_CHANNEL_H
 #define CVC4__THEORY__OUTPUT_CHANNEL_H
 
+#include "theory/incomplete_id.h"
 #include "theory/trust_node.h"
 #include "util/resource_manager.h"
 
@@ -150,7 +151,7 @@ class OutputChannel {
    * this context level.  If SAT is later determined by the
    * TheoryEngine, it should actually return an UNKNOWN result.
    */
-  virtual void setIncomplete() = 0;
+  virtual void setIncomplete(IncompleteId id) = 0;
 
   /**
    * "Spend" a "resource."  The meaning is specific to the context in
index 74469e7deb2b8b23d68011621545d9cdcbef5dfe..5afea1e9b07fc2609b78839cfefa43a1d9d170e9 100644 (file)
@@ -296,9 +296,10 @@ void InstStrategyCegqi::check(Theory::Effort e, QEffort quant_e)
   }
 }
 
-bool InstStrategyCegqi::checkComplete()
+bool InstStrategyCegqi::checkComplete(IncompleteId& incId)
 {
   if( ( !options::cegqiSat() && d_cbqi_set_quant_inactive ) || d_incomplete_check ){
+    incId = IncompleteId::QUANTIFIERS_CEGQI;
     return false;
   }else{
     return true;
index 6d4ee047f5547d82b2fd9446bdf31c4ce6a494c6..85724a915fc44747ea513ef8d3199939aa179c19 100644 (file)
@@ -85,7 +85,7 @@ class InstStrategyCegqi : public QuantifiersModule
   /** check */
   void check(Theory::Effort e, QEffort quant_e) override;
   /** check complete */
-  bool checkComplete() override;
+  bool checkComplete(IncompleteId& incId) override;
   /** check complete for quantified formula */
   bool checkCompleteFor(Node q) override;
   /** check ownership */
index 1c46e425d698d23753db0ca716d1cb08423f24b0..5fa1396814bba544e88cdf67326c10fc2d054938 100644 (file)
@@ -112,8 +112,14 @@ void ModelEngine::check(Theory::Effort e, QEffort quant_e)
   }
 }
 
-bool ModelEngine::checkComplete() {
-  return !d_incomplete_check;
+bool ModelEngine::checkComplete(IncompleteId& incId)
+{
+  if (d_incomplete_check)
+  {
+    incId = IncompleteId::QUANTIFIERS_FMF;
+    return false;
+  }
+  return true;
 }
 
 bool ModelEngine::checkCompleteFor( Node q ) {
index 2547f2831b3ab3e39d4111d19e3a91a3ac722be5..5a983d726a8f9113d048e19f1c73c82e6f9e37d4 100644 (file)
@@ -55,7 +55,7 @@ public:
  QEffort needsModel(Theory::Effort e) override;
  void reset_round(Theory::Effort e) override;
  void check(Theory::Effort e, QEffort quant_e) override;
- bool checkComplete() override;
+ bool checkComplete(IncompleteId& incId) override;
  bool checkCompleteFor(Node q) override;
  void registerQuantifier(Node f) override;
  void assertNode(Node f) override;
index 62376bff6fb4196f47372a560e5979887d6e8d0c..8fc1c4d136bec7cd82b1997d69c1425ed62310d5 100644 (file)
@@ -74,12 +74,13 @@ bool Instantiate::reset(Theory::Effort e)
 }
 
 void Instantiate::registerQuantifier(Node q) {}
-bool Instantiate::checkComplete()
+bool Instantiate::checkComplete(IncompleteId& incId)
 {
   if (!d_recordedInst.empty())
   {
     Trace("quant-engine-debug")
         << "Set incomplete due to recorded instantiations." << std::endl;
+    incId = IncompleteId::QUANTIFIERS_RECORDED_INST;
     return false;
   }
   return true;
index b3c0565068d0af74e35ac525677b198621b29ae1..b56938fd1f35c58f944eaf7ba4a1c608a7d12d3d 100644 (file)
@@ -117,7 +117,7 @@ class Instantiate : public QuantifiersUtil
   /** identify */
   std::string identify() const override { return "Instantiate"; }
   /** check incomplete */
-  bool checkComplete() override;
+  bool checkComplete(IncompleteId& incId) override;
 
   //--------------------------------------rewrite objects
   /** add instantiation rewriter */
index e6d5eee763ada20eca0f770f7626006433df778f..01a51ccff219ff59be7389d9dc205333b47b8474 100644 (file)
@@ -104,8 +104,11 @@ class QuantifiersModule
    *
    * This is called just before the quantifiers engine will return
    * with no lemmas added during a LAST_CALL effort check.
+   *
+   * If this method returns false, it should update incId to the reason for
+   * why the module was incomplete.
    */
-  virtual bool checkComplete() { return true; }
+  virtual bool checkComplete(IncompleteId& incId) { return true; }
   /** Check was complete for quantified formula q
    *
    * If for each quantified formula q, some module returns true for
index 7cd89c7d8c7e1fca2eba991d98f018b7fe060a9d..90955226cb2e0bb7184b0ae12871ca40d6836432 100644 (file)
@@ -22,6 +22,7 @@
 #include <vector>
 
 #include "expr/node.h"
+#include "theory/incomplete_id.h"
 #include "theory/theory.h"
 
 namespace cvc5 {
@@ -49,9 +50,10 @@ public:
   /** Check complete?
    *
    * Returns false if the utility's reasoning was globally incomplete
-   * (e.g. "sat" must be replaced with "incomplete").
+   * (e.g. "sat" must be replaced with "incomplete"). If this method returns
+   * false, it should update incId to the reason for incompleteness.
    */
-  virtual bool checkComplete() { return true; }
+  virtual bool checkComplete(IncompleteId& incId) { return true; }
 };
 
 class QuantPhaseReq
index 6db632b1160c8868fa7e339e1ba36930e238e586..c9ef1205c2172ae9b4776a75ad10b417b5025ca6 100644 (file)
@@ -616,7 +616,7 @@ bool SynthConjecture::doCheck(std::vector<Node>& lems)
       // We should set incomplete, since a "sat" answer should not be
       // interpreted as "infeasible", which would make a difference in the rare
       // case where e.g. we had a finite grammar and exhausted the grammar.
-      d_qim.setIncomplete();
+      d_qim.setIncomplete(IncompleteId::QUANTIFIERS_SYGUS_NO_VERIFY);
       return false;
     }
     // otherwise we are unsat, and we will process the solution below
index 0bcf1d19c9c39552a1fbde09c7ff0578c40591a3..21c82e9ebb602856ab4a84b337060dbb9cae38ca 100644 (file)
@@ -205,6 +205,7 @@ void QuantifiersEngine::check( Theory::Effort e ){
 
   d_qim.reset();
   bool setIncomplete = false;
+  IncompleteId setIncompleteId = IncompleteId::QUANTIFIERS;
 
   Trace("quant-engine-debug2") << "Quantifiers Engine call to check, level = " << e << ", needsCheck=" << needsCheck << std::endl;
   if( needsCheck ){
@@ -354,7 +355,7 @@ void QuantifiersEngine::check( Theory::Effort e ){
             //sources of incompleteness
             for (QuantifiersUtil*& util : d_util)
             {
-              if (!util->checkComplete())
+              if (!util->checkComplete(setIncompleteId))
               {
                 Trace("quant-engine-debug") << "Set incomplete because utility "
                                             << util->identify().c_str()
@@ -372,7 +373,7 @@ void QuantifiersEngine::check( Theory::Effort e ){
               //check if we should set the incomplete flag
               for (QuantifiersModule*& mdl : d_modules)
               {
-                if (!mdl->checkComplete())
+                if (!mdl->checkComplete(setIncompleteId))
                 {
                   Trace("quant-engine-debug")
                       << "Set incomplete because module "
@@ -447,7 +448,7 @@ void QuantifiersEngine::check( Theory::Effort e ){
   {
     if( setIncomplete ){
       Trace("quant-engine") << "Set incomplete flag." << std::endl;
-      d_qim.setIncomplete();
+      d_qim.setIncomplete(setIncompleteId);
     }
     //output debug stats
     d_qim.getInstantiate()->debugPrintModel();
index 5585b36ab49f1da36a7abc1a3b823b1a903386b8..db842e5a870d2848779a532c266394161f955c49 100644 (file)
@@ -899,7 +899,7 @@ void TheorySep::postCheck(Effort level)
 
   if (needAddLemma)
   {
-    d_im.setIncomplete();
+    d_im.setIncomplete(IncompleteId::SEP);
   }
   Trace("sep-check") << "Sep::check(): " << level
                      << " done, conflict=" << d_state.isInConflict()
index 3aa97672d7e42c564ab3b2815a5b68c6cf34d43f..5001b51dd6068634d4c8dc600a9d845b8d3b7b0b 100644 (file)
@@ -41,7 +41,8 @@ TheorySetsPrivate::TheorySetsPrivate(TheorySets& external,
                                      SkolemCache& skc)
     : d_deq(state.getSatContext()),
       d_termProcessed(state.getUserContext()),
-      d_full_check_incomplete(false),
+      d_fullCheckIncomplete(false),
+      d_fullCheckIncompleteId(IncompleteId::UNKNOWN),
       d_external(external),
       d_state(state),
       d_im(im),
@@ -208,7 +209,8 @@ bool TheorySetsPrivate::areCareDisequal(Node a, Node b)
 void TheorySetsPrivate::fullEffortReset()
 {
   Assert(d_equalityEngine->consistent());
-  d_full_check_incomplete = false;
+  d_fullCheckIncomplete = false;
+  d_fullCheckIncompleteId = IncompleteId::UNKNOWN;
   d_most_common_type.clear();
   d_most_common_type_term.clear();
   d_card_enabled = false;
@@ -295,7 +297,8 @@ void TheorySetsPrivate::fullEffortCheck()
           // some kinds of cardinality we cannot handle
           if (d_rels->isRelationKind(nk0))
           {
-            d_full_check_incomplete = true;
+            d_fullCheckIncomplete = true;
+            d_fullCheckIncompleteId = IncompleteId::SETS_RELS_CARD;
             Trace("sets-incomplete")
                 << "Sets : incomplete because of " << n << "." << std::endl;
             // TODO (#1124):  The issue can be divided into 4 parts
@@ -789,9 +792,9 @@ void TheorySetsPrivate::postCheck(Theory::Effort level)
       {
         fullEffortCheck();
         if (!d_state.isInConflict() && !d_im.hasSentLemma()
-            && d_full_check_incomplete)
+            && d_fullCheckIncomplete)
         {
-          d_im.setIncomplete();
+          d_im.setIncomplete(d_fullCheckIncompleteId);
         }
       }
     }
index c2f266971f6a64022d9f17dc4f9c47bd99dc181e..3c3469b070f0b4884b2fd58719c3a9434410d2dc 100644 (file)
@@ -122,7 +122,9 @@ class TheorySetsPrivate {
    * is incomplete for some reason (for instance, if we combine cardinality
    * with a relation or extended function kind).
    */
-  bool d_full_check_incomplete;
+  bool d_fullCheckIncomplete;
+  /** The reason we set the above flag to true */
+  IncompleteId d_fullCheckIncompleteId;
   std::map< Node, TypeNode > d_most_common_type;
   std::map< Node, Node > d_most_common_type_term;
 
index 6a461cb7a5c480011a1fd127386e6c9bd37f03f3..f38acfac29a27201c24a1286b867e5d2930a9678 100644 (file)
@@ -1778,7 +1778,7 @@ CoreSolver::ProcessLoopResult CoreSolver::processLoop(NormalForm& nfi,
   }
   else if (options::stringProcessLoopMode() == options::ProcessLoopMode::NONE)
   {
-    d_im.setIncomplete();
+    d_im.setIncomplete(IncompleteId::STRINGS_LOOP_SKIP);
     return ProcessLoopResult::SKIPPED;
   }
 
@@ -1931,7 +1931,7 @@ CoreSolver::ProcessLoopResult CoreSolver::processLoop(NormalForm& nfi,
     else if (options::stringProcessLoopMode()
              == options::ProcessLoopMode::SIMPLE)
     {
-      d_im.setIncomplete();
+      d_im.setIncomplete(IncompleteId::STRINGS_LOOP_SKIP);
       return ProcessLoopResult::SKIPPED;
     }
 
index ff3803b7e72e851b23aae7c13b339092af347c37..8a0429fae8f4da7d59a14dce97686715d498ba06 100644 (file)
@@ -241,8 +241,6 @@ bool InferenceManager::sendSplit(Node a, Node b, InferenceId infer, bool preq)
   return true;
 }
 
-void InferenceManager::setIncomplete() { d_out.setIncomplete(); }
-
 void InferenceManager::addToExplanation(Node a,
                                         Node b,
                                         std::vector<Node>& exp) const
index cb5560f2b32e70efa400d2d8dd8fff1e2be0358d..cfb8614ca2a6ed85cbe483bebed5b73b285bec57 100644 (file)
@@ -201,12 +201,6 @@ class InferenceManager : public InferenceManagerBuffered
    * otherwise. A split is trivial if a=b rewrites to a constant.
    */
   bool sendSplit(Node a, Node b, InferenceId infer, bool preq = true);
-  /**
-   * Set that we are incomplete for the current set of assertions (in other
-   * words, we must answer "unknown" instead of "sat"); this calls the output
-   * channel's setIncomplete method.
-   */
-  void setIncomplete();
 
   //----------------------------constructing antecedants
   /**
index 7510b26ca079c276c2d3faa97592195b4d54d30d..85d66cd5449c788dff44085660807d0d6d1e19be 100644 (file)
@@ -303,7 +303,7 @@ void RegExpSolver::check(const std::map<Node, std::vector<Node> >& mems)
           else
           {
             // otherwise we are incomplete
-            d_im.setIncomplete();
+            d_im.setIncomplete(IncompleteId::STRINGS_REGEXP_NO_SIMPLIFY);
           }
         }
         if (d_state.isInConflict())
index 2210caf6a1af474e5df9d7d22acc19b483457004..dd130e28a0a16b1fc8273d0a95a4b98fdea53c2c 100644 (file)
@@ -234,6 +234,8 @@ TheoryEngine::TheoryEngine(context::Context* context,
       d_inSatMode(false),
       d_hasShutDown(false),
       d_incomplete(context, false),
+      d_incompleteTheory(context, THEORY_BUILTIN),
+      d_incompleteId(context, IncompleteId::UNKNOWN),
       d_propagationMap(context),
       d_propagationMapTimestamp(context, 0),
       d_propagatedLiterals(context),
@@ -1454,6 +1456,14 @@ void TheoryEngine::conflict(theory::TrustNode tconflict, TheoryId theoryId)
   }
 }
 
+void TheoryEngine::setIncomplete(theory::TheoryId theory,
+                                 theory::IncompleteId id)
+{
+  d_incomplete = true;
+  d_incompleteTheory = theory;
+  d_incompleteId = id;
+}
+
 theory::TrustNode TheoryEngine::getExplanation(
     std::vector<NodeTheoryPair>& explanationVector)
 {
index 8960b324d8c52e7314ea817450526a4b3f91e90e..cc3de2e5030ff22b052453dcb96aee46402d6f51 100644 (file)
@@ -199,13 +199,14 @@ class TheoryEngine {
    * context level or below).
    */
   context::CDO<bool> d_incomplete;
+  /** The theory and identifier that (most recently) set incomplete */
+  context::CDO<theory::TheoryId> d_incompleteTheory;
+  context::CDO<theory::IncompleteId> d_incompleteId;
 
   /**
    * Called by the theories to notify that the current branch is incomplete.
    */
-  void setIncomplete(theory::TheoryId theory) {
-    d_incomplete = true;
-  }
+  void setIncomplete(theory::TheoryId theory, theory::IncompleteId id);
 
   /**
    * Mapping of propagations from recievers to senders.
index e7c89e7030d09f97508a4b5dc2151621815f2043..1ca86687156d72f5cee02f694238227b5b4cd617 100644 (file)
@@ -517,7 +517,10 @@ void TheoryInferenceManager::safePoint(ResourceManager::Resource r)
   d_out.safePoint(r);
 }
 
-void TheoryInferenceManager::setIncomplete() { d_out.setIncomplete(); }
+void TheoryInferenceManager::setIncomplete(IncompleteId id)
+{
+  d_out.setIncomplete(id);
+}
 
 }  // namespace theory
 }  // namespace cvc5
index e911fb41e764e91c7d06207fa611768227438b6d..380ba6e48155c39fd58531440d7d9dc0b093e9f2 100644 (file)
@@ -370,7 +370,7 @@ class TheoryInferenceManager
    * Notification from a theory that it realizes it is incomplete at
    * this context level.
    */
-  void setIncomplete();
+  void setIncomplete(IncompleteId id);
 
  protected:
   /**
index eb6145f9cad3762ca9183749d03b5b1705de7bea..6ba4594520f36e5637fcdb4212a6c2843b87bbf6 100644 (file)
@@ -1432,7 +1432,7 @@ void CardinalityExtension::assertNode(Node n, bool isDecision)
     if( lit.getKind()==CARDINALITY_CONSTRAINT || lit.getKind()==COMBINED_CARDINALITY_CONSTRAINT ){
       // cardinality constraint from user input, set incomplete   
       Trace("uf-ss") << "Literal " << lit << " not handled when uf ss mode is not FULL, set incomplete." << std::endl;
-      d_im.setIncomplete();
+      d_im.setIncomplete(IncompleteId::UF_CARD_MODE);
     }
   }
   Trace("uf-ss") << "Assert: done " << n << " " << isDecision << std::endl;
index ee3753e92410e97878904968d735ac22294cc7d6..78171349db9db062fe11516547dc7c3df0a927f1 100644 (file)
@@ -227,7 +227,7 @@ unsigned HoExtension::checkExtensionality(TheoryModel* m)
     // are present
     if (hasFunctions)
     {
-      d_im.setIncomplete();
+      d_im.setIncomplete(IncompleteId::UF_HO_EXT_DISABLED);
     }
     return 0;
   }
index 9cb37a26d3c6c97a855c68264b22560534cfb9a7..e23bc0c458e4089151b2ccbe088b17535ab8000e 100644 (file)
@@ -177,7 +177,7 @@ bool TheoryUF::preNotifyFact(
       else
       {
         // support for cardinality constraints is not enabled, set incomplete
-        d_im.setIncomplete();
+        d_im.setIncomplete(IncompleteId::UF_CARD_DISABLED);
       }
     }
     // don't need to assert cardinality constraints if not producing models
index 9be954059ff5fe38afb99df4553a5aad39b822c6..425e61bc22e1556acfb98d2489d1774612bd3acf 100644 (file)
@@ -137,7 +137,7 @@ class DummyOutputChannel : public cvc5::theory::OutputChannel
   }
 
   void requirePhase(TNode, bool) override {}
-  void setIncomplete() override {}
+  void setIncomplete(theory::IncompleteId id) override {}
   void handleUserAttribute(const char* attr, theory::Theory* t) override {}
 
   void splitLemma(TNode n, bool removable = false) override { push(LEMMA, n); }