Fixes #8344.
We now have cases where witness terms e.g. `(witness x : String. len(x) = N)` appear in model values. These terms require special care in CEGQI.
There are 2 fixes in this PR:
(1) we update our policy on what a legal term is,
(2) we erase annotations from witness terms appearing in instantiations, which is required for ensuring that proofs are consistent. Otherwise, the skolemization lemma for a witness term does not introduce the same skolem.
libcvc5_add_sources(
algorithm/flatten.h
+ annotation_elim_node_converter.cpp
+ annotation_elim_node_converter.h
array_store_all.cpp
array_store_all.h
ascription_type.cpp
--- /dev/null
+/******************************************************************************
+ * Top contributors (to current version):
+ * Andrew Reynolds
+ *
+ * This file is part of the cvc5 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.
+ * ****************************************************************************
+ *
+ * Implementation of annotation elimination node conversion
+ */
+
+#include "expr/annotation_elim_node_converter.h"
+
+using namespace cvc5::kind;
+
+namespace cvc5 {
+
+AnnotationElimNodeConverter::AnnotationElimNodeConverter() {}
+
+Node AnnotationElimNodeConverter::postConvert(Node n)
+{
+ if (n.isClosure() && n.getNumChildren() == 3)
+ {
+ return NodeManager::currentNM()->mkNode(n.getKind(), n[0], n[1]);
+ }
+ return n;
+}
+
+} // namespace cvc5
--- /dev/null
+/******************************************************************************
+ * Top contributors (to current version):
+ * Andrew Reynolds
+ *
+ * This file is part of the cvc5 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.
+ * ****************************************************************************
+ *
+ * Implementation of annotation elimination node conversion
+ */
+#include "cvc5_private.h"
+
+#ifndef CVC4__PROOF__EXPR__ANNOTATION_ELIM_NODE_CONVERTER_H
+#define CVC4__PROOF__EXPR__ANNOTATION_ELIM_NODE_CONVERTER_H
+
+#include "expr/node.h"
+#include "expr/node_converter.h"
+
+namespace cvc5 {
+
+/**
+ * This converts a node into one that does not involve annotations for
+ * quantified formulas. In other words, the third child is dropped for all
+ * closure terms with 3 children.
+ */
+class AnnotationElimNodeConverter : public NodeConverter
+{
+ public:
+ AnnotationElimNodeConverter();
+ ~AnnotationElimNodeConverter() {}
+ /** convert node n as described above during post-order traversal */
+ Node postConvert(Node n) override;
+};
+
+} // namespace cvc5
+
+#endif
#include "theory/quantifiers/cegqi/ceg_instantiator.h"
+#include "expr/annotation_elim_node_converter.h"
#include "expr/dtype.h"
#include "expr/dtype_cons.h"
#include "expr/node_algorithm.h"
void CegInstantiator::computeProgVars( Node n ){
if( d_prog_var.find( n )==d_prog_var.end() ){
d_prog_var[n].clear();
- if (n.getKind() == kind::WITNESS)
+ Kind k = n.getKind();
+ if (k == kind::WITNESS)
{
Assert(d_prog_var.find(n[0][0]) == d_prog_var.end());
+ // ignore the bound variable
d_prog_var[n[0][0]].clear();
}
if (d_vars_set.find(n) != d_vars_set.end())
d_inelig.insert(n);
return;
}
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ bool isClosure = n.isClosure();
+ for (size_t i = 0, nchild = n.getNumChildren(); i < nchild; i++)
+ {
+ if (isClosure && i != 1)
+ {
+ // ignore the bound variable list and annotation
+ continue;
+ }
computeProgVars( n[i] );
if( d_inelig.find( n[i] )!=d_inelig.end() ){
d_inelig.insert(n);
d_prog_var[n].insert(d_prog_var[n[i]].begin(), d_prog_var[n[i]].end());
}
// selectors applied to program variables are also variables
- if (n.getKind() == APPLY_SELECTOR
- && d_prog_var[n].find(n[0]) != d_prog_var[n].end())
+ if (k == APPLY_SELECTOR && d_prog_var[n].find(n[0]) != d_prog_var[n].end())
{
d_prog_var[n].insert(n);
}
- if (n.getKind() == kind::WITNESS)
+ if (k == kind::WITNESS)
{
d_prog_var.erase(n[0][0]);
}
}
Node CegInstantiator::getModelValue( Node n ) {
- return d_treg.getModel()->getValue(n);
+ Node mv = d_treg.getModel()->getValue(n);
+ // Witness terms with identifiers may appear in the model. We require
+ // dropping their annotations here.
+ AnnotationElimNodeConverter aenc;
+ mv = aenc.convert(mv);
+ return mv;
}
Node CegInstantiator::getBoundVariable(TypeNode tn)
regress1/quantifiers/issue7385-sygus-inst-i.smt2
regress1/quantifiers/issue7537-cegqi-comp-types.smt2
regress1/quantifiers/issue8157-duplicate-conflicts.smt2
+ regress1/quantifiers/issue8344-cegqi-string-witness.smt2
regress1/quantifiers/issue993.smt2
regress1/quantifiers/javafe.ast.StmtVec.009.smt2
regress1/quantifiers/lia-witness-div-pp.smt2
--- /dev/null
+; COMMAND-LINE: -q
+; EXPECT: unsat
+(set-logic ALL)
+(set-info :status unsat)
+(declare-fun a () String)
+(assert (forall ((b Int)) (or (> (str.len a) b) (= 0 (mod b 74998)))))
+(check-sat)