mirror of
https://github.com/Z3Prover/z3
synced 2025-06-06 06:03:23 +00:00
finite model finding for other concat cases in theory_str
This commit is contained in:
parent
e459617c39
commit
0af834421f
2 changed files with 220 additions and 159 deletions
|
@ -3126,7 +3126,6 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
|
||||||
// Type 0: M cuts Y.
|
// Type 0: M cuts Y.
|
||||||
// len(x) < len(m) || len(y) > len(n)
|
// len(x) < len(m) || len(y) > len(n)
|
||||||
//--------------------------------------
|
//--------------------------------------
|
||||||
if (!has_self_cut(m, y)) {
|
|
||||||
expr_ref_vector ax_l_items(mgr);
|
expr_ref_vector ax_l_items(mgr);
|
||||||
expr_ref_vector ax_r_items(mgr);
|
expr_ref_vector ax_r_items(mgr);
|
||||||
|
|
||||||
|
@ -3153,6 +3152,7 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
|
||||||
expr_ref ax_l(mk_and(ax_l_items), mgr);
|
expr_ref ax_l(mk_and(ax_l_items), mgr);
|
||||||
expr_ref ax_r(mk_and(ax_r_items), mgr);
|
expr_ref ax_r(mk_and(ax_r_items), mgr);
|
||||||
|
|
||||||
|
if (!has_self_cut(m, y)) {
|
||||||
// Cut Info
|
// Cut Info
|
||||||
add_cut_info_merge(t1, sLevel, m);
|
add_cut_info_merge(t1, sLevel, m);
|
||||||
add_cut_info_merge(t1, sLevel, y);
|
add_cut_info_merge(t1, sLevel, y);
|
||||||
|
@ -3165,9 +3165,15 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
loopDetected = true;
|
loopDetected = true;
|
||||||
|
if (m_params.m_FiniteOverlapModels) {
|
||||||
|
expr_ref tester = set_up_finite_model_test(concatAst1, concatAst2);
|
||||||
|
assert_implication(ax_l, tester);
|
||||||
|
add_theory_aware_branching_info(tester, -0.1, l_true);
|
||||||
|
} else {
|
||||||
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
||||||
// TODO printCutVar(m, y);
|
// TODO printCutVar(m, y);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (splitType == 1) {
|
} else if (splitType == 1) {
|
||||||
// Type 1:
|
// Type 1:
|
||||||
// len(x) = len(m) || len(y) = len(n)
|
// len(x) = len(m) || len(y) = len(n)
|
||||||
|
@ -3179,7 +3185,6 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
|
||||||
} else if (splitType == 2) {
|
} else if (splitType == 2) {
|
||||||
// Type 2: X cuts N.
|
// Type 2: X cuts N.
|
||||||
// len(x) > len(m) || len(y) < len(n)
|
// len(x) > len(m) || len(y) < len(n)
|
||||||
if (!has_self_cut(x, n)) {
|
|
||||||
expr_ref m_t2(mk_concat(m, t2), mgr);
|
expr_ref m_t2(mk_concat(m, t2), mgr);
|
||||||
expr_ref t2_y(mk_concat(t2, y), mgr);
|
expr_ref t2_y(mk_concat(t2, y), mgr);
|
||||||
|
|
||||||
|
@ -3205,6 +3210,7 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
|
||||||
expr_ref ax_l(mk_and(ax_l_items), mgr);
|
expr_ref ax_l(mk_and(ax_l_items), mgr);
|
||||||
expr_ref ax_r(mk_and(ax_r_items), mgr);
|
expr_ref ax_r(mk_and(ax_r_items), mgr);
|
||||||
|
|
||||||
|
if (!has_self_cut(x, n)) {
|
||||||
// Cut Info
|
// Cut Info
|
||||||
add_cut_info_merge(t2, sLevel, x);
|
add_cut_info_merge(t2, sLevel, x);
|
||||||
add_cut_info_merge(t2, sLevel, n);
|
add_cut_info_merge(t2, sLevel, n);
|
||||||
|
@ -3217,9 +3223,15 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
loopDetected = true;
|
loopDetected = true;
|
||||||
|
if (m_params.m_FiniteOverlapModels) {
|
||||||
|
expr_ref tester = set_up_finite_model_test(concatAst1, concatAst2);
|
||||||
|
assert_implication(ax_l, tester);
|
||||||
|
add_theory_aware_branching_info(tester, -0.1, l_true);
|
||||||
|
} else {
|
||||||
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
||||||
// TODO printCutVar(m, y);
|
// TODO printCutVar(m, y);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (splitType == -1) {
|
} else if (splitType == -1) {
|
||||||
// Here we don't really have a choice. We have no length information at all...
|
// Here we don't really have a choice. We have no length information at all...
|
||||||
|
|
||||||
|
@ -3265,12 +3277,19 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
|
||||||
add_cut_info_merge(t1, ctx.get_scope_level(), y);
|
add_cut_info_merge(t1, ctx.get_scope_level(), y);
|
||||||
} else {
|
} else {
|
||||||
loopDetected = true;
|
loopDetected = true;
|
||||||
|
if (m_params.m_FiniteOverlapModels) {
|
||||||
|
expr_ref tester = set_up_finite_model_test(concatAst1, concatAst2);
|
||||||
|
arrangement_disjunction.push_back(tester);
|
||||||
|
add_theory_aware_branching_info(tester, -0.1, l_true);
|
||||||
|
} else {
|
||||||
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
||||||
TRACE("t_str_detail", {print_cut_var(m, tout); print_cut_var(y, tout);});
|
TRACE("t_str_detail", {print_cut_var(m, tout); print_cut_var(y, tout);});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// break option 2:
|
// break option 2:
|
||||||
// x = m || y = n
|
// x = m . t2
|
||||||
|
// n = t2 . y
|
||||||
if (!avoidLoopCut || !has_self_cut(x, n)) {
|
if (!avoidLoopCut || !has_self_cut(x, n)) {
|
||||||
expr_ref_vector and_item(mgr);
|
expr_ref_vector and_item(mgr);
|
||||||
// break down option 1-2
|
// break down option 1-2
|
||||||
|
@ -3302,10 +3321,19 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
|
||||||
add_cut_info_merge(t2, ctx.get_scope_level(), n);
|
add_cut_info_merge(t2, ctx.get_scope_level(), n);
|
||||||
} else {
|
} else {
|
||||||
loopDetected = true;
|
loopDetected = true;
|
||||||
|
if (m_params.m_FiniteOverlapModels) {
|
||||||
|
// TODO this might repeat the case above, we may wish to avoid doing this twice
|
||||||
|
expr_ref tester = set_up_finite_model_test(concatAst1, concatAst2);
|
||||||
|
arrangement_disjunction.push_back(tester);
|
||||||
|
add_theory_aware_branching_info(tester, -0.1, l_true);
|
||||||
|
} else {
|
||||||
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
||||||
// TODO printCutVar(x, n);
|
// TODO printCutVar(x, n);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// option 3:
|
||||||
|
// x = m, y = n
|
||||||
if (can_two_nodes_eq(x, m) && can_two_nodes_eq(y, n)) {
|
if (can_two_nodes_eq(x, m) && can_two_nodes_eq(y, n)) {
|
||||||
expr_ref_vector and_item(mgr);
|
expr_ref_vector and_item(mgr);
|
||||||
|
|
||||||
|
@ -3496,8 +3524,6 @@ void theory_str::process_concat_eq_type2(expr * concatAst1, expr * concatAst2) {
|
||||||
// | m | str |
|
// | m | str |
|
||||||
expr_ref temp1_strAst(mk_concat(temp1, strAst), mgr);
|
expr_ref temp1_strAst(mk_concat(temp1, strAst), mgr);
|
||||||
if (can_two_nodes_eq(y, temp1_strAst)) {
|
if (can_two_nodes_eq(y, temp1_strAst)) {
|
||||||
if (!avoidLoopCut || !(has_self_cut(m, y))) {
|
|
||||||
// break down option 2-1
|
|
||||||
expr_ref_vector l_items(mgr);
|
expr_ref_vector l_items(mgr);
|
||||||
l_items.push_back(ctx.mk_eq_atom(concatAst1, concatAst2));
|
l_items.push_back(ctx.mk_eq_atom(concatAst1, concatAst2));
|
||||||
|
|
||||||
|
@ -3521,6 +3547,8 @@ void theory_str::process_concat_eq_type2(expr * concatAst1, expr * concatAst2) {
|
||||||
expr_ref ax_l(mk_and(l_items), mgr);
|
expr_ref ax_l(mk_and(l_items), mgr);
|
||||||
expr_ref ax_r(mk_and(r_items), mgr);
|
expr_ref ax_r(mk_and(r_items), mgr);
|
||||||
|
|
||||||
|
if (!avoidLoopCut || !(has_self_cut(m, y))) {
|
||||||
|
// break down option 2-1
|
||||||
add_cut_info_merge(temp1, sLevel, y);
|
add_cut_info_merge(temp1, sLevel, y);
|
||||||
add_cut_info_merge(temp1, sLevel, m);
|
add_cut_info_merge(temp1, sLevel, m);
|
||||||
|
|
||||||
|
@ -3532,10 +3560,17 @@ void theory_str::process_concat_eq_type2(expr * concatAst1, expr * concatAst2) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
loopDetected = true;
|
loopDetected = true;
|
||||||
|
|
||||||
|
if (m_params.m_FiniteOverlapModels) {
|
||||||
|
expr_ref tester = set_up_finite_model_test(concatAst1, concatAst2);
|
||||||
|
assert_implication(ax_l, tester);
|
||||||
|
add_theory_aware_branching_info(tester, -0.1, l_true);
|
||||||
|
} else {
|
||||||
TRACE("t_str", tout << "AVOID LOOP: SKIP" << std::endl;);
|
TRACE("t_str", tout << "AVOID LOOP: SKIP" << std::endl;);
|
||||||
// TODO printCutVar(m, y);
|
// TODO printCutVar(m, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (splitType == 1) {
|
} else if (splitType == 1) {
|
||||||
// | x | y |
|
// | x | y |
|
||||||
// | m | str |
|
// | m | str |
|
||||||
|
@ -3634,10 +3669,16 @@ void theory_str::process_concat_eq_type2(expr * concatAst1, expr * concatAst2) {
|
||||||
add_cut_info_merge(temp1, ctx.get_scope_level(), m);
|
add_cut_info_merge(temp1, ctx.get_scope_level(), m);
|
||||||
} else {
|
} else {
|
||||||
loopDetected = true;
|
loopDetected = true;
|
||||||
|
if (m_params.m_FiniteOverlapModels) {
|
||||||
|
expr_ref tester = set_up_finite_model_test(concatAst1, concatAst2);
|
||||||
|
arrangement_disjunction.push_back(tester);
|
||||||
|
add_theory_aware_branching_info(tester, -0.1, l_true);
|
||||||
|
} else {
|
||||||
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
||||||
// TODO printCutVar(m, y)
|
// TODO printCutVar(m, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i <= (int)strValue.size(); ++i) {
|
for (int i = 0; i <= (int)strValue.size(); ++i) {
|
||||||
std::string part1Str = strValue.substr(0, i);
|
std::string part1Str = strValue.substr(0, i);
|
||||||
|
@ -3921,10 +3962,16 @@ void theory_str::process_concat_eq_type3(expr * concatAst1, expr * concatAst2) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
loopDetected = true;
|
loopDetected = true;
|
||||||
|
if (m_params.m_FiniteOverlapModels) {
|
||||||
|
expr_ref tester = set_up_finite_model_test(concatAst1, concatAst2);
|
||||||
|
assert_implication(ax_l, tester);
|
||||||
|
add_theory_aware_branching_info(tester, -0.1, l_true);
|
||||||
|
} else {
|
||||||
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
||||||
// TODO printCutVar(x, n);
|
// TODO printCutVar(x, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// else {
|
// else {
|
||||||
// // negate! It's impossible to split str with these lengths
|
// // negate! It's impossible to split str with these lengths
|
||||||
// __debugPrint(logFile, "[Conflict] Negate! It's impossible to split str with these lengths @ %d.\n", __LINE__);
|
// __debugPrint(logFile, "[Conflict] Negate! It's impossible to split str with these lengths @ %d.\n", __LINE__);
|
||||||
|
@ -3995,10 +4042,16 @@ void theory_str::process_concat_eq_type3(expr * concatAst1, expr * concatAst2) {
|
||||||
add_cut_info_merge(temp1, sLevel, n);
|
add_cut_info_merge(temp1, sLevel, n);
|
||||||
} else {
|
} else {
|
||||||
loopDetected = true;
|
loopDetected = true;
|
||||||
|
if (m_params.m_FiniteOverlapModels) {
|
||||||
|
expr_ref tester = set_up_finite_model_test(concatAst1, concatAst2);
|
||||||
|
arrangement_disjunction.push_back(tester);
|
||||||
|
add_theory_aware_branching_info(tester, -0.1, l_true);
|
||||||
|
} else {
|
||||||
TRACE("t_str", tout << "AVOID LOOP: SKIPPED." << std::endl;);
|
TRACE("t_str", tout << "AVOID LOOP: SKIPPED." << std::endl;);
|
||||||
// TODO printCutVAR(x, n)
|
// TODO printCutVAR(x, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!arrangement_disjunction.empty()) {
|
if (!arrangement_disjunction.empty()) {
|
||||||
|
@ -4396,41 +4449,9 @@ void theory_str::process_concat_eq_type6(expr * concatAst1, expr * concatAst2) {
|
||||||
loopDetected = true;
|
loopDetected = true;
|
||||||
|
|
||||||
if (m_params.m_FiniteOverlapModels) {
|
if (m_params.m_FiniteOverlapModels) {
|
||||||
// TODO refactor this entire segment into its own method. this is really just for experiment purposes
|
expr_ref tester = set_up_finite_model_test(concatAst1, concatAst2);
|
||||||
TRACE("t_str", tout << "activating finite model testing for overlapping concats "
|
arrangement_disjunction.push_back(tester);
|
||||||
<< mk_pp(concatAst1, mgr) << " and " << mk_pp(concatAst2, mgr) << std::endl;);
|
add_theory_aware_branching_info(tester, -0.1, l_true);
|
||||||
std::map<expr*, int> concatMap;
|
|
||||||
std::map<expr*, int> unrollMap;
|
|
||||||
std::map<expr*, int> varMap;
|
|
||||||
classify_ast_by_type(concatAst1, varMap, concatMap, unrollMap);
|
|
||||||
classify_ast_by_type(concatAst2, varMap, concatMap, unrollMap);
|
|
||||||
TRACE("t_str_detail", tout << "found vars:";
|
|
||||||
for (std::map<expr*,int>::iterator it = varMap.begin(); it != varMap.end(); ++it) {
|
|
||||||
tout << " " << mk_pp(it->first, mgr);
|
|
||||||
}
|
|
||||||
tout << std::endl;
|
|
||||||
);
|
|
||||||
|
|
||||||
expr_ref testvar(mk_str_var("finiteModelTest"), mgr);
|
|
||||||
m_trail.push_back(testvar);
|
|
||||||
ptr_vector<expr> varlist;
|
|
||||||
|
|
||||||
for (std::map<expr*, int>::iterator it = varMap.begin(); it != varMap.end(); ++it) {
|
|
||||||
expr * v = it->first;
|
|
||||||
varlist.push_back(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
// make things easy for the core wrt. testvar
|
|
||||||
expr_ref t1(ctx.mk_eq_atom(testvar, m_strutil.mk_string("")), mgr);
|
|
||||||
expr_ref t_yes(ctx.mk_eq_atom(testvar, m_strutil.mk_string("yes")), mgr);
|
|
||||||
expr_ref testvaraxiom(mgr.mk_or(t1, t_yes), mgr);
|
|
||||||
assert_axiom(testvaraxiom);
|
|
||||||
|
|
||||||
finite_model_test_varlists.insert(testvar, varlist);
|
|
||||||
m_trail_stack.push(insert_obj_map<theory_str, expr, ptr_vector<expr> >(finite_model_test_varlists, testvar) );
|
|
||||||
|
|
||||||
arrangement_disjunction.push_back(t_yes);
|
|
||||||
add_theory_aware_branching_info(t_yes, -0.1, l_true);
|
|
||||||
} else {
|
} else {
|
||||||
TRACE("t_str", tout << "AVOID LOOP: SKIPPED." << std::endl;);
|
TRACE("t_str", tout << "AVOID LOOP: SKIPPED." << std::endl;);
|
||||||
TRACE("t_str", print_cut_var(m, tout); print_cut_var(y, tout););
|
TRACE("t_str", print_cut_var(m, tout); print_cut_var(y, tout););
|
||||||
|
@ -6603,6 +6624,44 @@ void theory_str::solve_concat_eq_str(expr * concat, expr * str) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr_ref theory_str::set_up_finite_model_test(expr * lhs, expr * rhs) {
|
||||||
|
context & ctx = get_context();
|
||||||
|
ast_manager & m = get_manager();
|
||||||
|
|
||||||
|
TRACE("t_str", tout << "activating finite model testing for overlapping concats "
|
||||||
|
<< mk_pp(lhs, m) << " and " << mk_pp(rhs, m) << std::endl;);
|
||||||
|
std::map<expr*, int> concatMap;
|
||||||
|
std::map<expr*, int> unrollMap;
|
||||||
|
std::map<expr*, int> varMap;
|
||||||
|
classify_ast_by_type(lhs, varMap, concatMap, unrollMap);
|
||||||
|
classify_ast_by_type(rhs, varMap, concatMap, unrollMap);
|
||||||
|
TRACE("t_str_detail", tout << "found vars:";
|
||||||
|
for (std::map<expr*,int>::iterator it = varMap.begin(); it != varMap.end(); ++it) {
|
||||||
|
tout << " " << mk_pp(it->first, m);
|
||||||
|
}
|
||||||
|
tout << std::endl;
|
||||||
|
);
|
||||||
|
|
||||||
|
expr_ref testvar(mk_str_var("finiteModelTest"), m);
|
||||||
|
m_trail.push_back(testvar);
|
||||||
|
ptr_vector<expr> varlist;
|
||||||
|
|
||||||
|
for (std::map<expr*, int>::iterator it = varMap.begin(); it != varMap.end(); ++it) {
|
||||||
|
expr * v = it->first;
|
||||||
|
varlist.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// make things easy for the core wrt. testvar
|
||||||
|
expr_ref t1(ctx.mk_eq_atom(testvar, m_strutil.mk_string("")), m);
|
||||||
|
expr_ref t_yes(ctx.mk_eq_atom(testvar, m_strutil.mk_string("yes")), m);
|
||||||
|
expr_ref testvaraxiom(m.mk_or(t1, t_yes), m);
|
||||||
|
assert_axiom(testvaraxiom);
|
||||||
|
|
||||||
|
finite_model_test_varlists.insert(testvar, varlist);
|
||||||
|
m_trail_stack.push(insert_obj_map<theory_str, expr, ptr_vector<expr> >(finite_model_test_varlists, testvar) );
|
||||||
|
return t_yes;
|
||||||
|
}
|
||||||
|
|
||||||
void theory_str::finite_model_test(expr * testvar, expr * str) {
|
void theory_str::finite_model_test(expr * testvar, expr * str) {
|
||||||
context & ctx = get_context();
|
context & ctx = get_context();
|
||||||
ast_manager & m = get_manager();
|
ast_manager & m = get_manager();
|
||||||
|
@ -6638,14 +6697,15 @@ void theory_str::finite_model_test(expr * testvar, expr * str) {
|
||||||
if (map_effectively_empty) {
|
if (map_effectively_empty) {
|
||||||
TRACE("t_str_detail", tout << "no existing length testers for " << mk_pp(v, m) << std::endl;);
|
TRACE("t_str_detail", tout << "no existing length testers for " << mk_pp(v, m) << std::endl;);
|
||||||
rational v_len;
|
rational v_len;
|
||||||
|
rational v_lower_bound;
|
||||||
|
rational v_upper_bound;
|
||||||
|
expr_ref vLengthExpr(mk_strlen(v), m);
|
||||||
if (get_len_value(v, v_len)) {
|
if (get_len_value(v, v_len)) {
|
||||||
TRACE("t_str_detail", tout << "length = " << v_len.to_string() << std::endl;);
|
TRACE("t_str_detail", tout << "length = " << v_len.to_string() << std::endl;);
|
||||||
|
v_lower_bound = v_len;
|
||||||
|
v_upper_bound = v_len;
|
||||||
} else {
|
} else {
|
||||||
expr_ref vLengthExpr(mk_strlen(v), m);
|
|
||||||
|
|
||||||
rational v_lower_bound;
|
|
||||||
bool lower_bound_exists = lower_bound(vLengthExpr, v_lower_bound);
|
bool lower_bound_exists = lower_bound(vLengthExpr, v_lower_bound);
|
||||||
rational v_upper_bound;
|
|
||||||
bool upper_bound_exists = upper_bound(vLengthExpr, v_upper_bound);
|
bool upper_bound_exists = upper_bound(vLengthExpr, v_upper_bound);
|
||||||
TRACE("t_str_detail", tout << "bounds = [" << (lower_bound_exists?v_lower_bound.to_string():"?")
|
TRACE("t_str_detail", tout << "bounds = [" << (lower_bound_exists?v_lower_bound.to_string():"?")
|
||||||
<< ".." << (upper_bound_exists?v_upper_bound.to_string():"?") << "]" << std::endl;);
|
<< ".." << (upper_bound_exists?v_upper_bound.to_string():"?") << "]" << std::endl;);
|
||||||
|
@ -6672,6 +6732,7 @@ void theory_str::finite_model_test(expr * testvar, expr * str) {
|
||||||
v_lower_bound = rational::zero();
|
v_lower_bound = rational::zero();
|
||||||
v_upper_bound = v_lower_bound + rational(10);
|
v_upper_bound = v_lower_bound + rational(10);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// now create a fake length tester over this finite disjunction of lengths
|
// now create a fake length tester over this finite disjunction of lengths
|
||||||
|
|
||||||
fvar_len_count_map[v] = 1;
|
fvar_len_count_map[v] = 1;
|
||||||
|
@ -6701,7 +6762,6 @@ void theory_str::finite_model_test(expr * testvar, expr * str) {
|
||||||
expr_ref implLhs(ctx.mk_eq_atom(testvar, str), m);
|
expr_ref implLhs(ctx.mk_eq_atom(testvar, str), m);
|
||||||
expr_ref implRhs(mk_and(andList), m);
|
expr_ref implRhs(mk_and(andList), m);
|
||||||
assert_implication(implLhs, implRhs);
|
assert_implication(implLhs, implRhs);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// TODO figure out this case
|
// TODO figure out this case
|
||||||
NOT_IMPLEMENTED_YET();
|
NOT_IMPLEMENTED_YET();
|
||||||
|
|
|
@ -592,6 +592,7 @@ namespace smt {
|
||||||
// TESTING
|
// TESTING
|
||||||
void refresh_theory_var(expr * e);
|
void refresh_theory_var(expr * e);
|
||||||
|
|
||||||
|
expr_ref set_up_finite_model_test(expr * lhs, expr * rhs);
|
||||||
void finite_model_test(expr * v, expr * c);
|
void finite_model_test(expr * v, expr * c);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue