mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	new interpolation fixes; re-added fixedpoint-push/pop
This commit is contained in:
		
							parent
							
								
									7ca6c744fd
								
							
						
					
					
						commit
						49c72abb2d
					
				
					 10 changed files with 156 additions and 21 deletions
				
			
		| 
						 | 
				
			
			@ -1307,7 +1307,7 @@ ast_manager::ast_manager(ast_manager const & src, bool disable_proofs):
 | 
			
		|||
void ast_manager::init() {
 | 
			
		||||
    // TODO: the following is a HACK to enable proofs in the old smt solver
 | 
			
		||||
    // When we stop using that solver, this hack can be removed
 | 
			
		||||
    m_proof_mode = PGM_FINE;
 | 
			
		||||
    // m_proof_mode = PGM_FINE;
 | 
			
		||||
 | 
			
		||||
    m_int_real_coercions = true;
 | 
			
		||||
    m_debug_ref_count = false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -170,6 +170,11 @@ struct iz3checker : iz3base {
 | 
			
		|||
  iz3checker(ast_manager &_m)
 | 
			
		||||
    : iz3base(_m) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  iz3checker(iz3mgr &_m)
 | 
			
		||||
    : iz3base(_m) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
};  
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
| 
						 | 
				
			
			@ -193,6 +198,18 @@ bool iz3check(ast_manager &_m_manager,
 | 
			
		|||
  return chk.check(s,err,chk.cook(cnsts),to_std_vector(parents),chk.cook(interps),chk.cook(theory));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool iz3check(iz3mgr &mgr,
 | 
			
		||||
	      solver *s,
 | 
			
		||||
	      std::ostream &err,
 | 
			
		||||
	      const std::vector<iz3mgr::ast> &cnsts,
 | 
			
		||||
	      const std::vector<int> &parents,
 | 
			
		||||
	      const std::vector<iz3mgr::ast> &interps,
 | 
			
		||||
	      const std::vector<iz3mgr::ast> &theory)
 | 
			
		||||
{
 | 
			
		||||
  iz3checker chk(mgr);
 | 
			
		||||
  return chk.check(s,err,cnsts,parents,interps,theory);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool iz3check(ast_manager &_m_manager,
 | 
			
		||||
	      solver *s,
 | 
			
		||||
	      std::ostream &err,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,4 +38,12 @@ bool iz3check(ast_manager &_m_manager,
 | 
			
		|||
	      ast *tree,
 | 
			
		||||
	      const ptr_vector<ast> &interps);
 | 
			
		||||
 | 
			
		||||
bool iz3check(iz3mgr &mgr,
 | 
			
		||||
	      solver *s,
 | 
			
		||||
	      std::ostream &err,
 | 
			
		||||
	      const std::vector<iz3mgr::ast> &cnsts,
 | 
			
		||||
	      const std::vector<int> &parents,
 | 
			
		||||
	      const std::vector<iz3mgr::ast> &interps,
 | 
			
		||||
	      const ptr_vector<iz3mgr::ast> &theory);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -304,6 +304,7 @@ public:
 | 
			
		|||
    fr.fix_interpolants(interps_vec);
 | 
			
		||||
 | 
			
		||||
    interps = interps_vec;
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -476,6 +476,15 @@ void iz3mgr::get_farkas_coeffs(const ast &proof, std::vector<ast>& coeffs){
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void abs_rat(std::vector<rational> &rats){
 | 
			
		||||
  // check that they are all non-neg -- if neg, take abs val and warn!
 | 
			
		||||
  for(unsigned i = 0; i < rats.size(); i++)
 | 
			
		||||
    if(rats[i].is_neg()){
 | 
			
		||||
      //      std::cout << "negative Farkas coeff!\n";
 | 
			
		||||
      rats[i] = -rats[i];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void iz3mgr::get_farkas_coeffs(const ast &proof, std::vector<rational>& rats){
 | 
			
		||||
  symb s = sym(proof);
 | 
			
		||||
  int numps = s->get_num_parameters();
 | 
			
		||||
| 
						 | 
				
			
			@ -494,12 +503,15 @@ void iz3mgr::get_farkas_coeffs(const ast &proof, std::vector<rational>& rats){
 | 
			
		|||
    }
 | 
			
		||||
    rats[i-2] = r;
 | 
			
		||||
  }
 | 
			
		||||
#if 0
 | 
			
		||||
  if(rats.size() != 0 && rats[0].is_neg()){
 | 
			
		||||
    for(unsigned i = 0; i < rats.size(); i++){
 | 
			
		||||
      assert(rats[i].is_neg());
 | 
			
		||||
      rats[i] = -rats[i];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  abs_rat(rats);
 | 
			
		||||
  extract_lcd(rats);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -536,6 +548,7 @@ void iz3mgr::get_assign_bounds_coeffs(const ast &proof, std::vector<rational>& r
 | 
			
		|||
    }
 | 
			
		||||
    rats[i-1] = r;
 | 
			
		||||
  }
 | 
			
		||||
#if 0
 | 
			
		||||
  if(rats[1].is_neg()){ // work around bug -- if all coeffs negative, negate them
 | 
			
		||||
    for(unsigned i = 1; i < rats.size(); i++){
 | 
			
		||||
      if(!rats[i].is_neg())
 | 
			
		||||
| 
						 | 
				
			
			@ -543,6 +556,8 @@ void iz3mgr::get_assign_bounds_coeffs(const ast &proof, std::vector<rational>& r
 | 
			
		|||
      rats[i] = -rats[i];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  abs_rat(rats);
 | 
			
		||||
  extract_lcd(rats);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -626,7 +626,7 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
      ast equa = sep_cond(arg(pf,0),cond);
 | 
			
		||||
      if(is_equivrel_chain(equa)){
 | 
			
		||||
	ast lhs,rhs; eq_from_ineq(arg(neg_equality,0),lhs,rhs); // get inequality we need to prove
 | 
			
		||||
	ast ineqs= chain_ineqs(LitA,equa,lhs,rhs); // chain must be from lhs to rhs
 | 
			
		||||
	ast ineqs= chain_ineqs(op(arg(neg_equality,0)),LitA,equa,lhs,rhs); // chain must be from lhs to rhs
 | 
			
		||||
	cond = my_and(cond,chain_conditions(LitA,equa)); 
 | 
			
		||||
	ast Bconds = chain_conditions(LitB,equa); 
 | 
			
		||||
	if(is_true(Bconds) && op(ineqs) != And)
 | 
			
		||||
| 
						 | 
				
			
			@ -1313,7 +1313,7 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  ast chain_ineqs(LitType t, const ast &chain, const ast &lhs, const ast &rhs){
 | 
			
		||||
  ast chain_ineqs(opr comp_op, LitType t, const ast &chain, const ast &lhs, const ast &rhs){
 | 
			
		||||
    if(is_true(chain)){
 | 
			
		||||
      if(lhs != rhs)
 | 
			
		||||
	throw "bad ineq inference";
 | 
			
		||||
| 
						 | 
				
			
			@ -1322,9 +1322,12 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
    ast last = chain_last(chain);
 | 
			
		||||
    ast rest = chain_rest(chain);
 | 
			
		||||
    ast mid = subst_in_pos(rhs,rewrite_pos(last),rewrite_lhs(last));
 | 
			
		||||
    ast cond = chain_ineqs(t,rest,lhs,mid);
 | 
			
		||||
    ast cond = chain_ineqs(comp_op,t,rest,lhs,mid);
 | 
			
		||||
    if(is_rewrite_side(t,last)){
 | 
			
		||||
      ast foo = z3_simplify(make(Leq,make_int("0"),make(Sub,mid,rhs)));
 | 
			
		||||
      ast diff;
 | 
			
		||||
      if(comp_op == Leq) diff = make(Sub,rhs,mid);
 | 
			
		||||
      else diff = make(Sub,mid,rhs);
 | 
			
		||||
      ast foo = z3_simplify(make(Leq,make_int("0"),diff));
 | 
			
		||||
      if(is_true(cond))
 | 
			
		||||
	cond = foo;
 | 
			
		||||
      else {
 | 
			
		||||
| 
						 | 
				
			
			@ -1351,6 +1354,8 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
	std::swap(lhs,rhs);
 | 
			
		||||
      if(op(rhs) == Times){
 | 
			
		||||
	rhs = arg(rhs,1);
 | 
			
		||||
	if(op(ineq) == Leq)
 | 
			
		||||
	  std::swap(lhs,rhs);
 | 
			
		||||
	return;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1368,16 +1373,31 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
 | 
			
		||||
  /** Make an assumption node. The given clause is assumed in the given frame. */
 | 
			
		||||
  virtual node make_assumption(int frame, const std::vector<ast> &assumption){
 | 
			
		||||
    if(pv->in_range(frame,rng)){
 | 
			
		||||
      std::vector<ast> itp_clause;
 | 
			
		||||
      for(unsigned i = 0; i < assumption.size(); i++)
 | 
			
		||||
	if(get_term_type(assumption[i]) != LitA)
 | 
			
		||||
	  itp_clause.push_back(assumption[i]);
 | 
			
		||||
      ast res = my_or(itp_clause);
 | 
			
		||||
      return res;
 | 
			
		||||
    if(!weak){
 | 
			
		||||
      if(pv->in_range(frame,rng)){
 | 
			
		||||
	std::vector<ast> itp_clause;
 | 
			
		||||
	for(unsigned i = 0; i < assumption.size(); i++)
 | 
			
		||||
	  if(get_term_type(assumption[i]) != LitA)
 | 
			
		||||
	    itp_clause.push_back(assumption[i]);
 | 
			
		||||
	ast res = my_or(itp_clause);
 | 
			
		||||
	return res;
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
	return mk_true();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      return mk_true();
 | 
			
		||||
      if(pv->in_range(frame,rng)){
 | 
			
		||||
	return mk_false();
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
	std::vector<ast> itp_clause;
 | 
			
		||||
	for(unsigned i = 0; i < assumption.size(); i++)
 | 
			
		||||
	  if(get_term_type(assumption[i]) != LitB)
 | 
			
		||||
	    itp_clause.push_back(assumption[i]);
 | 
			
		||||
	ast res = my_or(itp_clause);
 | 
			
		||||
	return mk_not(res);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1602,17 +1622,20 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
  virtual node make_congruence(const ast &p, const ast &con, const ast &prem1){
 | 
			
		||||
    ast x = arg(p,0), y = arg(p,1);
 | 
			
		||||
    ast itp;
 | 
			
		||||
    LitType con_t = get_term_type(con);
 | 
			
		||||
    if(get_term_type(p) == LitA){
 | 
			
		||||
      if(get_term_type(con) == LitA)
 | 
			
		||||
      if(con_t == LitA)
 | 
			
		||||
	itp = mk_false();
 | 
			
		||||
      else if(con_t == LitB)
 | 
			
		||||
	itp = p;
 | 
			
		||||
      else
 | 
			
		||||
	itp = make_mixed_congruence(x, y, p, con, prem1);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      if(get_term_type(con) == LitA)
 | 
			
		||||
      if(con_t == LitA)
 | 
			
		||||
	itp = mk_not(p);
 | 
			
		||||
      else{
 | 
			
		||||
	if(get_term_type(con) == LitB)
 | 
			
		||||
	if(con_t == LitB)
 | 
			
		||||
	  itp = mk_true();
 | 
			
		||||
	else
 | 
			
		||||
	  itp = make_mixed_congruence(x, y, p, con, prem1);
 | 
			
		||||
| 
						 | 
				
			
			@ -2047,30 +2070,58 @@ public:
 | 
			
		|||
  {
 | 
			
		||||
    pv = p;
 | 
			
		||||
    rng = r;
 | 
			
		||||
    weak = w;
 | 
			
		||||
    weak = false ; //w;
 | 
			
		||||
    type boolintbooldom[3] = {bool_type(),int_type(),bool_type()};
 | 
			
		||||
    type booldom[1] = {bool_type()};
 | 
			
		||||
    type boolbooldom[2] = {bool_type(),bool_type()};
 | 
			
		||||
    type boolboolbooldom[3] = {bool_type(),bool_type(),bool_type()};
 | 
			
		||||
    type intbooldom[2] = {int_type(),bool_type()};
 | 
			
		||||
    contra = function("@contra",2,boolbooldom,bool_type());
 | 
			
		||||
    m().inc_ref(contra);
 | 
			
		||||
    sum = function("@sum",3,boolintbooldom,bool_type());
 | 
			
		||||
    m().inc_ref(sum);
 | 
			
		||||
    rotate_sum = function("@rotsum",2,boolbooldom,bool_type());
 | 
			
		||||
    m().inc_ref(rotate_sum);
 | 
			
		||||
    leq2eq = function("@leq2eq",3,boolboolbooldom,bool_type());
 | 
			
		||||
    m().inc_ref(leq2eq);
 | 
			
		||||
    eq2leq = function("@eq2leq",2,boolbooldom,bool_type());
 | 
			
		||||
    m().inc_ref(eq2leq);
 | 
			
		||||
    cong = function("@cong",3,boolintbooldom,bool_type());
 | 
			
		||||
    m().inc_ref(cong);
 | 
			
		||||
    exmid = function("@exmid",3,boolboolbooldom,bool_type());
 | 
			
		||||
    m().inc_ref(exmid);
 | 
			
		||||
    symm = function("@symm",1,booldom,bool_type());
 | 
			
		||||
    m().inc_ref(symm);
 | 
			
		||||
    epsilon = make_var("@eps",int_type());
 | 
			
		||||
    modpon = function("@mp",3,boolboolbooldom,bool_type());
 | 
			
		||||
    m().inc_ref(modpon);
 | 
			
		||||
    no_proof = make_var("@nop",bool_type());
 | 
			
		||||
    concat = function("@concat",2,boolbooldom,bool_type());
 | 
			
		||||
    m().inc_ref(concat);
 | 
			
		||||
    top_pos = make_var("@top_pos",bool_type());
 | 
			
		||||
    add_pos = function("@add_pos",2,intbooldom,bool_type());
 | 
			
		||||
    m().inc_ref(add_pos);
 | 
			
		||||
    rewrite_A = function("@rewrite_A",3,boolboolbooldom,bool_type());
 | 
			
		||||
    m().inc_ref(rewrite_A);
 | 
			
		||||
    rewrite_B = function("@rewrite_B",3,boolboolbooldom,bool_type());
 | 
			
		||||
    m().inc_ref(rewrite_B);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ~iz3proof_itp_impl(){
 | 
			
		||||
    m().dec_ref(contra);
 | 
			
		||||
    m().dec_ref(sum);
 | 
			
		||||
    m().dec_ref(rotate_sum);
 | 
			
		||||
    m().dec_ref(leq2eq);
 | 
			
		||||
    m().dec_ref(eq2leq);
 | 
			
		||||
    m().dec_ref(cong);
 | 
			
		||||
    m().dec_ref(exmid);
 | 
			
		||||
    m().dec_ref(symm);
 | 
			
		||||
    m().dec_ref(modpon);
 | 
			
		||||
    m().dec_ref(concat);
 | 
			
		||||
    m().dec_ref(add_pos);
 | 
			
		||||
    m().dec_ref(rewrite_A);
 | 
			
		||||
    m().dec_ref(rewrite_B);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
iz3proof_itp *iz3proof_itp::create(prover *p, const prover::range &r, bool w){
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -881,11 +881,11 @@ public:
 | 
			
		|||
    std::vector<Iproof::node>  my_prems;
 | 
			
		||||
    std::vector<ast>  my_coeffs;
 | 
			
		||||
    std::vector<Iproof::node>  my_prem_cons;
 | 
			
		||||
    for(unsigned i = 0; i < coeffs.size(); i++){
 | 
			
		||||
    for(unsigned i = pol ? 0 : 1; i < coeffs.size(); i+= 2){
 | 
			
		||||
      rational &c = coeffs[i];
 | 
			
		||||
      if(pol ? c.is_pos() : c.is_neg()){
 | 
			
		||||
      if(c.is_pos()){
 | 
			
		||||
	my_prems.push_back(prems[i]);
 | 
			
		||||
	my_coeffs.push_back(pol ? make_int(c) : make_int(-c));
 | 
			
		||||
	my_coeffs.push_back(make_int(c));
 | 
			
		||||
	my_prem_cons.push_back(conc(prem(proof,i)));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -187,6 +187,10 @@ namespace datalog {
 | 
			
		|||
        if (m_trail.get_num_scopes() == 0) {
 | 
			
		||||
            throw default_exception("there are no backtracking points to pop to");
 | 
			
		||||
        }
 | 
			
		||||
	if(m_engine.get()){
 | 
			
		||||
	  if(get_engine() != DUALITY_ENGINE)
 | 
			
		||||
	    throw default_exception("operation is not supported by engine");
 | 
			
		||||
	}
 | 
			
		||||
        m_trail.pop_scope(1); 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,6 +82,7 @@ dl_interface::dl_interface(datalog::context& dl_ctx) :
 | 
			
		|||
 | 
			
		||||
{
 | 
			
		||||
  _d = 0;
 | 
			
		||||
  dl_ctx.get_manager().toggle_proof_mode(PGM_FINE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -454,6 +454,44 @@ public:
 | 
			
		|||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   \brief fixedpoint-push command.
 | 
			
		||||
*/
 | 
			
		||||
class dl_push_cmd : public cmd {
 | 
			
		||||
    ref<dl_context> m_dl_ctx;
 | 
			
		||||
public:
 | 
			
		||||
    dl_push_cmd(dl_context * dl_ctx):
 | 
			
		||||
      cmd("fixedpoint-push"),
 | 
			
		||||
      m_dl_ctx(dl_ctx)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    virtual char const * get_usage() const { return ""; }
 | 
			
		||||
    virtual char const * get_descr(cmd_context & ctx) const { return "push the fixedpoint context"; }
 | 
			
		||||
    virtual unsigned get_arity() const { return 0; }
 | 
			
		||||
    virtual void execute(cmd_context & ctx) {
 | 
			
		||||
        m_dl_ctx->push();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   \brief fixedpoint-pop command.
 | 
			
		||||
*/
 | 
			
		||||
class dl_pop_cmd : public cmd {
 | 
			
		||||
    ref<dl_context> m_dl_ctx;
 | 
			
		||||
public:
 | 
			
		||||
    dl_pop_cmd(dl_context * dl_ctx):
 | 
			
		||||
      cmd("fixedpoint-pop"),
 | 
			
		||||
      m_dl_ctx(dl_ctx)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    virtual char const * get_usage() const { return ""; }
 | 
			
		||||
    virtual char const * get_descr(cmd_context & ctx) const { return "pop the fixedpoint context"; }
 | 
			
		||||
    virtual unsigned get_arity() const { return 0; }
 | 
			
		||||
    virtual void execute(cmd_context & ctx) {
 | 
			
		||||
        m_dl_ctx->pop();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void install_dl_cmds_aux(cmd_context& ctx, dl_collected_cmds* collected_cmds) {
 | 
			
		||||
    dl_context * dl_ctx = alloc(dl_context, ctx, collected_cmds);
 | 
			
		||||
| 
						 | 
				
			
			@ -463,7 +501,7 @@ static void install_dl_cmds_aux(cmd_context& ctx, dl_collected_cmds* collected_c
 | 
			
		|||
    ctx.insert(alloc(dl_declare_var_cmd, dl_ctx));
 | 
			
		||||
    // #ifndef _EXTERNAL_RELEASE
 | 
			
		||||
    // TODO: we need these!
 | 
			
		||||
#if 0
 | 
			
		||||
#if 1
 | 
			
		||||
    ctx.insert(alloc(dl_push_cmd, dl_ctx)); // not exposed to keep command-extensions simple.
 | 
			
		||||
    ctx.insert(alloc(dl_pop_cmd, dl_ctx));
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue