| tok=( ATTRIBUTE_QUANTIFIER_ID_TOK ) symbol[s,CHECK_UNDECLARED,SYM_VARIABLE]
{
api::Term keyword = SOLVER->mkString("qid");
- api::Term name = SOLVER->mkString(s);
+ // must create a variable whose name is the name of the quantified
+ // formula, not a string.
+ api::Term name = SOLVER->mkConst(SOLVER->getBooleanSort(), s);
retExpr = MK_TERM(api::INST_ATTRIBUTE, keyword, name);
}
| ATTRIBUTE_NAMED_TOK symbol[s,CHECK_UNDECLARED,SYM_VARIABLE]
annot << " ";
for (const Node& nc : n[2])
{
- if (nc.getKind() == kind::INST_PATTERN)
+ Kind nck = nc.getKind();
+ if (nck == kind::INST_PATTERN)
{
out << "(! ";
annot << ":pattern ";
toStream(annot, nc, toDepth, nullptr);
annot << ") ";
}
- else if (nc.getKind() == kind::INST_NO_PATTERN)
+ else if (nck == kind::INST_NO_PATTERN)
{
out << "(! ";
annot << ":no-pattern ";
toStream(annot, nc[0], toDepth, nullptr);
annot << ") ";
}
+ else if (nck == kind::INST_ATTRIBUTE)
+ {
+ // notice that INST_ATTRIBUTES either have an "internal" form,
+ // where the argument is a variable with an internal attribute set
+ // on it, or an "external" form where it is of the form
+ // (INST_ATTRIBUTE "keyword" [nodeValues]). We print the latter
+ // here only.
+ if (nc[0].getKind() == kind::CONST_STRING)
+ {
+ out << "(! ";
+ // print out as string to avoid quotes
+ annot << ":" << nc[0].getConst<String>().toString();
+ for (size_t j = 1, nchild = nc.getNumChildren(); j < nchild; j++)
+ {
+ annot << " ";
+ toStream(annot, nc[j], toDepth, nullptr);
+ }
+ annot << ") ";
+ }
+ }
}
}
// Use a fresh let binder, since using existing let symbols may violate
variable SKOLEM "a Skolem variable (internal only)"
operator SEXPR 0: "a symbolic expression (any arity)"
-operator WITNESS 2 "a witness expression; first parameter is a BOUND_VAR_LIST, second is the witness body"
+operator WITNESS 2:3 "a witness expression; first parameter is a BOUND_VAR_LIST, second is the witness body"
constant TYPE_CONSTANT \
skip \
ss << "expected a body of a WITNESS expression to have Boolean type";
throw TypeCheckingExceptionPrivate(n, ss.str());
}
+ if (n.getNumChildren() == 3)
+ {
+ if (n[2].getType(check) != nodeManager->instPatternListType())
+ {
+ throw TypeCheckingExceptionPrivate(
+ n,
+ "third argument of witness is not instantiation "
+ "pattern list");
+ }
+ }
}
// The type of a witness function is the type of its bound variable.
return n[0][0].getType();
#include "theory/quantifiers/quantifiers_attributes.h"
+#include "expr/node_manager_attributes.h"
+#include "expr/skolem_manager.h"
#include "options/quantifiers_options.h"
#include "theory/arith/arith_msum.h"
#include "theory/quantifiers/fmf/bounded_integers.h"
// only set the name if there is a value
if (q[2][i].getNumChildren() > 1)
{
- Trace("quant-attr") << "Attribute : quantifier name : "
- << q[2][i][1].getConst<String>().toString()
+ std::string name;
+ q[2][i][1].getAttribute(expr::VarNameAttr(), name);
+ Trace("quant-attr") << "Attribute : quantifier name : " << name
<< " for " << q << std::endl;
// assign the name to a variable with the given name (to avoid
// enclosing the name in quotes)
- qa.d_name = nm->mkBoundVar(q[2][i][1].getConst<String>().toString(),
- nm->booleanType());
+ qa.d_name = nm->mkBoundVar(name, nm->booleanType());
}
else
{
}
}
+Node mkNamedQuant(Kind k, Node bvl, Node body, const std::string& name)
+{
+ NodeManager* nm = NodeManager::currentNM();
+ SkolemManager* sm = nm->getSkolemManager();
+ Node v = sm->mkDummySkolem(
+ name, nm->booleanType(), "", SkolemManager::SKOLEM_EXACT_NAME);
+ Node attr = nm->mkConst(String("qid"));
+ Node ip = nm->mkNode(INST_ATTRIBUTE, attr, v);
+ Node ipl = nm->mkNode(INST_PATTERN_LIST, ip);
+ return nm->mkNode(k, bvl, body, ipl);
+}
+
} // namespace quantifiers
} // namespace theory
} // namespace cvc5
std::map< Node, bool > d_fun_defs;
};
+/**
+ * Make a named quantified formula. This is a quantified formula that will
+ * print like:
+ * (<k> <bvl> (! <body> :qid name))
+ */
+Node mkNamedQuant(Kind k, Node bvl, Node body, const std::string& name);
}
}
} // namespace cvc5
env, d_state, d_im, d_termReg, d_csolver, d_esolver, d_statistics),
d_regexp_elim(options().strings.regExpElimAgg, d_pnm, userContext()),
d_stringsFmf(env, valuation, d_termReg),
- d_strat(d_env)
+ d_strat(d_env),
+ d_absModelCounter(0)
{
d_termReg.finishInit(&d_im);
Assert(!lenValue.isNull() && lenValue.isConst());
// make the abstract value (witness ((x String)) (= (str.len x)
// lenValue))
- Node w = utils::mkAbstractStringValueForLength(eqc, lenValue);
+ Node w = utils::mkAbstractStringValueForLength(
+ eqc, lenValue, d_absModelCounter);
+ d_absModelCounter++;
Trace("strings-model")
<< "-> length out of bounds, assign abstract " << w << std::endl;
if (!m->assertEquality(eqc, w, true))
StringsFmf d_stringsFmf;
/** The representation of the strategy */
Strategy d_strat;
+ /**
+ * For model building, a counter on the number of abstract witness terms
+ * we have built, so that unique debug names can be assigned.
+ */
+ size_t d_absModelCounter;
};/* class TheoryStrings */
} // namespace strings
#include "expr/skolem_manager.h"
#include "options/strings_options.h"
#include "theory/quantifiers/fmf/bounded_integers.h"
+#include "theory/quantifiers/quantifiers_attributes.h"
#include "theory/rewriter.h"
#include "theory/strings/arith_entail.h"
#include "theory/strings/strings_entail.h"
typedef expr::Attribute<StringValueForLengthVarAttributeId, Node>
StringValueForLengthVarAttribute;
-Node mkAbstractStringValueForLength(Node n, Node len)
+Node mkAbstractStringValueForLength(Node n, Node len, size_t id)
{
NodeManager* nm = NodeManager::currentNM();
BoundVarManager* bvm = nm->getBoundVarManager();
cacheVal, "s", n.getType());
Node pred = nm->mkNode(STRING_LENGTH, v).eqNode(len);
// return (witness ((v String)) (= (str.len v) len))
- return nm->mkNode(WITNESS, nm->mkNode(BOUND_VAR_LIST, v), pred);
+ Node bvl = nm->mkNode(BOUND_VAR_LIST, v);
+ std::stringstream ss;
+ ss << "w" << id;
+ return quantifiers::mkNamedQuant(WITNESS, bvl, pred, ss.str());
}
} // namespace utils
* This is used for constructing models for strings whose lengths are too large
* to represent in memory.
*/
-Node mkAbstractStringValueForLength(Node n, Node len);
+Node mkAbstractStringValueForLength(Node n, Node len, size_t id);
} // namespace utils
} // namespace strings
regress0/strings/code-sat-neg-one.smt2
regress0/strings/complement-simple.smt2
regress0/strings/delta-trust-subs.smt2
+ regress0/strings/distinct-witness-id.smt2
regress0/strings/escchar_25.smt2
regress0/strings/escchar.smt2
regress0/strings/from_code.smt2
--- /dev/null
+; COMMAND-LINE: -q
+; EXPECT: sat
+(set-logic ALL)
+(set-info :status sat)
+(declare-fun x () String)
+(declare-fun y () String)
+(declare-fun z () String)
+(assert (= (str.len x) 999999999999999999999999))
+(assert (= (str.len y) 999999999999999999999999))
+(assert (= z (str.++ x y)))
+(check-sat)