Avoids segfault in model construction due to asking for the value of irrelevant (non-shared) term.
}
d_currTerms.clear();
Trace("seq-array") << "ArraySolver::checkArrayConcat..." << std::endl;
- checkTerms(STRING_UPDATE);
- checkTerms(SEQ_NTH);
+ // Get the set of relevant terms. The core array solver requires knowing this
+ // set to ensure its write model is only over relevant terms.
+ std::set<Node> termSet;
+ d_termReg.getRelevantTermSet(termSet);
+ checkTerms(termSet);
}
void ArraySolver::checkArray()
return;
}
Trace("seq-array") << "ArraySolver::checkArray..." << std::endl;
- std::vector<Node> nthTerms = d_esolver.getActive(SEQ_NTH);
- std::vector<Node> updateTerms = d_esolver.getActive(STRING_UPDATE);
+ // get the set of relevant terms, for reasons described above
+ std::set<Node> termSet;
+ d_termReg.getRelevantTermSet(termSet);
+ std::vector<Node> nthTerms;
+ std::vector<Node> updateTerms;
+ for (const Node& n : termSet)
+ {
+ Kind k = n.getKind();
+ if (k == STRING_UPDATE)
+ {
+ updateTerms.push_back(n);
+ }
+ else if (k == SEQ_NTH)
+ {
+ nthTerms.push_back(n);
+ }
+ }
d_coreSolver.check(nthTerms, updateTerms);
}
-void ArraySolver::checkTerms(Kind k)
+void ArraySolver::checkTerms(const std::set<Node>& termSet)
{
- Assert(k == STRING_UPDATE || k == SEQ_NTH);
// get all the active update terms that have not been reduced in the
// current context by context-dependent simplification
- std::vector<Node> terms = d_esolver.getActive(k);
- for (const Node& t : terms)
+ for (const Node& t : termSet)
{
+ Kind k = t.getKind();
Trace("seq-array-debug") << "check term " << t << "..." << std::endl;
- Assert(t.getKind() == k);
if (k == STRING_UPDATE)
{
if (!d_termReg.isHandledUpdate(t))
// for update terms, also check the inverse inference
checkTerm(t, true);
}
+ else if (k != SEQ_NTH)
+ {
+ continue;
+ }
// check the normal inference
checkTerm(t, false);
}
const std::map<Node, Node>& getConnectedSequences();
private:
- /** check terms of given kind */
- void checkTerms(Kind k);
+ /** check terms of nth or update kind that occur in termSet */
+ void checkTerms(const std::set<Node>& termSet);
/** check inferences for the given term
*
* @param t the term to check
#include "theory/strings/inference_manager.h"
#include "theory/strings/theory_strings_utils.h"
#include "theory/strings/word.h"
+#include "theory/theory.h"
#include "util/rational.h"
#include "util/string.h"
namespace strings {
TermRegistry::TermRegistry(Env& env,
+ Theory& t,
SolverState& s,
SequencesStatistics& statistics,
ProofNodeManager* pnm)
: EnvObj(env),
+ d_theory(t),
d_state(s),
d_im(nullptr),
d_statistics(statistics),
d_proxyVar(userContext()),
d_proxyVarToLength(userContext()),
d_lengthLemmaTermsCache(userContext()),
- d_epg(
- pnm ? new EagerProofGenerator(
- pnm, userContext(), "strings::TermRegistry::EagerProofGenerator")
- : nullptr)
+ d_epg(pnm ? new EagerProofGenerator(
+ pnm,
+ userContext(),
+ "strings::TermRegistry::EagerProofGenerator")
+ : nullptr)
{
NodeManager* nm = NodeManager::currentNM();
d_zero = nm->mkConstInt(Rational(0));
}
}
+void TermRegistry::getRelevantTermSet(std::set<Node>& termSet)
+{
+ d_theory.collectAssertedTerms(termSet);
+ // also, get the additionally relevant terms
+ d_theory.computeRelevantTerms(termSet);
+}
+
Node TermRegistry::mkNConcat(Node n1, Node n2) const
{
return rewrite(NodeManager::currentNM()->mkNode(STRING_CONCAT, n1, n2));
namespace cvc5 {
namespace theory {
+
+class Theory;
+
namespace strings {
class InferenceManager;
public:
TermRegistry(Env& env,
+ Theory& t,
SolverState& s,
SequencesStatistics& statistics,
ProofNodeManager* pnm);
*/
Node mkNConcat(const std::vector<Node>& c, TypeNode tn) const;
+ /** compute relevant terms of the theory of strings */
+ void getRelevantTermSet(std::set<Node>& termSet);
+
private:
+ /** Reference to theory of strings, for computing relevant terms */
+ Theory& d_theory;
/** Common constants */
Node d_zero;
Node d_one;
d_notify(*this),
d_statistics(),
d_state(env, d_valuation),
- d_termReg(env, d_state, d_statistics, d_pnm),
+ d_termReg(env, *this, d_state, d_statistics, d_pnm),
d_rewriter(env.getRewriter(),
&d_statistics.d_rewrites,
d_termReg.getAlphabetCardinality()),
regress0/seq/seq-nth.smt2
regress0/seq/seq-rewrites.smt2
regress0/seq/seq-types.smt2
+ regress0/seq/shared-term-registration.smt2
regress0/seq/update-concat-non-atomic.smt2
regress0/seq/update-concat-non-atomic2.smt2
regress0/seq/update-eq.smt2
--- /dev/null
+; COMMAND-LINE: --strings-exp --seq-array=lazy
+; EXPECT: unknown
+(set-logic ALL)
+(declare-sort T@$ 0)
+(declare-sort |T@[| 0)
+(declare-sort T 0)
+(declare-sort T@ 0)
+(declare-datatypes ((@ 0)) ((($1 (l Int)))))
+(declare-datatypes (($1 0)) ((($1 (v (Seq @))))))
+(declare-datatypes ((@$ 0)) ((($1 (p $1)))))
+(declare-datatypes ((M 0)) (((M (c T@)))))
+(declare-datatypes ((E 0)) (((T))))
+(declare-datatypes ((@M 0)) (((M (|#| T)))))
+(declare-datatypes (($E 0)) ((($E (s |T@[|)))))
+(declare-fun S (|T@[| T@$) @M)
+(declare-fun S (T E) Int)
+(declare-fun |1| () M)
+(declare-fun S (T@ Int) @$)
+(declare-fun $ () Int)
+(declare-fun e () $E)
+(declare-fun t () Bool)
+(assert (not (=> (and (forall ((h T@$)) (and (forall ((v E)) (= 0 (S (|#| (S (s e) h)) T)))))) (< 0 (seq.len (v (p (S (c |1|) 1))))) (and t (= 0 (l (seq.nth (v (p (S (c |1|) 1))) $)))))))
+(check-sat)