mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 19:52:29 +00:00 
			
		
		
		
	add partial support for complementation of regular expressions. Handles case of complementing character ranges
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
		
							parent
							
								
									9dbb8057ca
								
							
						
					
					
						commit
						94453033b6
					
				
					 4 changed files with 93 additions and 6 deletions
				
			
		|  | @ -83,7 +83,7 @@ eautomaton* re2automaton::operator()(expr* e) { | |||
| 
 | ||||
| eautomaton* re2automaton::re2aut(expr* e) { | ||||
|     SASSERT(u.is_re(e)); | ||||
|     expr* e1, *e2; | ||||
|     expr *e0, *e1, *e2; | ||||
|     scoped_ptr<eautomaton> a, b; | ||||
|     unsigned lo, hi; | ||||
|     zstring s1, s2; | ||||
|  | @ -98,8 +98,7 @@ eautomaton* re2automaton::re2aut(expr* e) { | |||
|     } | ||||
|     else if (u.re.is_star(e, e1) && (a = re2aut(e1))) { | ||||
|         a->add_final_to_init_moves(); | ||||
|         a->add_init_to_final_states(); | ||||
|          | ||||
|         a->add_init_to_final_states();         | ||||
|         return a.detach();             | ||||
|     } | ||||
|     else if (u.re.is_plus(e, e1) && (a = re2aut(e1))) { | ||||
|  | @ -116,8 +115,6 @@ eautomaton* re2automaton::re2aut(expr* e) { | |||
|             unsigned start = s1[0]; | ||||
|             unsigned stop = s2[0]; | ||||
|             unsigned nb = s1.num_bits(); | ||||
|             sort_ref s(bv.mk_sort(nb), m);           | ||||
|             expr_ref v(m.mk_var(0, s), m); | ||||
|             expr_ref _start(bv.mk_numeral(start, nb), m); | ||||
|             expr_ref _stop(bv.mk_numeral(stop, nb), m); | ||||
|             a = alloc(eautomaton, sm, sym_expr::mk_range(_start, _stop)); | ||||
|  | @ -127,6 +124,39 @@ eautomaton* re2automaton::re2aut(expr* e) { | |||
|             TRACE("seq", tout << "Range expression is not handled: " << mk_pp(e, m) << "\n";); | ||||
|         } | ||||
|     } | ||||
|     else if (u.re.is_complement(e, e0)) { | ||||
|         if (u.re.is_range(e0, e1, e2) && u.str.is_string(e1, s1) && u.str.is_string(e2, s2) && | ||||
|             s1.length() == 1 && s2.length() == 1) { | ||||
|             unsigned start = s1[0]; | ||||
|             unsigned stop = s2[0]; | ||||
|             unsigned nb = s1.num_bits(); | ||||
|             sort_ref s(bv.mk_sort(nb), m);           | ||||
|             expr_ref v(m.mk_var(0, s), m); | ||||
|             expr_ref _start(bv.mk_numeral(start, nb), m); | ||||
|             expr_ref _stop(bv.mk_numeral(stop, nb), m); | ||||
|             expr_ref _pred(m.mk_not(m.mk_and(bv.mk_ule(_start, v), bv.mk_ule(v, _stop))), m); | ||||
|             a = alloc(eautomaton, sm, sym_expr::mk_pred(_pred)); | ||||
|             return a.detach(); | ||||
|         } | ||||
|         else if (u.re.is_to_re(e0, e1) && u.str.is_string(e1, s1) && s1.length() == 1) { | ||||
|             unsigned nb = s1.num_bits(); | ||||
|             sort_ref s(bv.mk_sort(nb), m);           | ||||
|             expr_ref v(m.mk_var(0, s), m); | ||||
|             expr_ref _ch(bv.mk_numeral(s1[0], nb), m);           | ||||
|             expr_ref _pred(m.mk_not(m.mk_eq(v, _ch)), m); | ||||
|             a = alloc(eautomaton, sm, sym_expr::mk_pred(_pred)); | ||||
|             return a.detach(); | ||||
|         } | ||||
|         else if (u.re.is_to_re(e0, e1) && u.str.is_unit(e1, e2)) { | ||||
|             expr_ref v(m.mk_var(0, m.get_sort(e2)), m); | ||||
|             expr_ref _pred(m.mk_not(m.mk_eq(v, e2)), m); | ||||
|             a = alloc(eautomaton, sm, sym_expr::mk_pred(_pred)); | ||||
|             return a.detach(); | ||||
|         } | ||||
|         else { | ||||
|             TRACE("seq", tout << "Complement expression is not handled: " << mk_pp(e, m) << "\n";); | ||||
|         } | ||||
|     } | ||||
|     else if (u.re.is_loop(e, e1, lo, hi) && (a = re2aut(e1))) { | ||||
|         scoped_ptr<eautomaton> eps = eautomaton::mk_epsilon(sm); | ||||
|         b = eautomaton::mk_epsilon(sm); | ||||
|  | @ -225,6 +255,9 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con | |||
|     case OP_RE_INTERSECT: | ||||
|         SASSERT(num_args == 2); | ||||
|         return mk_re_inter(args[0], args[1], result); | ||||
|     case OP_RE_COMPLEMENT: | ||||
|         SASSERT(num_args == 1); | ||||
|         return mk_re_complement(args[0], result); | ||||
|     case OP_RE_LOOP: | ||||
|         return mk_re_loop(num_args, args, result); | ||||
|     case OP_RE_EMPTY_SET: | ||||
|  | @ -967,6 +1000,26 @@ br_status seq_rewriter::mk_re_union(expr* a, expr* b, expr_ref& result) { | |||
|     return BR_FAILED; | ||||
| } | ||||
| 
 | ||||
| br_status seq_rewriter::mk_re_complement(expr* a, expr_ref& result) { | ||||
|     expr* e1, *e2; | ||||
|     if (m_util.re.is_intersection(a, e1, e2)) { | ||||
|         result = m_util.re.mk_union(m_util.re.mk_complement(e1), m_util.re.mk_complement(e2)); | ||||
|         return BR_REWRITE2; | ||||
|     } | ||||
|     if (m_util.re.is_union(a, e1, e2)) { | ||||
|         result = m_util.re.mk_inter(m_util.re.mk_complement(e1), m_util.re.mk_complement(e2)); | ||||
|         return BR_REWRITE2; | ||||
|     } | ||||
|     if (m_util.re.is_empty(a)) { | ||||
|         result = m_util.re.mk_full(m().get_sort(a)); | ||||
|         return BR_DONE; | ||||
|     } | ||||
|     if (m_util.re.is_full(a)) { | ||||
|         result = m_util.re.mk_empty(m().get_sort(a)); | ||||
|         return BR_DONE; | ||||
|     } | ||||
|     return BR_FAILED; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|    (emp n r) = emp | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue