In each case, previously we were generating a define-fun, what we needed was to do a model substitution.
This actually meant that check-models was giving false positives. The model was incorrect but check-models succeeded due to its use of expand definitions.
}
// If the result is BV, it needs to be casted back.
result = castToType(result, resultType);
- // add the function definition to the smt engine.
- d_preprocContext->getSmt()->defineFunction(bvUF, args, result, true);
+ // add the substitution to the preprocessing context, which ensures the
+ // model for bvUF is correct, as well as substituting it in the input
+ // assertions when necessary.
+ if (!args.empty())
+ {
+ result = d_nm->mkNode(
+ kind::LAMBDA, d_nm->mkNode(kind::BOUND_VAR_LIST, args), result);
+ }
+ d_preprocContext->addSubstitution(bvUF, result);
}
bool BVToInt::childrenTypesChanged(Node n)
#include "theory/rewriter.h"
#include "theory/theory_model.h"
+using namespace cvc5::theory;
+
namespace cvc5 {
namespace preprocessing {
namespace passes {
-using namespace std;
-using namespace cvc5::theory;
+RealToInt::RealToInt(PreprocessingPassContext* preprocContext)
+ : PreprocessingPass(preprocContext, "real-to-int"),
+ d_cache(preprocContext->getUserContext())
+{
+}
Node RealToInt::realToIntInternal(TNode n, NodeMap& cache, std::vector<Node>& var_eq)
{
}
else if (n.isVar())
{
- ret = sm->mkDummySkolem(
- "__realToIntInternal_var",
- nm->integerType(),
- "Variable introduced in realToIntInternal pass");
+ Node toIntN = nm->mkNode(kind::TO_INTEGER, n);
+ ret = sm->mkPurifySkolem(toIntN, "__realToIntInternal_var");
var_eq.push_back(n.eqNode(ret));
- // ensure that the original variable is defined to be the returned
- // one, which is important for models and for incremental solving.
- std::vector<Node> args;
- d_preprocContext->getSmt()->defineFunction(n, args, ret);
+ // add the substitution to the preprocessing context, which ensures
+ // the model for n is correct, as well as substituting it in the input
+ // assertions when necessary.
+ d_preprocContext->addSubstitution(n, ret);
}
}
}
}
}
-RealToInt::RealToInt(PreprocessingPassContext* preprocContext)
- : PreprocessingPass(preprocContext, "real-to-int"){};
-
PreprocessingPassResult RealToInt::applyInternal(
AssertionPipeline* assertionsToPreprocess)
{
- unordered_map<Node, Node, NodeHashFunction> cache;
std::vector<Node> var_eq;
for (unsigned i = 0, size = assertionsToPreprocess->size(); i < size; ++i)
{
assertionsToPreprocess->replace(
- i, realToIntInternal((*assertionsToPreprocess)[i], cache, var_eq));
+ i, realToIntInternal((*assertionsToPreprocess)[i], d_cache, var_eq));
}
return PreprocessingPassResult::NO_CONFLICT;
}
#include <vector>
+#include "context/cdhashmap.h"
#include "expr/node.h"
#include "preprocessing/preprocessing_pass.h"
namespace preprocessing {
namespace passes {
-using NodeMap = std::unordered_map<Node, Node, NodeHashFunction>;
-
class RealToInt : public PreprocessingPass
{
+ using NodeMap = context::CDHashMap<Node, Node, NodeHashFunction>;
+
public:
RealToInt(PreprocessingPassContext* preprocContext);
private:
Node realToIntInternal(TNode n, NodeMap& cache, std::vector<Node>& var_eq);
+ /** Cache for the above method */
+ NodeMap d_cache;
};
} // namespace passes
// see if we can succesfully solve the input as a sygus problem
if (solveSygus(assertionsToPreprocess->ref(), funs, sols))
{
+ Trace("sygus-infer") << "...Solved:" << std::endl;
Assert(funs.size() == sols.size());
- // if so, sygus gives us function definitions
- SmtEngine* master_smte = d_preprocContext->getSmt();
+ // if so, sygus gives us function definitions, which we add as substitutions
for (unsigned i = 0, size = funs.size(); i < size; i++)
{
- std::vector<Node> args;
- Node sol = sols[i];
- // if it is a non-constant function
- if (sol.getKind() == LAMBDA)
- {
- for (const Node& v : sol[0])
- {
- args.push_back(v);
- }
- sol = sol[1];
- }
- master_smte->defineFunction(funs[i], args, sol);
+ Trace("sygus-infer") << funs[i] << " -> " << sols[i] << std::endl;
+ d_preprocContext->addSubstitution(funs[i], sols[i]);
}
// apply substitution to everything, should result in SAT
lhs, d_smt->expandDefinitions(rhs, false));
}
+void PreprocessingPassContext::addSubstitution(const Node& lhs,
+ const Node& rhs,
+ ProofGenerator* pg)
+{
+ d_topLevelSubstitutions.addSubstitution(lhs, rhs, pg);
+ // also add as a model substitution
+ addModelSubstitution(lhs, rhs);
+}
+
ProofNodeManager* PreprocessingPassContext::getProofNodeManager()
{
return d_pnm;
void recordSymbolsInAssertions(const std::vector<Node>& assertions);
/**
- * Add substitution to theory model.
+ * Add substitution to theory model. This method should only be called if
+ * we have already added the substitution to the top-level substitutions
+ * class. Otherwise, addSubstitution should be called instead.
* @param lhs The node replaced by node 'rhs'
* @param rhs The node to substitute node 'lhs'
*/
void addModelSubstitution(const Node& lhs, const Node& rhs);
+ /**
+ * Add substitution to the top-level substitutions and to the theory model.
+ * @param lhs The node replaced by node 'rhs'
+ * @param rhs The node to substitute node 'lhs'
+ * @param pg The proof generator that can provide a proof of lhs == rhs.
+ */
+ void addSubstitution(const Node& lhs,
+ const Node& rhs,
+ ProofGenerator* pg = nullptr);
/** The the proof node manager associated with this context, if it exists */
ProofNodeManager* getProofNodeManager();
-; COMMAND-LINE: --incremental --solve-real-as-int
+; COMMAND-LINE: --incremental --solve-real-as-int -q
; EXPECT: sat
; EXPECT: sat
; EXPECT: sat
-; COMMAND-LINE: --sygus-inference
+; COMMAND-LINE: --sygus-inference -q
; EXPECT: sat
(set-logic UFLIA)
(set-info :status sat)
-; COMMAND-LINE: --sygus-unif-pi=complete --sygus-infer
+; COMMAND-LINE: --sygus-unif-pi=complete --sygus-infer -q
; EXPECT: sat
(set-logic UFLIA)
(set-info :status sat)
+; COMMAND-LINE: -q
+; EXPECT: sat
(set-logic ALL)
(set-option :conjecture-filter-model true)
(set-option :conjecture-gen true)