summaryrefslogtreecommitdiff
path: root/src/theory/strings
diff options
context:
space:
mode:
authorajreynol <andrew.j.reynolds@gmail.com>2016-10-01 07:08:45 -0500
committerajreynol <andrew.j.reynolds@gmail.com>2016-10-01 07:08:45 -0500
commit4adb2ef78320743ff4b56eac15bfdbe4b9591b51 (patch)
treec116e571f00e1f3c104126813714dab1c358a4ac /src/theory/strings
parentb55cdcaee28aebed9f4ea7e4790e0c97249933ae (diff)
Incorporate non-bv parts of ajr/bvExt branch
Diffstat (limited to 'src/theory/strings')
-rw-r--r--src/theory/strings/theory_strings.cpp244
-rw-r--r--src/theory/strings/theory_strings.h6
2 files changed, 124 insertions, 126 deletions
diff --git a/src/theory/strings/theory_strings.cpp b/src/theory/strings/theory_strings.cpp
index 2f6f7e9e7..3ef6df3fc 100644
--- a/src/theory/strings/theory_strings.cpp
+++ b/src/theory/strings/theory_strings.cpp
@@ -331,6 +331,92 @@ bool TheoryStrings::getCurrentSubstitution( int effort, std::vector< Node >& var
return true;
}
+int TheoryStrings::getReduction( int effort, Node n, Node& nr ) {
+ //determine the effort level to process the extf at
+ // 0 - at assertion time, 1+ - after no other reduction is applicable
+ Assert( d_extf_info_tmp.find( n )!=d_extf_info_tmp.end() );
+ if( d_extf_info_tmp[n].d_model_active ){
+ int r_effort = -1;
+ int pol = d_extf_info_tmp[n].d_pol;
+ if( n.getKind()==kind::STRING_STRCTN ){
+ if( pol==1 ){
+ r_effort = 1;
+ }else if( pol==-1 ){
+ if( effort==2 ){
+ Node x = n[0];
+ Node s = n[1];
+ std::vector< Node > lexp;
+ Node lenx = getLength( x, lexp );
+ Node lens = getLength( s, lexp );
+ if( areEqual( lenx, lens ) ){
+ Trace("strings-extf-debug") << " resolve extf : " << n << " based on equal lengths disequality." << std::endl;
+ //we can reduce to disequality when lengths are equal
+ if( !areDisequal( x, s ) ){
+ lexp.push_back( lenx.eqNode(lens) );
+ lexp.push_back( n.negate() );
+ Node xneqs = x.eqNode(s).negate();
+ sendInference( lexp, xneqs, "NEG-CTN-EQL", true );
+ }
+ return 1;
+ }else if( !areDisequal( lenx, lens ) ){
+ //split on their lenths
+ sendSplit( lenx, lens, "NEG-CTN-SP" );
+ }else{
+ r_effort = 2;
+ }
+ }
+ }
+ }else{
+ if( options::stringLazyPreproc() ){
+ if( n.getKind()==kind::STRING_SUBSTR ){
+ r_effort = 1;
+ }else if( n.getKind()!=kind::STRING_IN_REGEXP ){
+ r_effort = 2;
+ }
+ }
+ }
+ if( effort==r_effort ){
+ Node c_n = pol==-1 ? n.negate() : n;
+ if( d_preproc_cache.find( c_n )==d_preproc_cache.end() ){
+ d_preproc_cache[ c_n ] = true;
+ Trace("strings-process-debug") << "Process reduction for " << n << ", pol = " << pol << std::endl;
+ if( n.getKind()==kind::STRING_STRCTN && pol==1 ){
+ Node x = n[0];
+ Node s = n[1];
+ //positive contains reduces to a equality
+ Node sk1 = mkSkolemCached( x, s, sk_id_ctn_pre, "sc1" );
+ Node sk2 = mkSkolemCached( x, s, sk_id_ctn_post, "sc2" );
+ Node eq = Rewriter::rewrite( x.eqNode( mkConcat( sk1, s, sk2 ) ) );
+ std::vector< Node > exp_vec;
+ exp_vec.push_back( n );
+ sendInference( d_empty_vec, exp_vec, eq, "POS-CTN", true );
+ //we've reduced this n
+ Trace("strings-extf-debug") << " resolve extf : " << n << " based on positive contain reduction." << std::endl;
+ return 1;
+ }else{
+ // for STRING_SUBSTR, STRING_STRCTN with pol=-1,
+ // STRING_STRIDOF, STRING_ITOS, STRING_U16TOS, STRING_U32TOS, STRING_STOI, STRING_STOU16, STRING_STOU32, STRING_STRREPL
+ std::vector< Node > new_nodes;
+ Node res = d_preproc.simplify( n, new_nodes );
+ Assert( res!=n );
+ new_nodes.push_back( NodeManager::currentNM()->mkNode( res.getType().isBoolean() ? kind::IFF : kind::EQUAL, res, n ) );
+ Node nnlem = new_nodes.size()==1 ? new_nodes[0] : NodeManager::currentNM()->mkNode( kind::AND, new_nodes );
+ nnlem = Rewriter::rewrite( nnlem );
+ Trace("strings-red-lemma") << "Reduction_" << effort << " lemma : " << nnlem << std::endl;
+ Trace("strings-red-lemma") << "...from " << n << std::endl;
+ sendInference( d_empty_vec, nnlem, "Reduction", true );
+ //we've reduced this n
+ Trace("strings-extf-debug") << " resolve extf : " << n << " based on reduction." << std::endl;
+ return 1;
+ }
+ }else{
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
/////////////////////////////////////////////////////////////////////////////
// NOTIFICATIONS
/////////////////////////////////////////////////////////////////////////////
@@ -404,15 +490,13 @@ void TheoryStrings::collectModelInfo( TheoryModel* m, bool fullModel ) {
for( unsigned j=0; j<col[i].size(); j++ ) {
Trace("strings-model") << col[i][j] << " ";
//check if col[i][j] has only variables
- EqcInfo* ei = getOrMakeEqcInfo( col[i][j], false );
- Node cst = ei ? ei->d_const_term : Node::null();
- if( cst.isNull() ){
+ if( !col[i][j].isConst() ){
Assert( d_normal_forms.find( col[i][j] )!=d_normal_forms.end() );
if( d_normal_forms[col[i][j]].size()==1 ){//&& d_normal_forms[col[i][j]][0]==col[i][j] ){
pure_eq.push_back( col[i][j] );
}
}else{
- processed[col[i][j]] = cst;
+ processed[col[i][j]] = col[i][j];
}
}
Trace("strings-model") << "have length " << lts_values[i] << std::endl;
@@ -692,104 +776,29 @@ bool TheoryStrings::needsCheckLastEffort() {
}
void TheoryStrings::checkExtfReductions( int effort ) {
+ //standardize this?
+ //std::vector< Node > nred;
+ //d_extt->doReductions( effort, nred, false );
+
std::vector< Node > extf;
d_extt->getActive( extf );
+ Trace("strings-process") << "checking " << extf.size() << " active extf" << std::endl;
for( unsigned i=0; i<extf.size(); i++ ){
Node n = extf[i];
- if( d_extf_info_tmp[n].d_model_active ){
- Assert( d_extf_info_tmp.find( n )!=d_extf_info_tmp.end() );
- if( checkExtfReduction( n, d_extf_info_tmp[n].d_pol, effort ) ){
- d_extt->markReduced( n );
- }
- if( hasProcessed() ){
+ Trace("strings-process") << "Check " << n << ", active in model=" << d_extf_info_tmp[n].d_model_active << std::endl;
+ Node nr;
+ int ret = getReduction( effort, n, nr );
+ Assert( nr.isNull() );
+ if( ret!=0 ){
+ d_extt->markReduced( extf[i] );
+ if( options::stringOpt1() && hasProcessed() ){
return;
}
}
}
}
-bool TheoryStrings::checkExtfReduction( Node atom, int pol, int effort ) {
- //determine the effort level to process the extf at
- // 0 - at assertion time, 1+ - after no other reduction is applicable
- int r_effort = -1;
- if( atom.getKind()==kind::STRING_STRCTN ){
- if( pol==1 ){
- r_effort = 1;
- }else{
- Assert( pol==-1 );
- if( effort==2 ){
- Node x = atom[0];
- Node s = atom[1];
- std::vector< Node > lexp;
- Node lenx = getLength( x, lexp );
- Node lens = getLength( s, lexp );
- if( areEqual( lenx, lens ) ){
- Trace("strings-extf-debug") << " resolve extf : " << atom << " based on equal lengths disequality." << std::endl;
- //we can reduce to disequality when lengths are equal
- if( !areDisequal( x, s ) ){
- lexp.push_back( lenx.eqNode(lens) );
- lexp.push_back( atom.negate() );
- Node xneqs = x.eqNode(s).negate();
- sendInference( lexp, xneqs, "NEG-CTN-EQL", true );
- }
- return true;
- }else if( !areDisequal( lenx, lens ) ){
- //split on their lenths
- sendSplit( lenx, lens, "NEG-CTN-SP" );
- }else{
- r_effort = 2;
- }
- }
- }
- }else{
- if( options::stringLazyPreproc() ){
- if( atom.getKind()==kind::STRING_SUBSTR ){
- r_effort = 1;
- }else if( atom.getKind()!=kind::STRING_IN_REGEXP ){
- r_effort = 2;
- }
- }
- }
- if( effort==r_effort ){
- Node c_atom = pol==-1 ? atom.negate() : atom;
- if( d_preproc_cache.find( c_atom )==d_preproc_cache.end() ){
- d_preproc_cache[ c_atom ] = true;
- Trace("strings-process-debug") << "Process reduction for " << atom << ", pol = " << pol << std::endl;
- if( atom.getKind()==kind::STRING_STRCTN && pol==1 ){
- Node x = atom[0];
- Node s = atom[1];
- //positive contains reduces to a equality
- Node sk1 = mkSkolemCached( x, s, sk_id_ctn_pre, "sc1" );
- Node sk2 = mkSkolemCached( x, s, sk_id_ctn_post, "sc2" );
- Node eq = Rewriter::rewrite( x.eqNode( mkConcat( sk1, s, sk2 ) ) );
- std::vector< Node > exp_vec;
- exp_vec.push_back( atom );
- sendInference( d_empty_vec, exp_vec, eq, "POS-CTN", true );
- //we've reduced this atom
- Trace("strings-extf-debug") << " resolve extf : " << atom << " based on positive contain reduction." << std::endl;
- return true;
- }else{
- // for STRING_SUBSTR, STRING_STRCTN with pol=-1,
- // STRING_STRIDOF, STRING_ITOS, STRING_U16TOS, STRING_U32TOS, STRING_STOI, STRING_STOU16, STRING_STOU32, STRING_STRREPL
- std::vector< Node > new_nodes;
- Node res = d_preproc.simplify( atom, new_nodes );
- Assert( res!=atom );
- new_nodes.push_back( NodeManager::currentNM()->mkNode( res.getType().isBoolean() ? kind::IFF : kind::EQUAL, res, atom ) );
- Node nnlem = new_nodes.size()==1 ? new_nodes[0] : NodeManager::currentNM()->mkNode( kind::AND, new_nodes );
- nnlem = Rewriter::rewrite( nnlem );
- Trace("strings-red-lemma") << "Reduction_" << effort << " lemma : " << nnlem << std::endl;
- Trace("strings-red-lemma") << "...from " << atom << std::endl;
- sendInference( d_empty_vec, nnlem, "Reduction", true );
- //we've reduced this atom
- Trace("strings-extf-debug") << " resolve extf : " << atom << " based on reduction." << std::endl;
- return true;
- }
- }
- }
- return false;
-}
-
-TheoryStrings::EqcInfo::EqcInfo( context::Context* c ) : d_const_term(c), d_length_term(c), d_cardinality_lem_k(c), d_normalized_length(c) {
+TheoryStrings::EqcInfo::EqcInfo( context::Context* c ) : d_length_term(c), d_cardinality_lem_k(c), d_normalized_length(c) {
}
@@ -827,10 +836,6 @@ void TheoryStrings::conflict(TNode a, TNode b){
/** called when a new equivalance class is created */
void TheoryStrings::eqNotifyNewClass(TNode t){
- if( t.getKind() == kind::CONST_STRING ){
- EqcInfo * ei =getOrMakeEqcInfo( t, true );
- ei->d_const_term = t;
- }
if( t.getKind() == kind::STRING_LENGTH ){
Trace("strings-debug") << "New length eqc : " << t << std::endl;
Node r = d_equalityEngine.getRepresentative(t[0]);
@@ -838,6 +843,8 @@ void TheoryStrings::eqNotifyNewClass(TNode t){
ei->d_length_term = t[0];
//we care about the length of this string
registerTerm( t[0], 1 );
+ }else{
+ //d_extt->registerTerm( t );
}
}
@@ -847,9 +854,6 @@ void TheoryStrings::eqNotifyPreMerge(TNode t1, TNode t2){
if( e2 ){
EqcInfo * e1 = getOrMakeEqcInfo( t1 );
//add information from e2 to e1
- if( !e2->d_const_term.get().isNull() ){
- e1->d_const_term.set( e2->d_const_term );
- }
if( !e2->d_length_term.get().isNull() ){
e1->d_length_term.set( e2->d_length_term );
}
@@ -987,7 +991,6 @@ void TheoryStrings::assertPendingFact(Node atom, bool polarity, Node exp) {
d_equalityEngine.assertPredicate( atom, polarity, exp );
//process extf
if( atom.getKind()==kind::STRING_IN_REGEXP ){
- d_extt->registerTerm( atom );
if( polarity && atom[1].getKind()==kind::REGEXP_RANGE ){
if( d_extf_infer_cache_u.find( atom )==d_extf_infer_cache_u.end() ){
d_extf_infer_cache_u.insert( atom );
@@ -999,6 +1002,8 @@ void TheoryStrings::assertPendingFact(Node atom, bool polarity, Node exp) {
}
}
}
+ //register the atom here, since it may not create a new equivalence class
+ //d_extt->registerTerm( atom );
}
Trace("strings-pending-debug") << " Now collect terms" << std::endl;
//collect extended function terms in the atom
@@ -1292,7 +1297,8 @@ void TheoryStrings::checkExtfEval( int effort ) {
std::vector< Node > terms;
std::vector< Node > sterms;
std::vector< std::vector< Node > > exp;
- d_extt->getInferences( effort, terms, sterms, exp );
+ d_extt->getActive( terms );
+ d_extt->getSubstitutedTerms( effort, terms, sterms, exp );
for( unsigned i=0; i<terms.size(); i++ ){
Node n = terms[i];
Node sn = sterms[i];
@@ -3875,16 +3881,6 @@ Node TheoryStrings::ppRewrite(TNode atom) {
return atom;
}
-void TheoryStrings::collectExtendedFuncTerms( Node n, std::map< Node, bool >& visited ) {
- if( visited.find( n )==visited.end() ){
- visited[n] = true;
- d_extt->registerTerm( n );
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- collectExtendedFuncTerms( n[i], visited );
- }
- }
-}
-
// Stats
TheoryStrings::Statistics::Statistics():
d_splits("TheoryStrings::NumOfSplitOnDemands", 0),
@@ -3974,17 +3970,11 @@ Node TheoryStrings::normalizeRegexp(Node r) {
if(r[0].isConst()) {
break;
} else {
- if (d_normal_forms.find(r[0]) != d_normal_forms.end()) {
- const std::vector<Node>& nf_r0 = d_normal_forms[r[0]];
- nf_r = mkConcat(nf_r0);
- Debug("regexp-nf") << "Term: " << r[0] << " has a normal form "
- << nf_r << std::endl;
- std::vector<Node>::iterator nf_end_exp = nf_exp.end();
- std::vector<Node>::const_iterator nf_r0_begin = nf_r0.begin();
- std::vector<Node>::const_iterator nf_r0_end = nf_r0.end();
- nf_exp.insert(nf_end_exp, nf_r0_begin, nf_r0_end);
- nf_r = Rewriter::rewrite(NodeManager::currentNM()->mkNode(
- kind::STRING_TO_REGEXP, nf_r));
+ if(d_normal_forms.find( r[0] ) != d_normal_forms.end()) {
+ nf_r = mkConcat( d_normal_forms[r[0]] );
+ Debug("regexp-nf") << "Term: " << r[0] << " has a normal form " << nf_r << std::endl;
+ nf_exp.insert(nf_exp.end(), d_normal_forms_exp[r[0]].begin(), d_normal_forms_exp[r[0]].end());
+ nf_r = Rewriter::rewrite( NodeManager::currentNM()->mkNode(kind::STRING_TO_REGEXP, nf_r) );
}
}
}
@@ -4873,6 +4863,16 @@ Node TheoryStrings::getNormalSymRegExp(Node r, std::vector<Node> &nf_exp) {
return ret;
}
+void TheoryStrings::collectExtendedFuncTerms( Node n, std::map< Node, bool >& visited ) {
+ if( visited.find( n )==visited.end() ){
+ visited[n] = true;
+ d_extt->registerTerm( n );
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ collectExtendedFuncTerms( n[i], visited );
+ }
+ }
+}
+
}/* CVC4::theory::strings namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/strings/theory_strings.h b/src/theory/strings/theory_strings.h
index fe72bd8e7..fd984bd58 100644
--- a/src/theory/strings/theory_strings.h
+++ b/src/theory/strings/theory_strings.h
@@ -72,6 +72,7 @@ public:
Node explain( TNode literal );
eq::EqualityEngine * getEqualityEngine() { return &d_equalityEngine; }
bool getCurrentSubstitution( int effort, std::vector< Node >& vars, std::vector< Node >& subs, std::map< Node, std::vector< Node > >& exp );
+ int getReduction( int effort, Node n, Node& nr );
// NotifyClass for equality engine
class NotifyClass : public eq::EqualityEngineNotify {
@@ -237,7 +238,6 @@ private:
EqcInfo( context::Context* c );
~EqcInfo(){}
//constant in this eqc
- context::CDO< Node > d_const_term;
context::CDO< Node > d_length_term;
context::CDO< unsigned > d_cardinality_lem_k;
// 1 = added length lemma
@@ -274,8 +274,6 @@ private:
int d_pol;
//explanation
std::vector< Node > d_exp;
- //reps -> list of variables
- //std::map< Node, std::vector< Node > > d_rep_vars;
//false if it is reduced in the model
bool d_model_active;
};
@@ -321,7 +319,6 @@ private:
Node getSymbolicDefinition( Node n, std::vector< Node >& exp );
//check extf reduction
void checkExtfReductions( int effort );
- bool checkExtfReduction( Node atom, int pol, int effort );
//flat forms check
void checkFlatForms();
Node checkCycles( Node eqc, std::vector< Node >& curr, std::vector< Node >& exp );
@@ -523,6 +520,7 @@ public:
~Statistics();
};/* class TheoryStrings::Statistics */
Statistics d_statistics;
+
};/* class TheoryStrings */
}/* CVC4::theory::strings namespace */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback