mirror of
https://github.com/Z3Prover/z3
synced 2025-04-12 12:08:18 +00:00
enable wcnf output for weighted maxsat problems
This commit is contained in:
parent
b02cba6106
commit
13f05ae9dc
|
@ -20,14 +20,21 @@ Revision History:
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
#include "display_dimacs.h"
|
#include "display_dimacs.h"
|
||||||
|
|
||||||
std::ostream& display_dimacs(std::ostream& out, expr_ref_vector const& fmls, bool include_names) {
|
struct dimacs_pp {
|
||||||
ast_manager& m = fmls.m();
|
ast_manager& m;
|
||||||
unsigned_vector expr2var;
|
unsigned_vector expr2var;
|
||||||
ptr_vector<expr> exprs;
|
ptr_vector<expr> exprs;
|
||||||
unsigned num_vars = 0;
|
unsigned num_vars { 0 };
|
||||||
unsigned num_cls = fmls.size();
|
|
||||||
bool is_from_dimacs = true;
|
dimacs_pp(ast_manager& m): m(m) {}
|
||||||
for (expr * f : fmls) {
|
|
||||||
|
void reset() {
|
||||||
|
num_vars = 0;
|
||||||
|
expr2var.reset();
|
||||||
|
exprs.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool init_from_dimacs(expr* f) {
|
||||||
unsigned num_lits;
|
unsigned num_lits;
|
||||||
expr * const * lits;
|
expr * const * lits;
|
||||||
if (m.is_or(f)) {
|
if (m.is_or(f)) {
|
||||||
|
@ -42,10 +49,8 @@ std::ostream& display_dimacs(std::ostream& out, expr_ref_vector const& fmls, boo
|
||||||
expr * l = lits[j];
|
expr * l = lits[j];
|
||||||
if (m.is_not(l))
|
if (m.is_not(l))
|
||||||
l = to_app(l)->get_arg(0);
|
l = to_app(l)->get_arg(0);
|
||||||
if (!is_uninterp_const(l)) {
|
if (!is_uninterp_const(l))
|
||||||
is_from_dimacs = false;
|
return false;
|
||||||
break;
|
|
||||||
}
|
|
||||||
symbol const& s = to_app(l)->get_decl()->get_name();
|
symbol const& s = to_app(l)->get_decl()->get_name();
|
||||||
if (s.is_numerical() && s.get_num() > 0) {
|
if (s.is_numerical() && s.get_num() > 0) {
|
||||||
if (expr2var.get(l->get_id(), UINT_MAX) == UINT_MAX) {
|
if (expr2var.get(l->get_id(), UINT_MAX) == UINT_MAX) {
|
||||||
|
@ -55,43 +60,35 @@ std::ostream& display_dimacs(std::ostream& out, expr_ref_vector const& fmls, boo
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
is_from_dimacs = false;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (!is_from_dimacs) {
|
return true;
|
||||||
num_vars = 0;
|
}
|
||||||
expr2var.reset();
|
|
||||||
exprs.reset();
|
void init_formula(expr* f) {
|
||||||
break;
|
unsigned num_lits;
|
||||||
|
expr * const * lits;
|
||||||
|
if (m.is_or(f)) {
|
||||||
|
num_lits = to_app(f)->get_num_args();
|
||||||
|
lits = to_app(f)->get_args();
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
|
num_lits = 1;
|
||||||
if (!is_from_dimacs) {
|
lits = &f;
|
||||||
for (expr * f : fmls) {
|
}
|
||||||
unsigned num_lits;
|
for (unsigned j = 0; j < num_lits; j++) {
|
||||||
expr * const * lits;
|
expr * l = lits[j];
|
||||||
if (m.is_or(f)) {
|
if (m.is_not(l))
|
||||||
num_lits = to_app(f)->get_num_args();
|
l = to_app(l)->get_arg(0);
|
||||||
lits = to_app(f)->get_args();
|
if (expr2var.get(l->get_id(), UINT_MAX) == UINT_MAX) {
|
||||||
}
|
num_vars++;
|
||||||
else {
|
expr2var.setx(l->get_id(), num_vars, UINT_MAX);
|
||||||
num_lits = 1;
|
exprs.setx(l->get_id(), l, nullptr);
|
||||||
lits = &f;
|
|
||||||
}
|
|
||||||
for (unsigned j = 0; j < num_lits; j++) {
|
|
||||||
expr * l = lits[j];
|
|
||||||
if (m.is_not(l))
|
|
||||||
l = to_app(l)->get_arg(0);
|
|
||||||
if (expr2var.get(l->get_id(), UINT_MAX) == UINT_MAX) {
|
|
||||||
num_vars++;
|
|
||||||
expr2var.setx(l->get_id(), num_vars, UINT_MAX);
|
|
||||||
exprs.setx(l->get_id(), l, nullptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out << "p cnf " << num_vars << " " << num_cls << "\n";
|
|
||||||
for (expr* f : fmls) {
|
void pp_formula(std::ostream& out, expr* f) {
|
||||||
unsigned num_lits;
|
unsigned num_lits;
|
||||||
expr * const * lits;
|
expr * const * lits;
|
||||||
if (m.is_or(f)) {
|
if (m.is_or(f)) {
|
||||||
|
@ -113,18 +110,61 @@ std::ostream& display_dimacs(std::ostream& out, expr_ref_vector const& fmls, boo
|
||||||
}
|
}
|
||||||
out << "0\n";
|
out << "0\n";
|
||||||
}
|
}
|
||||||
if (include_names && !is_from_dimacs) {
|
|
||||||
for (expr* e : exprs) {
|
void pp_defs(std::ostream& out) {
|
||||||
|
for (expr* e : exprs)
|
||||||
if (e && is_app(e)) {
|
if (e && is_app(e)) {
|
||||||
symbol const& n = to_app(e)->get_decl()->get_name();
|
symbol const& n = to_app(e)->get_decl()->get_name();
|
||||||
out << "c " << expr2var[e->get_id()] << " " << n << "\n";
|
out << "c " << expr2var[e->get_id()] << " " << n << "\n";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& display_dimacs(std::ostream& out, expr_ref_vector const& fmls, bool include_names) {
|
||||||
|
ast_manager& m = fmls.m();
|
||||||
|
dimacs_pp pp(m);
|
||||||
|
unsigned num_cls = fmls.size();
|
||||||
|
bool is_from_dimacs = true;
|
||||||
|
for (expr * f : fmls) {
|
||||||
|
is_from_dimacs = pp.init_from_dimacs(f);
|
||||||
|
if (!is_from_dimacs)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_from_dimacs) {
|
||||||
|
pp.reset();
|
||||||
|
for (expr * f : fmls) {
|
||||||
|
pp.init_formula(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
out << "p cnf " << pp.num_vars << " " << num_cls << "\n";
|
||||||
|
for (expr* f : fmls)
|
||||||
|
pp.pp_formula(out, f);
|
||||||
|
if (include_names && !is_from_dimacs)
|
||||||
|
pp.pp_defs(out);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& display_wcnf(std::ostream& out, expr_ref_vector const& fmls, vector<std::pair<expr*,unsigned>> const& soft, bool include_names) {
|
std::ostream& display_wcnf(std::ostream& out, expr_ref_vector const& fmls, svector<std::pair<expr*,unsigned>> const& soft) {
|
||||||
NOT_IMPLEMENTED_YET();
|
ast_manager& m = fmls.m();
|
||||||
|
dimacs_pp pp(m);
|
||||||
|
for (expr* f : fmls)
|
||||||
|
pp.init_formula(f);
|
||||||
|
for (auto s : soft)
|
||||||
|
pp.init_formula(s.first);
|
||||||
|
out << "p wcnf " << pp.num_vars << " " << fmls.size() + soft.size() << "\n";
|
||||||
|
unsigned sum_soft = 1;
|
||||||
|
for (auto s : soft)
|
||||||
|
sum_soft += s.second;
|
||||||
|
for (expr* f : fmls) {
|
||||||
|
out << sum_soft << " ";
|
||||||
|
pp.pp_formula(out, f);
|
||||||
|
}
|
||||||
|
for (auto s : soft) {
|
||||||
|
out << s.second << " ";
|
||||||
|
pp.pp_formula(out, s.first);
|
||||||
|
}
|
||||||
|
pp.pp_defs(out);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,5 +22,5 @@ Revision History:
|
||||||
|
|
||||||
std::ostream& display_dimacs(std::ostream& out, expr_ref_vector const& fmls, bool include_names);
|
std::ostream& display_dimacs(std::ostream& out, expr_ref_vector const& fmls, bool include_names);
|
||||||
|
|
||||||
std::ostream& display_wcnf(std::ostream& out, expr_ref_vector const& fmls, vector<std::pair<expr*,unsigned>> const& soft, bool include_names);
|
std::ostream& display_wcnf(std::ostream& out, expr_ref_vector const& fmls, svector<std::pair<expr*,unsigned>> const& soft);
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ Notes:
|
||||||
#include "ast/pb_decl_plugin.h"
|
#include "ast/pb_decl_plugin.h"
|
||||||
#include "ast/ast_smt_pp.h"
|
#include "ast/ast_smt_pp.h"
|
||||||
#include "ast/ast_pp_util.h"
|
#include "ast/ast_pp_util.h"
|
||||||
|
#include "ast/display_dimacs.h"
|
||||||
#include "model/model_smt2_pp.h"
|
#include "model/model_smt2_pp.h"
|
||||||
#include "tactic/goal.h"
|
#include "tactic/goal.h"
|
||||||
#include "tactic/tactic.h"
|
#include "tactic/tactic.h"
|
||||||
|
@ -1540,9 +1541,12 @@ namespace opt {
|
||||||
m_enable_sls = _p.enable_sls();
|
m_enable_sls = _p.enable_sls();
|
||||||
m_maxsat_engine = _p.maxsat_engine();
|
m_maxsat_engine = _p.maxsat_engine();
|
||||||
m_pp_neat = _p.pp_neat();
|
m_pp_neat = _p.pp_neat();
|
||||||
|
m_pp_wcnf = _p.pp_wcnf();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string context::to_string() const {
|
std::string context::to_string() {
|
||||||
|
if (m_pp_wcnf)
|
||||||
|
return to_wcnf();
|
||||||
return to_string(false, m_scoped_state.m_hard, m_scoped_state.m_objectives);
|
return to_string(false, m_scoped_state.m_hard, m_scoped_state.m_objectives);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1557,6 +1561,9 @@ namespace opt {
|
||||||
auto const& objectives = m_objectives;
|
auto const& objectives = m_objectives;
|
||||||
if (objectives.size() > 1)
|
if (objectives.size() > 1)
|
||||||
throw default_exception("only single objective weighted MaxSAT wcnf output is supported");
|
throw default_exception("only single objective weighted MaxSAT wcnf output is supported");
|
||||||
|
ptr_vector<expr> soft_f;
|
||||||
|
vector<rational> soft_w;
|
||||||
|
svector<std::pair<expr*, unsigned>> soft;
|
||||||
if (objectives.size() == 1) {
|
if (objectives.size() == 1) {
|
||||||
auto const& obj = objectives[0];
|
auto const& obj = objectives[0];
|
||||||
if (obj.m_type != O_MAXSMT)
|
if (obj.m_type != O_MAXSMT)
|
||||||
|
@ -1565,10 +1572,15 @@ namespace opt {
|
||||||
rational w = obj.m_weights[j];
|
rational w = obj.m_weights[j];
|
||||||
if (!w.is_unsigned())
|
if (!w.is_unsigned())
|
||||||
throw default_exception("only single objective weighted MaxSAT wcnf output is supported");
|
throw default_exception("only single objective weighted MaxSAT wcnf output is supported");
|
||||||
|
soft_f.push_back(obj.m_terms[j]);
|
||||||
|
soft_w.push_back(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NOT_IMPLEMENTED_YET();
|
std::ostringstream strm;
|
||||||
return std::string("");
|
m_sat_solver = mk_inc_sat_solver(m, m_params);
|
||||||
|
m_sat_solver->assert_expr(m_hard_constraints);
|
||||||
|
inc_sat_display(strm, *m_sat_solver.get(), soft_f.size(), soft_f.c_ptr(), soft_w.c_ptr());
|
||||||
|
return strm.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string context::to_string(bool is_internal, expr_ref_vector const& hard, vector<objective> const& objectives) const {
|
std::string context::to_string(bool is_internal, expr_ref_vector const& hard, vector<objective> const& objectives) const {
|
||||||
|
|
|
@ -179,10 +179,11 @@ namespace opt {
|
||||||
func_decl_ref_vector m_objective_refs;
|
func_decl_ref_vector m_objective_refs;
|
||||||
expr_ref_vector m_core;
|
expr_ref_vector m_core;
|
||||||
tactic_ref m_simplify;
|
tactic_ref m_simplify;
|
||||||
bool m_enable_sat;
|
bool m_enable_sat { true } ;
|
||||||
bool m_enable_sls;
|
bool m_enable_sls { false };
|
||||||
bool m_is_clausal;
|
bool m_is_clausal { false };
|
||||||
bool m_pp_neat;
|
bool m_pp_neat { true };
|
||||||
|
bool m_pp_wcnf { false };
|
||||||
symbol m_maxsat_engine;
|
symbol m_maxsat_engine;
|
||||||
symbol m_logic;
|
symbol m_logic;
|
||||||
svector<symbol> m_labels;
|
svector<symbol> m_labels;
|
||||||
|
@ -232,7 +233,7 @@ namespace opt {
|
||||||
void get_lower(unsigned idx, expr_ref_vector& es) { to_exprs(get_lower_as_num(idx), es); }
|
void get_lower(unsigned idx, expr_ref_vector& es) { to_exprs(get_lower_as_num(idx), es); }
|
||||||
void get_upper(unsigned idx, expr_ref_vector& es) { to_exprs(get_upper_as_num(idx), es); }
|
void get_upper(unsigned idx, expr_ref_vector& es) { to_exprs(get_upper_as_num(idx), es); }
|
||||||
|
|
||||||
std::string to_string() const;
|
std::string to_string();
|
||||||
|
|
||||||
|
|
||||||
unsigned num_objectives() override { return m_scoped_state.m_objectives.size(); }
|
unsigned num_objectives() override { return m_scoped_state.m_objectives.size(); }
|
||||||
|
|
|
@ -16,6 +16,7 @@ def_module_params('opt',
|
||||||
('elim_01', BOOL, True, 'eliminate 01 variables'),
|
('elim_01', BOOL, True, 'eliminate 01 variables'),
|
||||||
('pp.neat', BOOL, True, 'use neat (as opposed to less readable, but faster) pretty printer when displaying context'),
|
('pp.neat', BOOL, True, 'use neat (as opposed to less readable, but faster) pretty printer when displaying context'),
|
||||||
('pb.compile_equality', BOOL, False, 'compile arithmetical equalities into pseudo-Boolean equality (instead of two inequalites)'),
|
('pb.compile_equality', BOOL, False, 'compile arithmetical equalities into pseudo-Boolean equality (instead of two inequalites)'),
|
||||||
|
('pp.wcnf', BOOL, False, 'print maxsat benchmark into wcnf format'),
|
||||||
('maxlex.enable', BOOL, True, 'enable maxlex heuristic for lexicographic MaxSAT problems'),
|
('maxlex.enable', BOOL, True, 'enable maxlex heuristic for lexicographic MaxSAT problems'),
|
||||||
('maxres.hill_climb', BOOL, True, 'give preference for large weight cores'),
|
('maxres.hill_climb', BOOL, True, 'give preference for large weight cores'),
|
||||||
('maxres.add_upper_bound_block', BOOL, False, 'restict upper bound with constraint'),
|
('maxres.add_upper_bound_block', BOOL, False, 'restict upper bound with constraint'),
|
||||||
|
|
|
@ -4002,17 +4002,18 @@ namespace sat {
|
||||||
|
|
||||||
void solver::display_wcnf(std::ostream & out, unsigned sz, literal const* lits, unsigned const* weights) const {
|
void solver::display_wcnf(std::ostream & out, unsigned sz, literal const* lits, unsigned const* weights) const {
|
||||||
unsigned max_weight = 0;
|
unsigned max_weight = 0;
|
||||||
for (unsigned i = 0; i < sz; ++i) {
|
for (unsigned i = 0; i < sz; ++i)
|
||||||
max_weight = std::max(max_weight, weights[i]);
|
max_weight += weights[i];
|
||||||
}
|
|
||||||
++max_weight;
|
++max_weight;
|
||||||
|
|
||||||
|
if (m_ext)
|
||||||
|
throw default_exception("wcnf is only supported for pure CNF problems");
|
||||||
|
|
||||||
out << "p wcnf " << num_vars() << " " << num_clauses() + sz << " " << max_weight << "\n";
|
out << "p wcnf " << num_vars() << " " << num_clauses() + sz << " " << max_weight << "\n";
|
||||||
out << "c soft " << sz << "\n";
|
out << "c soft " << sz << "\n";
|
||||||
|
|
||||||
for (literal lit : m_trail) {
|
for (literal lit : m_trail)
|
||||||
out << max_weight << " " << dimacs_lit(lit) << " 0\n";
|
out << max_weight << " " << dimacs_lit(lit) << " 0\n";
|
||||||
}
|
|
||||||
unsigned l_idx = 0;
|
unsigned l_idx = 0;
|
||||||
for (watch_list const& wlist : m_watches) {
|
for (watch_list const& wlist : m_watches) {
|
||||||
literal l = ~to_literal(l_idx);
|
literal l = ~to_literal(l_idx);
|
||||||
|
|
Loading…
Reference in a new issue