@@ -1224,16 +1224,39 @@ namespace seq {
12241224 let n = len(x)
12251225 - len(a ++ b) = len(a) + len(b) if x = a ++ b
12261226 - len(unit(u)) = 1 if x = unit(u)
1227+ - len(extract(x, o, l)) = l if len(x) >= o + l etc
12271228 - len(str) = str.length() if x = str
12281229 - len(empty) = 0 if x = empty
12291230 - len(int.to.str(i)) >= 1 if x = int.to.str(i) and more generally if i = 0 then 1 else 1+floor(log(|i|))
12301231 - len(x) >= 0 otherwise
12311232 */
12321233 void axioms::length_axiom (expr* n) {
1233- expr* x = nullptr ;
1234+ expr* x = nullptr , * y = nullptr , * offs = nullptr , * l = nullptr ;
12341235 VERIFY (seq.str .is_length (n, x));
1235- if (seq.str .is_concat (x) ||
1236- seq.str .is_unit (x) ||
1236+ if (seq.str .is_concat (x) && to_app (x)->get_num_args () != 0 ) {
1237+ ptr_vector<expr> args;
1238+ for (auto arg : *to_app (x))
1239+ args.push_back (seq.str .mk_length (arg));
1240+ expr_ref len (a.mk_add (args), m);
1241+ add_clause (mk_eq (len, n));
1242+ }
1243+ else if (seq.str .is_extract (x, y, offs, l)) {
1244+ // len(extract(y, o, l)) = l if len(y) >= o + l, o >= 0, l >= 0
1245+ // len(extract(y, o, l)) = 0 if o < 0 or l <= 0 or len(y) < o
1246+ // len(extract(y, o, l)) = o + l - len(y) if o <= len(y) < o + l
1247+ expr_ref len_y (mk_len (y), m);
1248+ expr_ref z (a.mk_int (0 ), m);
1249+ expr_ref y_ge_l (a.mk_ge (len_y, a.mk_add (offs, l)), m);
1250+ expr_ref y_ge_o (a.mk_ge (len_y, offs), m);
1251+ expr_ref offs_ge_0 (a.mk_ge (offs, z), m);
1252+ expr_ref l_ge_0 (a.mk_ge (l, z), m);
1253+ add_clause (~offs_ge_0, ~l_ge_0, ~y_ge_l, mk_eq (n, l));
1254+ add_clause (offs_ge_0, mk_eq (n, z));
1255+ add_clause (l_ge_0, mk_eq (n, z));
1256+ add_clause (y_ge_o, mk_eq (n, z));
1257+ add_clause (~y_ge_o, y_ge_l, mk_eq (n, a.mk_sub (a.mk_add (offs, l), len_y)));
1258+ }
1259+ else if (seq.str .is_unit (x) ||
12371260 seq.str .is_empty (x) ||
12381261 seq.str .is_string (x)) {
12391262 expr_ref len (n, m);
0 commit comments