Z3_ast Z3_API Z3_model_extrapolate (Z3_context c, Z3_model m, Z3_ast fml) { Z3_TRY; LOG_Z3_model_extrapolate (c, m, fml); RESET_ERROR_CODE(); model_ref model (to_model_ref (m)); expr_ref_vector facts (mk_c(c)->m ()); facts.push_back (to_expr (fml)); flatten_and (facts); spacer::model_evaluator_util mev (mk_c(c)->m()); mev.set_model (*model); expr_ref_vector lits (mk_c(c)->m()); spacer::compute_implicant_literals (mev, facts, lits); expr_ref result (mk_c(c)->m ()); result = mk_and (lits); mk_c(c)->save_ast_trail (result.get ()); return of_expr (result.get ()); Z3_CATCH_RETURN(0); }
void cnft::gate_xor(literalt a, literalt b, literalt o) { // a xor b = o <==> (a' + b' + o') // (a + b + o' ) // (a' + b + o) // (a + b' + o) bvt lits(3); lits[0]=neg(a); lits[1]=neg(b); lits[2]=neg(o); lcnf(lits); lits[0]=pos(a); lits[1]=pos(b); lits[2]=neg(o); lcnf(lits); lits[0]=neg(a); lits[1]=pos(b); lits[2]=pos(o); lcnf(lits); lits[0]=pos(a); lits[1]=neg(b); lits[2]=pos(o); lcnf(lits); }
void tst_theory_pb() { fuzz_pb(); ast_manager m; smt_params params; params.m_model = true; reg_decl_plugins(m); expr_ref tmp(m); enable_trace("pb"); for (unsigned N = 4; N < 11; ++N) { for (unsigned i = 0; i < (1u << N); ++i) { smt::literal_vector lits(N, smt::false_literal); unsigned k = populate_literals(i, lits); std::cout << "k:" << k << " " << N << "\n"; std::cout.flush(); TRACE("pb", tout << "k " << k << ": "; for (unsigned j = 0; j < lits.size(); ++j) { tout << lits[j] << " "; } tout << "\n";); { smt::context ctx(m, params); ctx.push(); smt::literal l = smt::theory_pb::assert_ge(ctx, k+1, lits.size(), lits.c_ptr()); if (l != smt::false_literal) { ctx.assign(l, 0, false); TRACE("pb", tout << "assign: " << l << "\n"; ctx.display(tout);); VERIFY(l_false == ctx.check()); } ctx.pop(1); }
literalt cnft::land(const bvt &bv) { if(bv.size()==0) return const_literal(true); if(bv.size()==1) return bv[0]; if(bv.size()==2) return land(bv[0], bv[1]); forall_literals(it, bv) if(it->is_false()) return *it; if(is_all(bv, const_literal(true))) return const_literal(true); bvt new_bv; eliminate_duplicates(bv, new_bv); bvt lits(2); literalt literal=new_variable(); lits[1]=neg(literal); forall_literals(it, new_bv) { lits[0]=pos(*it); lcnf(lits); }
static void tst6() { params_ref ps; reslimit rlim; nlsat::solver s(rlim, ps); anum_manager & am = s.am(); nlsat::pmanager & pm = s.pm(); nlsat::assignment as(am); nlsat::explain& ex = s.get_explain(); nlsat::var x0, x1, x2, a, b, c, d; a = s.mk_var(false); b = s.mk_var(false); c = s.mk_var(false); d = s.mk_var(false); x0 = s.mk_var(false); x1 = s.mk_var(false); x2 = s.mk_var(false); polynomial_ref p1(pm), p2(pm), p3(pm), p4(pm), p5(pm); polynomial_ref _x0(pm), _x1(pm), _x2(pm); polynomial_ref _a(pm), _b(pm), _c(pm), _d(pm); _x0 = pm.mk_polynomial(x0); _x1 = pm.mk_polynomial(x1); _x2 = pm.mk_polynomial(x2); _a = pm.mk_polynomial(a); _b = pm.mk_polynomial(b); _c = pm.mk_polynomial(c); _d = pm.mk_polynomial(d); p1 = (_a*(_x0^2)) + _x2 + 2; p2 = (_b*_x1) - (2*_x2) - _x0 + 8; nlsat::scoped_literal_vector lits(s); lits.push_back(mk_gt(s, p1)); lits.push_back(mk_gt(s, p2)); lits.push_back(mk_gt(s, (_c*_x0) + _x2 + 1)); lits.push_back(mk_gt(s, (_d*_x0) - _x1 + 5*_x2)); scoped_anum zero(am), one(am), two(am); am.set(zero, 0); am.set(one, 1); am.set(two, 2); as.set(0, one); as.set(1, one); as.set(2, two); as.set(3, two); as.set(4, two); as.set(5, one); as.set(6, one); s.set_rvalues(as); project(s, ex, x0, 2, lits.c_ptr()); project(s, ex, x1, 3, lits.c_ptr()); project(s, ex, x2, 3, lits.c_ptr()); project(s, ex, x2, 2, lits.c_ptr()); project(s, ex, x2, 4, lits.c_ptr()); project(s, ex, x2, 3, lits.c_ptr()+1); }
static void tst7() { params_ref ps; reslimit rlim; nlsat::solver s(rlim, ps); anum_manager & am = s.am(); nlsat::pmanager & pm = s.pm(); nlsat::var x0, x1, x2, a, b, c, d; a = s.mk_var(false); b = s.mk_var(false); c = s.mk_var(false); d = s.mk_var(false); x0 = s.mk_var(false); x1 = s.mk_var(false); x2 = s.mk_var(false); polynomial_ref p1(pm), p2(pm), p3(pm), p4(pm), p5(pm); polynomial_ref _x0(pm), _x1(pm), _x2(pm); polynomial_ref _a(pm), _b(pm), _c(pm), _d(pm); _x0 = pm.mk_polynomial(x0); _x1 = pm.mk_polynomial(x1); _x2 = pm.mk_polynomial(x2); _a = pm.mk_polynomial(a); _b = pm.mk_polynomial(b); _c = pm.mk_polynomial(c); _d = pm.mk_polynomial(d); p1 = _x0 + _x1; p2 = _x2 - _x0; p3 = (-1*_x0) - _x1; nlsat::scoped_literal_vector lits(s); lits.push_back(mk_gt(s, p1)); lits.push_back(mk_gt(s, p2)); lits.push_back(mk_gt(s, p3)); nlsat::literal_vector litsv(lits.size(), lits.c_ptr()); lbool res = s.check(litsv); SASSERT(res == l_false); for (unsigned i = 0; i < litsv.size(); ++i) { s.display(std::cout, litsv[i]); std::cout << " "; } std::cout << "\n"; litsv.reset(); litsv.append(2, lits.c_ptr()); res = s.check(litsv); SASSERT(res == l_true); s.display(std::cout); s.am().display(std::cout, s.value(x0)); std::cout << "\n"; s.am().display(std::cout, s.value(x1)); std::cout << "\n"; s.am().display(std::cout, s.value(x2)); std::cout << "\n"; }
static void test2(char const *ex) { smt_params params; params.m_model = true; ast_manager m; reg_decl_plugins(m); arith_util a(m); expr_ref fml = parse_fml(m, ex); app_ref_vector vars(m); expr_ref_vector lits(m); vars.push_back(m.mk_const(symbol("x"), a.mk_real())); vars.push_back(m.mk_const(symbol("y"), a.mk_real())); vars.push_back(m.mk_const(symbol("z"), a.mk_real())); flatten_and(fml, lits); smt::context ctx(m, params); ctx.push(); ctx.assert_expr(fml); lbool result = ctx.check(); VERIFY(result == l_true); ref<model> md; ctx.get_model(md); ctx.pop(1); std::cout << mk_pp(fml, m) << "\n"; expr_ref pr1(m), pr2(m), fml2(m); expr_ref_vector bound(m); ptr_vector<sort> sorts; svector<symbol> names; for (unsigned i = 0; i < vars.size(); ++i) { bound.push_back(vars[i].get()); names.push_back(vars[i]->get_decl()->get_name()); sorts.push_back(m.get_sort(vars[i].get())); } expr_abstract(m, 0, bound.size(), bound.c_ptr(), fml, fml2); fml2 = m.mk_exists(bound.size(), sorts.c_ptr(), names.c_ptr(), fml2); qe::expr_quant_elim qe(m, params); for (unsigned i = 0; i < vars.size(); ++i) { VERIFY(qe::arith_project(*md, vars[i].get(), lits)); } pr1 = mk_and(lits); qe(m.mk_true(), fml2, pr2); std::cout << mk_pp(pr1, m) << "\n"; std::cout << mk_pp(pr2, m) << "\n"; expr_ref npr2(m); npr2 = m.mk_not(pr2); ctx.push(); ctx.assert_expr(pr1); ctx.assert_expr(npr2); VERIFY(l_false == ctx.check()); ctx.pop(1); }
Z3_literals Z3_API Z3_get_guessed_literals(Z3_context c) { Z3_TRY; LOG_Z3_get_guessed_literals(c); RESET_ERROR_CODE(); ast_manager& m = mk_c(c)->m(); expr_ref_vector lits(m); mk_c(c)->get_smt_kernel().get_guessed_literals(lits); labels* lbls = alloc(labels); for (unsigned i = 0; i < lits.size(); ++i) { lbls->push_back(labeled_literal(m,lits[i].get())); } RETURN_Z3(reinterpret_cast<Z3_literals>(lbls)); Z3_CATCH_RETURN(0); }
static void test(app* var, expr_ref& fml) { ast_manager& m = fml.get_manager(); smt_params params; params.m_model = true; symbol x_name(var->get_decl()->get_name()); sort* x_sort = m.get_sort(var); expr_ref pr(m); expr_ref_vector lits(m); flatten_and(fml, lits); model_ref md; { smt::context ctx(m, params); ctx.assert_expr(fml); lbool result = ctx.check(); if (result != l_true) return; ctx.get_model(md); } VERIFY(qe::arith_project(*md, var, lits)); pr = mk_and(lits); std::cout << "original: " << mk_pp(fml, m) << "\n"; std::cout << "projected: " << mk_pp(pr, m) << "\n"; // projection is consistent with model. VERIFY(md->is_true(pr)); // projection implies E x. fml { qe::expr_quant_elim qelim(m, params); expr_ref result(m), efml(m); expr* x = var; expr_abstract(m, 0, 1, &x, fml, efml); efml = m.mk_exists(1, &x_sort, &x_name, efml); qelim(m.mk_true(), efml, result); smt::context ctx(m, params); ctx.assert_expr(pr); ctx.assert_expr(m.mk_not(result)); std::cout << "exists: " << pr << " =>\n" << result << "\n"; VERIFY(l_false == ctx.check()); } std::cout << "\n"; }
Z3_literals Z3_API Z3_get_relevant_labels(Z3_context c) { Z3_TRY; LOG_Z3_get_relevant_labels(c); RESET_ERROR_CODE(); buffer<symbol> labl_syms; ast_manager& m = mk_c(c)->m(); expr_ref_vector lits(m); mk_c(c)->get_smt_kernel().get_relevant_labels(0, labl_syms); mk_c(c)->get_smt_kernel().get_relevant_labeled_literals(mk_c(c)->fparams().m_at_labels_cex, lits); labels* lbls = alloc(labels); SASSERT(labl_syms.size() == lits.size()); for (unsigned i = 0; i < lits.size(); ++i) { lbls->push_back(labeled_literal(m,lits[i].get(), labl_syms[i])); } RETURN_Z3(reinterpret_cast<Z3_literals>(lbls)); Z3_CATCH_RETURN(0); }
ArgArray<Literal> ValueSymmetryImp<IntView> ::symmetric(Literal l, const ViewArray<IntView>& x) const { (void) x; if (values.valid(l._value) && values.get(l._value)) { int n = 0; for (Iter::Values::BitSetOffset<Support::BitSetOffset<Space> > i(values) ; i() ; ++i) n++; ArgArray<Literal> lits(n); int j = 0; for (Iter::Values::BitSetOffset<Support::BitSetOffset<Space> > i(values) ; i() ; ++i) lits[j++] = Literal(l._variable, i.val()); return lits; } else { return ArgArray<Literal>(0); } }
static void tst8() { params_ref ps; reslimit rlim; nlsat::solver s(rlim, ps); anum_manager & am = s.am(); nlsat::pmanager & pm = s.pm(); nlsat::assignment as(am); nlsat::explain& ex = s.get_explain(); nlsat::var x0, x1, x2, a, b, c, d; a = s.mk_var(false); b = s.mk_var(false); c = s.mk_var(false); d = s.mk_var(false); x0 = s.mk_var(false); x1 = s.mk_var(false); x2 = s.mk_var(false); polynomial_ref p1(pm), p2(pm), p3(pm), p4(pm), p5(pm); polynomial_ref _x0(pm), _x1(pm), _x2(pm); polynomial_ref _a(pm), _b(pm), _c(pm), _d(pm); _x0 = pm.mk_polynomial(x0); _x1 = pm.mk_polynomial(x1); _x2 = pm.mk_polynomial(x2); _a = pm.mk_polynomial(a); _b = pm.mk_polynomial(b); _c = pm.mk_polynomial(c); _d = pm.mk_polynomial(d); scoped_anum zero(am), one(am), two(am), six(am); am.set(zero, 0); am.set(one, 1); am.set(two, 2); am.set(six, 6); as.set(0, two); // a as.set(1, one); // b as.set(2, six); // c as.set(3, zero); // d as.set(4, zero); // x0 as.set(5, zero); // x1 as.set(6, two); // x2 s.set_rvalues(as); nlsat::scoped_literal_vector lits(s); lits.push_back(mk_eq(s, (_a*_x2*_x2) - (_b*_x2) - _c)); project(s, ex, x2, 1, lits.c_ptr()); }
void Z3_API Z3_block_literals(Z3_context c, Z3_literals lbls) { Z3_TRY; LOG_Z3_block_literals(c, lbls); RESET_ERROR_CODE(); labels* _lbls = reinterpret_cast<labels*>(lbls); ast_manager& m = mk_c(c)->m(); expr_ref_vector lits(m); for (unsigned i = 0; i < _lbls->size(); ++i) { if ((*_lbls)[i].is_enabled()) { lits.push_back(m.mk_not((*_lbls)[i].get_literal())); } } expr_ref clause(m); clause = m.mk_or(lits.size(), lits.c_ptr()); mk_c(c)->save_ast_trail(clause.get()); mk_c(c)->assert_cnstr(clause.get()); Z3_CATCH; }
void cnft::gate_nor(literalt a, literalt b, literalt o) { // a Nor b = o <==> (a' + o')( b' + o')(a + b + o) bvt lits(2); lits[0]=neg(a); lits[1]=neg(o); lcnf(lits); lits[0]=neg(b); lits[1]=neg(o); lcnf(lits); lits.resize(3); lits[0]=pos(a); lits[1]=pos(b); lits[2]=pos(o); lcnf(lits); }
void cnft::gate_or(literalt a, literalt b, literalt o) { // a+b=c <==> (a' + c)( b' + c)(a + b + c') bvt lits(2); lits[0]=neg(a); lits[1]=pos(o); lcnf(lits); lits[0]=neg(b); lits[1]=pos(o); lcnf(lits); lits.resize(3); lits[0]=pos(a); lits[1]=pos(b); lits[2]=neg(o); lcnf(lits); }
void cnft::gate_and(literalt a, literalt b, literalt o) { // a*b=c <==> (a + o')( b + o')(a'+b'+o) bvt lits(2); lits[0]=pos(a); lits[1]=neg(o); lcnf(lits); lits[0]=pos(b); lits[1]=neg(o); lcnf(lits); lits.clear(); lits.reserve(3); lits.push_back(neg(a)); lits.push_back(neg(b)); lits.push_back(pos(o)); lcnf(lits); }
static void test(char const *ex) { smt_params params; params.m_model = true; ast_manager m; reg_decl_plugins(m); arith_util a(m); expr_ref fml = parse_fml(m, ex); app_ref_vector vars(m); expr_ref_vector lits(m); vars.push_back(m.mk_const(symbol("x"), a.mk_real())); flatten_and(fml, lits); smt::context ctx(m, params); ctx.assert_expr(fml); lbool result = ctx.check(); SASSERT(result == l_true); ref<model> md; ctx.get_model(md); expr_ref pr = qe::arith_project(*md, vars, lits); std::cout << mk_pp(fml, m) << "\n"; std::cout << mk_pp(pr, m) << "\n"; }
static void tst9() { params_ref ps; reslimit rlim; nlsat::solver s(rlim, ps); anum_manager & am = s.am(); nlsat::pmanager & pm = s.pm(); nlsat::assignment as(am); nlsat::explain& ex = s.get_explain(); int num_lo = 4; int num_hi = 5; svector<nlsat::var> los, his; for (int i = 0; i < num_lo; ++i) { los.push_back(s.mk_var(false)); scoped_anum num(am); am.set(num, - i - 1); as.set(i, num); } for (int i = 0; i < num_hi; ++i) { his.push_back(s.mk_var(false)); scoped_anum num(am); am.set(num, i + 1); as.set(num_lo + i, num); } nlsat::var _z = s.mk_var(false); nlsat::var _x = s.mk_var(false); polynomial_ref x(pm), z(pm); x = pm.mk_polynomial(_x); scoped_anum val(am); am.set(val, 0); as.set(num_lo + num_hi, val); as.set(num_lo + num_hi + 1, val); s.set_rvalues(as); nlsat::scoped_literal_vector lits(s); for (int i = 0; i < num_lo; ++i) { polynomial_ref y(pm); y = pm.mk_polynomial(los[i]); lits.push_back(mk_gt(s, x - y)); } for (int i = 0; i < num_hi; ++i) { polynomial_ref y(pm); y = pm.mk_polynomial(his[i]); lits.push_back(mk_gt(s, y - x)); } z = pm.mk_polynomial(_z); lits.push_back(mk_eq(s, x - z)); #define TEST_ON_OFF() \ std::cout << "Off "; \ ex.set_signed_project(false); \ project(s, ex, _x, lits.size()-1, lits.c_ptr()); \ std::cout << "On "; \ ex.set_signed_project(true); \ project(s, ex, _x, lits.size()-1, lits.c_ptr()); \ std::cout << "Off "; \ ex.set_signed_project(false); \ project(s, ex, _x, lits.size(), lits.c_ptr()); \ std::cout << "On "; \ ex.set_signed_project(true); \ project(s, ex, _x, lits.size(), lits.c_ptr()) \ TEST_ON_OFF(); lits.reset(); polynomial_ref u(pm); u = pm.mk_polynomial(his[1]); for (int i = 0; i < num_lo; ++i) { polynomial_ref y(pm); y = pm.mk_polynomial(los[i]); lits.push_back(mk_gt(s, u*x - y)); } for (int i = 0; i < num_hi; ++i) { polynomial_ref y(pm); y = pm.mk_polynomial(his[i]); lits.push_back(mk_gt(s, y - u*x)); } z = pm.mk_polynomial(_z); lits.push_back(mk_eq(s, u*x - z)); TEST_ON_OFF(); lits.reset(); u = pm.mk_polynomial(los[1]); for (int i = 0; i < num_lo; ++i) { polynomial_ref y(pm); y = pm.mk_polynomial(los[i]); lits.push_back(mk_gt(s, u*x - y)); } for (int i = 0; i < num_hi; ++i) { polynomial_ref y(pm); y = pm.mk_polynomial(his[i]); lits.push_back(mk_gt(s, y - u*x)); } z = pm.mk_polynomial(_z); lits.push_back(mk_eq(s, x - z)); TEST_ON_OFF(); }
static void test_project() { ast_manager m; reg_decl_plugins(m); qe::arith_project_plugin plugin(m); arith_util a(m); app_ref_vector vars(m); expr_ref_vector lits(m), ds(m); model mdl(m); app_ref x(m), y(m), z(m), u(m); x = m.mk_const(symbol("x"), a.mk_int()); y = m.mk_const(symbol("y"), a.mk_int()); z = m.mk_const(symbol("z"), a.mk_int()); u = m.mk_const(symbol("u"), a.mk_int()); func_decl_ref f(m); sort* int_sort = a.mk_int(); f = m.mk_func_decl(symbol("f"), 1, &int_sort, int_sort); // test non-projection mdl.register_decl(x->get_decl(), a.mk_int(0)); mdl.register_decl(y->get_decl(), a.mk_int(1)); mdl.register_decl(z->get_decl(), a.mk_int(2)); mdl.register_decl(u->get_decl(), a.mk_int(3)); func_interp* fi = alloc(func_interp, m, 1); expr_ref_vector nums(m); nums.push_back(a.mk_int(0)); nums.push_back(a.mk_int(1)); nums.push_back(a.mk_int(2)); fi->insert_new_entry(nums.c_ptr(), a.mk_int(1)); fi->insert_new_entry(nums.c_ptr()+1, a.mk_int(2)); fi->insert_new_entry(nums.c_ptr()+2, a.mk_int(3)); fi->set_else(a.mk_int(10)); mdl.register_decl(f, fi); vars.reset(); lits.reset(); vars.push_back(x); lits.push_back(x <= app_ref(m.mk_app(f, (expr*)x), m)); lits.push_back(x < y); plugin(mdl, vars, lits); std::cout << lits << "\n"; // test not-equals vars.reset(); lits.reset(); vars.push_back(x); lits.push_back(m.mk_not(m.mk_eq(x, y))); plugin(mdl, vars, lits); std::cout << lits << "\n"; // test negation of distinct using bound variables mdl.register_decl(x->get_decl(), a.mk_int(0)); mdl.register_decl(y->get_decl(), a.mk_int(1)); mdl.register_decl(z->get_decl(), a.mk_int(0)); mdl.register_decl(u->get_decl(), a.mk_int(6)); vars.reset(); lits.reset(); ds.reset(); vars.push_back(x); vars.push_back(y); ds.push_back(x); ds.push_back(y); ds.push_back(z + 2); ds.push_back(u); ds.push_back(z); lits.push_back(m.mk_not(m.mk_distinct(ds.size(), ds.c_ptr()))); plugin(mdl, vars, lits); std::cout << lits << "\n"; // test negation of distinct, not using bound variables mdl.register_decl(x->get_decl(), a.mk_int(0)); mdl.register_decl(y->get_decl(), a.mk_int(1)); mdl.register_decl(z->get_decl(), a.mk_int(0)); mdl.register_decl(u->get_decl(), a.mk_int(6)); vars.reset(); lits.reset(); ds.reset(); vars.push_back(x); vars.push_back(y); ds.push_back(x); ds.push_back(y); ds.push_back(z + 2); ds.push_back(u); ds.push_back(z + 10); ds.push_back(u + 4); lits.push_back(m.mk_not(m.mk_distinct(ds.size(), ds.c_ptr()))); plugin(mdl, vars, lits); std::cout << lits << "\n"; // test distinct mdl.register_decl(x->get_decl(), a.mk_int(0)); mdl.register_decl(y->get_decl(), a.mk_int(1)); mdl.register_decl(z->get_decl(), a.mk_int(0)); mdl.register_decl(u->get_decl(), a.mk_int(6)); vars.reset(); lits.reset(); ds.reset(); vars.push_back(x); vars.push_back(y); ds.push_back(x); ds.push_back(y); ds.push_back(z + 2); ds.push_back(u); lits.push_back(m.mk_distinct(ds.size(), ds.c_ptr())); plugin(mdl, vars, lits); std::cout << lits << "\n"; // equality over modulus mdl.register_decl(y->get_decl(), a.mk_int(4)); mdl.register_decl(z->get_decl(), a.mk_int(8)); lits.reset(); vars.reset(); vars.push_back(y); lits.push_back(m.mk_eq(a.mk_mod(y, a.mk_int(3)), a.mk_int(1))); lits.push_back(m.mk_eq(2*y, z)); plugin(mdl, vars, lits); std::cout << lits << "\n"; // inequality test mdl.register_decl(x->get_decl(), a.mk_int(0)); mdl.register_decl(y->get_decl(), a.mk_int(1)); mdl.register_decl(z->get_decl(), a.mk_int(0)); mdl.register_decl(u->get_decl(), a.mk_int(6)); vars.reset(); lits.reset(); vars.push_back(x); vars.push_back(y); lits.push_back(z <= (x + (2*y))); lits.push_back(2*x < u + 3); lits.push_back(2*y <= u); plugin(mdl, vars, lits); std::cout << lits << "\n"; // non-unit equalities mdl.register_decl(x->get_decl(), a.mk_int(1)); mdl.register_decl(z->get_decl(), a.mk_int(2)); mdl.register_decl(u->get_decl(), a.mk_int(3)); mdl.register_decl(y->get_decl(), a.mk_int(4)); lits.reset(); vars.reset(); vars.push_back(x); lits.push_back(m.mk_eq(2*x, z)); lits.push_back(m.mk_eq(3*x, u)); plugin(mdl, vars, lits); std::cout << lits << "\n"; }
void aig_prop_solvert::convert_node( unsigned n, const aigt::nodet &node, bool n_pos, bool n_neg, std::vector<unsigned> &p_usage_count, std::vector<unsigned> &n_usage_count) { if (p_usage_count[n] > 0 || n_usage_count[n] > 0) { literalt o=literalt(n, false); bvt body(2); body[0]=node.a; body[1]=node.b; #ifdef USE_AIG_COMPACT // Inline positive literals // This should remove the overhead introduced by land and lor for bvt for (bvt::size_type i = 0; i < body.size(); i++) { literalt l = body[i]; if (!l.sign() && // Used positively... aig.nodes[l.var_no()].is_and() && // ... is a gate ... p_usage_count[l.var_no()] == 1 && // ... only used here. n_usage_count[l.var_no()] == 0) { const aigt::nodet &rep = aig.nodes[l.var_no()]; body[i] = rep.a; body.push_back(rep.b); --i; // Repeat the process --p_usage_count[l.var_no()]; // Supress generation of inlined node } } // TODO : Could check the array for duplicates / complementary literals // but this should be found by the SAT preprocessor. // TODO : Likewise could find things that are constrained, esp the output // and backwards constant propagate. Again may not be worth it. // lxor and lselect et al. are difficult to express in AIGs. // Doing so introduces quite a bit of overhead. // This should recognise the AIGs they produce and // handle them in a more efficient way. // Recognise something of the form: // // neg(o) = lor(land(a,b), land(neg(a),c)) // o = land(lneg(land(a,b)), lneg(land(neg(a),c))) // // Note that lxor and lselect generate the negation of this // but will still be recognised because the negation is // recorded where it is used if(body.size() == 2 && body[0].sign() && body[1].sign()) { const aigt::nodet &left = aig.nodes[body[0].var_no()]; const aigt::nodet &right = aig.nodes[body[1].var_no()]; if(left.is_and() && right.is_and()) { if(left.a == neg(right.a)) { if (p_usage_count[body[0].var_no()] == 0 && n_usage_count[body[0].var_no()] == 1 && p_usage_count[body[1].var_no()] == 0 && n_usage_count[body[1].var_no()] == 1) { bvt lits(3); if (n_neg) { lits[0] = left.a; lits[1] = right.b; lits[2] = o; solver.lcnf(lits); lits[0] = neg(left.a); lits[1] = left.b; lits[2] = o; solver.lcnf(lits); } if (n_pos) { lits[0] = left.a; lits[1] = neg(right.b); lits[2] = neg(o); solver.lcnf(lits); lits[0] = neg(left.a); lits[1] = neg(left.b); lits[2] = neg(o); solver.lcnf(lits); } // Supress generation --n_usage_count[body[0].var_no()]; --n_usage_count[body[1].var_no()]; return; } } } } // Likewise, carry has an improved encoding which is generated // by the CNF encoding if (body.size() == 3 && body[0].sign() && body[1].sign() && body[2].sign()) { const aigt::nodet &left = aig.nodes[body[0].var_no()]; const aigt::nodet &mid = aig.nodes[body[1].var_no()]; const aigt::nodet &right = aig.nodes[body[2].var_no()]; if (left.is_and() && mid.is_and() && right.is_and()) { if (p_usage_count[body[0].var_no()] == 0 && n_usage_count[body[0].var_no()] == 1 && p_usage_count[body[1].var_no()] == 0 && n_usage_count[body[1].var_no()] == 1 && p_usage_count[body[2].var_no()] == 0 && n_usage_count[body[2].var_no()] == 1) { literalt a = left.a; literalt b = left.b; literalt c = mid.a; if (a == right.b && b == mid.b && c == right.a) { // A (negative) carry -- 1 if at most one input is 1 bvt lits(3); if (n_neg) { lits[0] = a; lits[1] = b; lits[2] = o; solver.lcnf(lits); lits[0] = a; lits[1] = c; lits[2] = o; solver.lcnf(lits); lits[0] = b; lits[1] = c; lits[2] = o; solver.lcnf(lits); } if (n_pos) { lits[0] = neg(a); lits[1] = neg(b); lits[2] = neg(o); solver.lcnf(lits); lits[0] = neg(a); lits[1] = neg(c); lits[2] = neg(o); solver.lcnf(lits); lits[0] = neg(b); lits[1] = neg(c); lits[2] = neg(o); solver.lcnf(lits); } // Supress generation --n_usage_count[body[0].var_no()]; --n_usage_count[body[1].var_no()]; --n_usage_count[body[2].var_no()]; return; } } } } // TODO : these special cases are fragile and could be improved. // They don't handle cases where the construction is partially constant // folded. Also the usage constraints are sufficient for improvement // but reductions may still be possible with looser restrictions. #endif if(n_pos) { bvt lits(2); lits[1]=neg(o); forall_literals(it, body) { lits[0]=pos(*it); solver.lcnf(lits); } }
int main(){ std::vector<SolvedCNF> chains; std::vector<unsigned int> chaindef(NUMVARS); for(unsigned int i = 0; i<NUMVARS; i++){ chaindef[i] = i; } do { std::vector<unsigned int> pattern(NUMVARS, 0); for(unsigned int i = 0; i<=NUMVARS; i++){ for(unsigned int j = 0; j<i; j++){ pattern[j] = 1; } do{ CNFFormula f(NUMVARS,2); std::vector<literal> lits(NUMVARS); for(unsigned int j = 0; j<NUMVARS; j++){ literal l; l.variable = chaindef[j]; l.value = pattern[j]; lits[j] = l; } for(unsigned int j = 0; j<NUMVARS; j++){ CNFClause c; c.add_literal(lits[j]); c.add_literal(lits[(j+1)%NUMVARS]); f.add_clause(c); } SolvedCNF solf(f); chains.push_back(solf); } while(std::prev_permutation(pattern.begin(), pattern.end())); } } while(std::next_permutation(chaindef.begin(), chaindef.end())); std::vector<Assignment> all_assig; for(unsigned int i = 0; i<=NUMVARS; i++){ std::vector<short> assigvec(NUMVARS, 0); for(unsigned int j = 0; j<i; j++){ assigvec[j] = 1; } do{ all_assig.push_back(assigvec); } while(std::prev_permutation(assigvec.begin(), assigvec.end())); } for(unsigned int i = 0; i<=all_assig.size(); i++){ std::cout << "i = " << i << std::endl; std::vector<short> covercandidatechoice(all_assig.size(), 0); for(unsigned int j = 0; j<i; j++){ covercandidatechoice[j] = 1; } do{ std::vector<Assignment> covercandidate; for(unsigned int j = 0; j<all_assig.size(); j++){ if(covercandidatechoice[j] == 1){ covercandidate.push_back(all_assig[j]); } } bool validcover = true; for(auto chain : chains){ std::vector<Assignment> chainsat = chain.get_satisfying_assignments(); bool covered = false; for(auto assig : covercandidate){ if(std::find(chainsat.begin(), chainsat.end(), assig) != chainsat.end()){ covered = true; break; } } if(covered == false){ validcover = false; break; } } if(validcover){ for(auto assig : covercandidate){ std::cout << assig; } std::cout << std::endl; } } while(std::prev_permutation(covercandidatechoice.begin(), covercandidatechoice.end())); } }