d_length_nodes(c),
//d_var_lmin( c ),
//d_var_lmax( c ),
- d_charAtUF(),
d_str_pos_ctn( c ),
d_str_neg_ctn( c ),
d_reg_exp_mem( c ),
d_equalityEngine.addFunctionKind(kind::STRING_LENGTH);
d_equalityEngine.addFunctionKind(kind::STRING_CONCAT);
d_equalityEngine.addFunctionKind(kind::STRING_STRCTN);
- //d_equalityEngine.addFunctionKind(kind::STRING_CHARAT_TOTAL);
+ d_equalityEngine.addFunctionKind(kind::STRING_CHARAT_TOTAL);
//d_equalityEngine.addFunctionKind(kind::STRING_SUBSTR_TOTAL);
d_zero = NodeManager::currentNM()->mkConst( Rational( 0 ) );
+ d_one = NodeManager::currentNM()->mkConst( Rational( 1 ) );
d_emptyString = NodeManager::currentNM()->mkConst( ::CVC4::String("") );
d_true = NodeManager::currentNM()->mkConst( true );
d_false = NodeManager::currentNM()->mkConst( false );
default:
if(n.getType().isString() && n.getKind() != kind::CONST_STRING && n.getKind()!=kind::STRING_CONCAT ) {
if( std::find( d_length_intro_vars.begin(), d_length_intro_vars.end(), n )==d_length_intro_vars.end() ) {
- Node n_len = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, n);
- Node n_len_eq_z = n_len.eqNode( d_zero );
- Node n_len_geq_zero = NodeManager::currentNM()->mkNode( kind::OR, n_len_eq_z,
- NodeManager::currentNM()->mkNode( kind::GT, n_len, d_zero) );
- Trace("strings-lemma") << "Strings::Lemma LENGTH >= 0 : " << n_len_geq_zero << std::endl;
- d_out->lemma(n_len_geq_zero);
- d_out->requirePhase( n_len_eq_z, true );
+ if(n.getKind() == kind::STRING_CHARAT_TOTAL) {
+ Node lenc_eq_one = d_one.eqNode(NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, n));
+ Trace("strings-lemma") << "Strings::Lemma LEN(CHAR) = 1 : " << lenc_eq_one << std::endl;
+ d_out->lemma(lenc_eq_one);
+ } else {
+ Node n_len = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, n);
+ Node n_len_eq_z = n_len.eqNode( d_zero );
+ Node n_len_geq_zero = NodeManager::currentNM()->mkNode( kind::OR, n_len_eq_z,
+ NodeManager::currentNM()->mkNode( kind::GT, n_len, d_zero) );
+ Trace("strings-lemma") << "Strings::Lemma LENGTH >= 0 : " << n_len_geq_zero << std::endl;
+ d_out->lemma(n_len_geq_zero);
+ d_out->requirePhase( n_len_eq_z, true );
+ }
}
// FMF
if( n.getKind() == kind::VARIABLE ) {//options::stringFMF() &&
addedLemma = checkLengthsEqc();
Trace("strings-process") << "Done check lengths, addedLemma = " << addedLemma << ", d_conflict = " << d_conflict << std::endl;
if(!d_conflict && !addedLemma) {
- addedLemma = checkCardinality();
- Trace("strings-process") << "Done check cardinality, addedLemma = " << addedLemma << ", d_conflict = " << d_conflict << std::endl;
+ addedLemma = checkContains();
+ Trace("strings-process") << "Done check contain constraints, addedLemma = " << addedLemma << ", d_conflict = " << d_conflict << std::endl;
if( !d_conflict && !addedLemma ) {
addedLemma = checkMemberships();
Trace("strings-process") << "Done check membership constraints, addedLemma = " << addedLemma << ", d_conflict = " << d_conflict << std::endl;
if( !d_conflict && !addedLemma ) {
- addedLemma = checkContains();
- Trace("strings-process") << "Done check contain constraints, addedLemma = " << addedLemma << ", d_conflict = " << d_conflict << std::endl;
+ addedLemma = checkCardinality();
+ Trace("strings-process") << "Done check cardinality, addedLemma = " << addedLemma << ", d_conflict = " << d_conflict << std::endl;
}
}
}
bool success;
do
{
- //---------------------do simple stuff first
+ //simple check
if( processSimpleNEq( normal_forms, normal_form_src, curr_exp, i, j, index_i, index_j, false ) ){
//added a lemma, return
return true;
}
- //----------------------
success = false;
//if we are at the end
}
}
- //Node sk = NodeManager::currentNM()->mkSkolem( "v_spt_$$", normal_forms[i][index_i].getType(), "created for v/v split" );
- //Node eq1 = Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::EQUAL, normal_forms[i][index_i],
- // NodeManager::currentNM()->mkNode( kind::STRING_CONCAT, normal_forms[j][index_j], sk ) ) );
- //Node eq2 = Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::EQUAL, normal_forms[j][index_j],
- // NodeManager::currentNM()->mkNode( kind::STRING_CONCAT, normal_forms[i][index_i], sk ) ) );
Node eq1 = mkSplitEq( "v_spt_l_$$", "created for v/v split", normal_forms[i][index_i], normal_forms[j][index_j], true );
Node eq2 = mkSplitEq( "v_spt_r_$$", "created for v/v split", normal_forms[j][index_j], normal_forms[i][index_i], true );
conc = NodeManager::currentNM()->mkNode( kind::OR, eq1, eq2 );
std::vector< Node > nfj;
nfj.insert( nfj.end(), d_normal_forms[nj].begin(), d_normal_forms[nj].end() );
- //int revRet = processReverseDeq( nfi, nfj, ni, nj );
- //if( revRet!=0 ){
- // return revRet==-1;
- //}
+ int revRet = processReverseDeq( nfi, nfj, ni, nj );
+ if( revRet!=0 ){
+ return revRet==-1;
+ }
nfi.clear();
nfi.insert( nfi.end(), d_normal_forms[ni].begin(), d_normal_forms[ni].end() );
Node g1 = Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::AND, NodeManager::currentNM()->mkNode( kind::GEQ, b1, d_zero ),
NodeManager::currentNM()->mkNode( kind::GEQ, NodeManager::currentNM()->mkNode( kind::MINUS, lenx, lens ), b1 ) ) );
Node b2 = NodeManager::currentNM()->mkBoundVar("bj", NodeManager::currentNM()->integerType());
- if(d_charAtUF.isNull()) {
- std::vector< TypeNode > argTypes;
- argTypes.push_back(NodeManager::currentNM()->stringType());
- argTypes.push_back(NodeManager::currentNM()->integerType());
- d_charAtUF = NodeManager::currentNM()->mkSkolem("charAt",
- NodeManager::currentNM()->mkFunctionType(
- argTypes,
- NodeManager::currentNM()->stringType()),
- "total charat",
- NodeManager::SKOLEM_EXACT_NAME);
- }
- Node s2 = NodeManager::currentNM()->mkNode(kind::APPLY_UF, d_charAtUF, x, NodeManager::currentNM()->mkNode( kind::PLUS, b1, b2 ));
- Node s5 = NodeManager::currentNM()->mkNode(kind::APPLY_UF, d_charAtUF, s, b2);
+ Node s2 = NodeManager::currentNM()->mkNode(kind::STRING_CHARAT_TOTAL, x, NodeManager::currentNM()->mkNode( kind::PLUS, b1, b2 ));
+ Node s5 = NodeManager::currentNM()->mkNode(kind::STRING_CHARAT_TOTAL, s, b2);
Node s1 = NodeManager::currentNM()->mkBoundVar("s1", NodeManager::currentNM()->stringType());
Node s3 = NodeManager::currentNM()->mkBoundVar("s3", NodeManager::currentNM()->stringType());
vec_nodes.push_back(cc);
cc = s2.eqNode(s5).negate();
vec_nodes.push_back(cc);
- cc = NodeManager::currentNM()->mkNode(kind::STRING_LENGTH, s2).eqNode(NodeManager::currentNM()->mkConst( Rational(1)));
- vec_nodes.push_back(cc);
- cc = NodeManager::currentNM()->mkNode(kind::STRING_LENGTH, s5).eqNode(NodeManager::currentNM()->mkConst( Rational(1)));
- vec_nodes.push_back(cc);
cc = NodeManager::currentNM()->mkNode(kind::STRING_LENGTH, s1).eqNode(NodeManager::currentNM()->mkNode( kind::PLUS, b1, b2 ));
vec_nodes.push_back(cc);
cc = NodeManager::currentNM()->mkNode(kind::STRING_LENGTH, s4).eqNode(b2);
std::vector< TypeNode > argTypes;
argTypes.push_back(NodeManager::currentNM()->stringType());
argTypes.push_back(NodeManager::currentNM()->integerType());
- d_charAtUF = NodeManager::currentNM()->mkSkolem("charAt",
- NodeManager::currentNM()->mkFunctionType(
- argTypes,
- NodeManager::currentNM()->stringType()),
- "total charat",
- NodeManager::SKOLEM_EXACT_NAME);
}
void StringsPreprocess::simplifyRegExp( Node s, Node r, std::vector< Node > &ret, std::vector< Node > &nn ) {
int v_id = 1 - c_id;
int len = t[c_id].getConst<Rational>().getNumerator().toUnsignedInt();
if(len > 1) {
- Node one = NodeManager::currentNM()->mkConst( ::CVC4::Rational(1) );
std::vector< Node > vec;
for(int i=0; i<len; i++) {
Node num = NodeManager::currentNM()->mkConst( ::CVC4::Rational(i) );
- Node sk = NodeManager::currentNM()->mkNode(kind::APPLY_UF, d_charAtUF, t[v_id][0], num);
+ Node sk = NodeManager::currentNM()->mkNode(kind::STRING_CHARAT_TOTAL, t[v_id][0], num);
vec.push_back(sk);
- Node lem = one.eqNode( NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, sk ) );
- new_nodes.push_back( lem );
}
Node lem = t[v_id][0].eqNode( NodeManager::currentNM()->mkNode( kind::STRING_CONCAT, vec ) );
lem = NodeManager::currentNM()->mkNode( kind::IMPLIES, t, lem );
tp = NodeManager::currentNM()->mkNode( kind::IMPLIES, lenxgti, tp );
new_nodes.push_back( tp );
- d_cache[t] = sk2;
- retNode = sk2;
- } else if( t.getKind() == kind::STRING_CHARAT_TOTAL ){
- Node sk1 = NodeManager::currentNM()->mkSkolem( "ca1_$$", NodeManager::currentNM()->stringType(), "created for charat" );
- Node sk2 = NodeManager::currentNM()->mkSkolem( "ca2_$$", NodeManager::currentNM()->stringType(), "created for charat" );
- Node sk3 = NodeManager::currentNM()->mkSkolem( "ca3_$$", NodeManager::currentNM()->stringType(), "created for charat" );
- Node x = simplify( t[0], new_nodes );
- Node lenxgti = NodeManager::currentNM()->mkNode( kind::GT,
- NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, x ), t[1] );
- Node x_eq_123 = NodeManager::currentNM()->mkNode( kind::EQUAL,
- NodeManager::currentNM()->mkNode( kind::STRING_CONCAT, sk1, sk2, sk3 ), x );
- Node len_sk1_eq_i = NodeManager::currentNM()->mkNode( kind::EQUAL, t[1],
- NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, sk1 ) );
- Node len_sk2_eq_1 = NodeManager::currentNM()->mkNode( kind::EQUAL, NodeManager::currentNM()->mkConst( Rational( 1 ) ),
- NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, sk2 ) );
-
- Node tp = NodeManager::currentNM()->mkNode( kind::AND, x_eq_123, len_sk1_eq_i, len_sk2_eq_1 );
- tp = NodeManager::currentNM()->mkNode( kind::IMPLIES, lenxgti, tp );
- new_nodes.push_back( tp );
-
d_cache[t] = sk2;
retNode = sk2;
} else if( t.getKind() == kind::STRING_STRIDOF ){
throw LogicException("string replace not supported in this release");
}
} else if(t.getKind() == kind::STRING_CHARAT) {
- Node sk2 = NodeManager::currentNM()->mkNode(kind::APPLY_UF, d_charAtUF, t[0], t[1]);
+ Node sk2 = NodeManager::currentNM()->mkNode(kind::STRING_CHARAT_TOTAL, t[0], t[1]);
Node sk1 = NodeManager::currentNM()->mkSkolem( "ca1_$$", NodeManager::currentNM()->stringType(), "created for charat" );
Node sk3 = NodeManager::currentNM()->mkSkolem( "ca3_$$", NodeManager::currentNM()->stringType(), "created for charat" );
Node x = simplify( t[0], new_nodes );
Node len_sk1_eq_i = t[1].eqNode( NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, sk1 ) );
Node tp = NodeManager::currentNM()->mkNode( kind::AND, x_eq_123, len_sk1_eq_i );
tp = NodeManager::currentNM()->mkNode( kind::IMPLIES, lenxgti, tp );
- Node len_sk2_eq_1 = NodeManager::currentNM()->mkNode( kind::EQUAL, NodeManager::currentNM()->mkConst( Rational( 1 ) ),
- NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, sk2 ) );
- tp = NodeManager::currentNM()->mkNode( kind::AND, len_sk2_eq_1, tp );
-
new_nodes.push_back( tp );
d_cache[t] = sk2;
retNode = sk2;
} else if(t.getKind() == kind::STRING_SUBSTR) {
- InternalError("CharAt and Substr should not be reached here.");
+ InternalError("Substr should not be reached here.");
} else if( t.getNumChildren()>0 ) {
std::vector< Node > cc;
if (t.getMetaKind() == kind::metakind::PARAMETERIZED) {