mirror of
https://github.com/Z3Prover/z3
synced 2025-04-10 03:07:07 +00:00
adding handlers for dimacs for solver_from_file, and opb, wncf for opt_from_file, #1361
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
2f6283e1ed
commit
bdbaf68f8b
|
@ -16,6 +16,9 @@ Revision History:
|
|||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include "util/cancel_eh.h"
|
||||
#include "util/scoped_timer.h"
|
||||
#include "util/file_path.h"
|
||||
#include "api/z3.h"
|
||||
#include "api/api_log_macros.h"
|
||||
#include "api/api_stats.h"
|
||||
|
@ -24,11 +27,11 @@ Revision History:
|
|||
#include "api/api_model.h"
|
||||
#include "opt/opt_context.h"
|
||||
#include "opt/opt_cmds.h"
|
||||
#include "util/cancel_eh.h"
|
||||
#include "util/scoped_timer.h"
|
||||
#include "opt/opt_parse.h"
|
||||
#include "parsers/smt2/smt2parser.h"
|
||||
#include "api/api_ast_vector.h"
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
struct Z3_optimize_ref : public api::object {
|
||||
|
@ -286,8 +289,19 @@ extern "C" {
|
|||
static void Z3_optimize_from_stream(
|
||||
Z3_context c,
|
||||
Z3_optimize opt,
|
||||
std::istream& s) {
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
std::istream& s,
|
||||
char const* ext) {
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
if (ext && std::string("opb") == ext) {
|
||||
unsigned_vector h;
|
||||
parse_opb(*to_optimize_ptr(opt), s, h);
|
||||
return;
|
||||
}
|
||||
if (ext && std::string("wcnf") == ext) {
|
||||
unsigned_vector h;
|
||||
parse_wcnf(*to_optimize_ptr(opt), s, h);
|
||||
return;
|
||||
}
|
||||
scoped_ptr<cmd_context> ctx = alloc(cmd_context, false, &m);
|
||||
install_opt_cmds(*ctx.get(), to_optimize_ptr(opt));
|
||||
ctx->set_ignore_check(true);
|
||||
|
@ -311,7 +325,7 @@ extern "C" {
|
|||
//LOG_Z3_optimize_from_string(c, d, s);
|
||||
std::string str(s);
|
||||
std::istringstream is(str);
|
||||
Z3_optimize_from_stream(c, d, is);
|
||||
Z3_optimize_from_stream(c, d, is, nullptr);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
|
@ -327,7 +341,7 @@ extern "C" {
|
|||
strm << "Could not open file " << s;
|
||||
throw default_exception(strm.str());
|
||||
}
|
||||
Z3_optimize_from_stream(c, d, is);
|
||||
Z3_optimize_from_stream(c, d, is, get_extension(s));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,12 +29,16 @@ Revision History:
|
|||
#include "util/scoped_ctrl_c.h"
|
||||
#include "util/cancel_eh.h"
|
||||
#include "util/scoped_timer.h"
|
||||
#include "util/file_path.h"
|
||||
#include "tactic/portfolio/smt_strategic_solver.h"
|
||||
#include "smt/smt_solver.h"
|
||||
#include "smt/smt_implied_equalities.h"
|
||||
#include "solver/smt_logics.h"
|
||||
#include "cmd_context/cmd_context.h"
|
||||
#include "parsers/smt2/smt2parser.h"
|
||||
#include "sat/dimacs.h"
|
||||
#include "sat/sat_solver.h"
|
||||
#include "sat/tactic/goal2sat.h"
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
@ -127,13 +131,30 @@ extern "C" {
|
|||
void Z3_API Z3_solver_from_file(Z3_context c, Z3_solver s, Z3_string file_name) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_from_file(c, s, file_name);
|
||||
scoped_ptr<cmd_context> ctx = alloc(cmd_context, false, &(mk_c(c)->m()));
|
||||
ctx->set_ignore_check(true);
|
||||
char const* ext = get_extension(file_name);
|
||||
std::ifstream is(file_name);
|
||||
if (!is) {
|
||||
SET_ERROR_CODE(Z3_FILE_ACCESS_ERROR);
|
||||
return;
|
||||
}
|
||||
if (ext && std::string("dimacs") == ext) {
|
||||
ast_manager& m = to_solver_ref(s)->get_manager();
|
||||
sat::solver solver(to_solver_ref(s)->get_params(), m.limit());
|
||||
parse_dimacs(is, solver);
|
||||
sat2goal s2g;
|
||||
model_converter_ref mc;
|
||||
atom2bool_var a2b(m);
|
||||
goal g(m);
|
||||
s2g(solver, a2b, to_solver_ref(s)->get_params(), g, mc);
|
||||
for (unsigned i = 0; i < g.size(); ++i) {
|
||||
to_solver_ref(s)->assert_expr(g.form(i));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
scoped_ptr<cmd_context> ctx = alloc(cmd_context, false, &(mk_c(c)->m()));
|
||||
ctx->set_ignore_check(true);
|
||||
|
||||
if (!parse_smt2_commands(*ctx.get(), is)) {
|
||||
ctx = nullptr;
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
|
|
|
@ -6,6 +6,7 @@ z3_add_component(opt
|
|||
opt_cmds.cpp
|
||||
opt_context.cpp
|
||||
opt_pareto.cpp
|
||||
opt_parse.cpp
|
||||
optsmt.cpp
|
||||
opt_solver.cpp
|
||||
pb_sls.cpp
|
||||
|
|
317
src/opt/opt_parse.cpp
Normal file
317
src/opt/opt_parse.cpp
Normal file
|
@ -0,0 +1,317 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
opt_parse.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Parse utilities for optimization.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2017-11-19
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "opt/opt_context.h"
|
||||
#include "opt/opt_parse.h"
|
||||
|
||||
|
||||
class opt_stream_buffer {
|
||||
std::istream & m_stream;
|
||||
int m_val;
|
||||
unsigned m_line;
|
||||
public:
|
||||
opt_stream_buffer(std::istream & s):
|
||||
m_stream(s),
|
||||
m_line(0) {
|
||||
m_val = m_stream.get();
|
||||
}
|
||||
int operator *() const { return m_val;}
|
||||
void operator ++() { m_val = m_stream.get(); }
|
||||
int ch() const { return m_val; }
|
||||
void next() { m_val = m_stream.get(); }
|
||||
bool eof() const { return ch() == EOF; }
|
||||
unsigned line() const { return m_line; }
|
||||
void skip_whitespace();
|
||||
void skip_space();
|
||||
void skip_line();
|
||||
bool parse_token(char const* token);
|
||||
int parse_int();
|
||||
unsigned parse_unsigned();
|
||||
};
|
||||
|
||||
|
||||
void opt_stream_buffer::skip_whitespace() {
|
||||
while ((ch() >= 9 && ch() <= 13) || ch() == 32) {
|
||||
if (ch() == 10) ++m_line;
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
void opt_stream_buffer::skip_space() {
|
||||
while (ch() != 10 && ((ch() >= 9 && ch() <= 13) || ch() == 32)) {
|
||||
next();
|
||||
}
|
||||
}
|
||||
void opt_stream_buffer::skip_line() {
|
||||
while(true) {
|
||||
if (eof()) {
|
||||
return;
|
||||
}
|
||||
if (ch() == '\n') {
|
||||
++m_line;
|
||||
next();
|
||||
return;
|
||||
}
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
bool opt_stream_buffer::parse_token(char const* token) {
|
||||
skip_whitespace();
|
||||
char const* t = token;
|
||||
while (ch() == *t) {
|
||||
next();
|
||||
++t;
|
||||
}
|
||||
return 0 == *t;
|
||||
}
|
||||
|
||||
unsigned opt_stream_buffer::parse_unsigned() {
|
||||
skip_space();
|
||||
if (ch() == '\n') {
|
||||
return UINT_MAX;
|
||||
}
|
||||
unsigned val = 0;
|
||||
while (ch() >= '0' && ch() <= '9') {
|
||||
val = val*10 + (ch() - '0');
|
||||
next();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
int opt_stream_buffer::parse_int() {
|
||||
int val = 0;
|
||||
bool neg = false;
|
||||
skip_whitespace();
|
||||
|
||||
if (ch() == '-') {
|
||||
neg = true;
|
||||
next();
|
||||
}
|
||||
else if (ch() == '+') {
|
||||
next();
|
||||
}
|
||||
if (ch() < '0' || ch() > '9') {
|
||||
std::cerr << "(error line " << line() << " \"unexpected char: " << ((char)ch()) << "\" )\n";
|
||||
exit(3);
|
||||
}
|
||||
while (ch() >= '0' && ch() <= '9') {
|
||||
val = val*10 + (ch() - '0');
|
||||
next();
|
||||
}
|
||||
return neg ? -val : val;
|
||||
}
|
||||
|
||||
|
||||
class wcnf {
|
||||
opt::context& opt;
|
||||
ast_manager& m;
|
||||
opt_stream_buffer& in;
|
||||
unsigned_vector& m_handles;
|
||||
|
||||
app_ref read_clause(unsigned& weight) {
|
||||
int parsed_lit;
|
||||
int var;
|
||||
weight = in.parse_unsigned();
|
||||
app_ref result(m), p(m);
|
||||
expr_ref_vector ors(m);
|
||||
while (true) {
|
||||
parsed_lit = in.parse_int();
|
||||
if (parsed_lit == 0)
|
||||
break;
|
||||
var = abs(parsed_lit);
|
||||
p = m.mk_const(symbol(var), m.mk_bool_sort());
|
||||
if (parsed_lit < 0) p = m.mk_not(p);
|
||||
ors.push_back(p);
|
||||
}
|
||||
result = to_app(mk_or(m, ors.size(), ors.c_ptr()));
|
||||
return result;
|
||||
}
|
||||
|
||||
void parse_spec(unsigned& num_vars, unsigned& num_clauses, unsigned& max_weight) {
|
||||
in.parse_token("wcnf");
|
||||
num_vars = in.parse_unsigned();
|
||||
num_clauses = in.parse_unsigned();
|
||||
max_weight = in.parse_unsigned();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
wcnf(opt::context& opt, opt_stream_buffer& in, unsigned_vector& h): opt(opt), m(opt.get_manager()), in(in), m_handles(h) {
|
||||
opt.set_clausal(true);
|
||||
}
|
||||
|
||||
void parse() {
|
||||
unsigned num_vars = 0, num_clauses = 0, max_weight = 0;
|
||||
while (true) {
|
||||
in.skip_whitespace();
|
||||
if (in.eof()) {
|
||||
break;
|
||||
}
|
||||
else if (*in == 'c') {
|
||||
in.skip_line();
|
||||
}
|
||||
else if (*in == 'p') {
|
||||
++in;
|
||||
parse_spec(num_vars, num_clauses, max_weight);
|
||||
}
|
||||
else {
|
||||
unsigned weight = 0;
|
||||
app_ref cls = read_clause(weight);
|
||||
if (weight >= max_weight) {
|
||||
opt.add_hard_constraint(cls);
|
||||
}
|
||||
else {
|
||||
unsigned id = opt.add_soft_constraint(cls, rational(weight), symbol::null);
|
||||
if (m_handles.empty()) {
|
||||
m_handles.push_back(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class opb {
|
||||
opt::context& opt;
|
||||
ast_manager& m;
|
||||
opt_stream_buffer& in;
|
||||
unsigned_vector& m_handles;
|
||||
arith_util arith;
|
||||
|
||||
app_ref parse_id() {
|
||||
bool negated = in.parse_token("~");
|
||||
if (!in.parse_token("x")) {
|
||||
std::cerr << "(error line " << in.line() << " \"unexpected char: " << ((char)in.ch()) << "\" expected \"x\")\n";
|
||||
exit(3);
|
||||
}
|
||||
app_ref p(m);
|
||||
int id = in.parse_int();
|
||||
p = m.mk_const(symbol(id), m.mk_bool_sort());
|
||||
if (negated) p = m.mk_not(p);
|
||||
in.skip_whitespace();
|
||||
return p;
|
||||
}
|
||||
|
||||
app_ref parse_ids() {
|
||||
app_ref result = parse_id();
|
||||
while (*in == '~' || *in == 'x') {
|
||||
result = m.mk_and(result, parse_id());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
rational parse_coeff_r() {
|
||||
in.skip_whitespace();
|
||||
svector<char> num;
|
||||
bool pos = true;
|
||||
if (*in == '-') pos = false, ++in;
|
||||
if (*in == '+') ++in;
|
||||
if (!pos) num.push_back('-');
|
||||
in.skip_whitespace();
|
||||
while ('0' <= *in && *in <='9') num.push_back(*in), ++in;
|
||||
num.push_back(0);
|
||||
return rational(num.c_ptr());
|
||||
}
|
||||
|
||||
app_ref parse_coeff() {
|
||||
return app_ref(arith.mk_numeral(parse_coeff_r(), true), m);
|
||||
}
|
||||
|
||||
app_ref parse_term() {
|
||||
app_ref c = parse_coeff();
|
||||
app_ref e = parse_ids();
|
||||
return app_ref(m.mk_ite(e, c, arith.mk_numeral(rational(0), true)), m);
|
||||
}
|
||||
|
||||
void parse_objective(bool is_min) {
|
||||
app_ref t = parse_term();
|
||||
while (!in.parse_token(";") && !in.eof()) {
|
||||
if (is_min) {
|
||||
t = arith.mk_add(t, parse_term());
|
||||
}
|
||||
else {
|
||||
t = arith.mk_sub(t, parse_term());
|
||||
}
|
||||
}
|
||||
m_handles.push_back(opt.add_objective(t, false));
|
||||
}
|
||||
|
||||
void parse_constraint() {
|
||||
app_ref t = parse_term();
|
||||
while (!in.eof()) {
|
||||
if (in.parse_token(">=")) {
|
||||
t = arith.mk_ge(t, parse_coeff());
|
||||
in.parse_token(";");
|
||||
break;
|
||||
}
|
||||
if (in.parse_token("=")) {
|
||||
t = m.mk_eq(t, parse_coeff());
|
||||
in.parse_token(";");
|
||||
break;
|
||||
}
|
||||
if (in.parse_token("<=")) {
|
||||
t = arith.mk_le(t, parse_coeff());
|
||||
in.parse_token(";");
|
||||
break;
|
||||
}
|
||||
t = arith.mk_add(t, parse_term());
|
||||
}
|
||||
opt.add_hard_constraint(t);
|
||||
}
|
||||
public:
|
||||
opb(opt::context& opt, opt_stream_buffer& in, unsigned_vector& h):
|
||||
opt(opt), m(opt.get_manager()),
|
||||
in(in), m_handles(h), arith(m) {}
|
||||
|
||||
void parse() {
|
||||
while (true) {
|
||||
in.skip_whitespace();
|
||||
if (in.eof()) {
|
||||
break;
|
||||
}
|
||||
else if (*in == '*') {
|
||||
in.skip_line();
|
||||
}
|
||||
else if (in.parse_token("min:")) {
|
||||
parse_objective(true);
|
||||
}
|
||||
else if (in.parse_token("max:")) {
|
||||
parse_objective(false);
|
||||
}
|
||||
else {
|
||||
parse_constraint();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void parse_wcnf(opt::context& opt, std::istream& is, unsigned_vector& h) {
|
||||
opt_stream_buffer _is(is);
|
||||
wcnf w(opt, _is, h);
|
||||
w.parse();
|
||||
}
|
||||
|
||||
void parse_opb(opt::context& opt, std::istream& is, unsigned_vector& h) {
|
||||
opt_stream_buffer _is(is);
|
||||
opb opb(opt, _is, h);
|
||||
opb.parse();
|
||||
}
|
||||
|
||||
|
28
src/opt/opt_parse.h
Normal file
28
src/opt/opt_parse.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
opt_parse.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Parse utilities for optimization.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2017-11-19
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef OPT_PARSE_H_
|
||||
#define OPT_PARSE_H_
|
||||
|
||||
void parse_wcnf(opt::context& opt, std::istream& is, unsigned_vector& h);
|
||||
|
||||
void parse_opb(opt::context& opt, std::istream& is, unsigned_vector& h);
|
||||
|
||||
#endif /* OPT_PARSE_H_ */
|
||||
|
||||
|
|
@ -33,6 +33,7 @@ Revision History:
|
|||
#include "util/timeout.h"
|
||||
#include "util/z3_exception.h"
|
||||
#include "util/error_codes.h"
|
||||
#include "util/file_path.h"
|
||||
#include "util/gparams.h"
|
||||
#include "util/env_params.h"
|
||||
#include "shell/lp_frontend.h"
|
||||
|
@ -289,19 +290,6 @@ void parse_cmd_line_args(int argc, char ** argv) {
|
|||
}
|
||||
}
|
||||
|
||||
char const * get_extension(char const * file_name) {
|
||||
if (file_name == 0)
|
||||
return 0;
|
||||
char const * last_dot = 0;
|
||||
for (;;) {
|
||||
char const * tmp = strchr(file_name, '.');
|
||||
if (tmp == 0) {
|
||||
return last_dot;
|
||||
}
|
||||
last_dot = tmp + 1;
|
||||
file_name = last_dot;
|
||||
}
|
||||
}
|
||||
|
||||
int STD_CALL main(int argc, char ** argv) {
|
||||
try{
|
||||
|
|
|
@ -13,6 +13,7 @@ Copyright (c) 2015 Microsoft Corporation
|
|||
#include "util/gparams.h"
|
||||
#include "util/timeout.h"
|
||||
#include "ast/reg_decl_plugins.h"
|
||||
#include "opt/opt_parse.h"
|
||||
|
||||
extern bool g_display_statistics;
|
||||
static bool g_first_interrupt = true;
|
||||
|
@ -20,275 +21,6 @@ static opt::context* g_opt = 0;
|
|||
static double g_start_time = 0;
|
||||
static unsigned_vector g_handles;
|
||||
|
||||
class opt_stream_buffer {
|
||||
std::istream & m_stream;
|
||||
int m_val;
|
||||
unsigned m_line;
|
||||
public:
|
||||
opt_stream_buffer(std::istream & s):
|
||||
m_stream(s),
|
||||
m_line(0) {
|
||||
m_val = m_stream.get();
|
||||
}
|
||||
int operator *() const { return m_val;}
|
||||
void operator ++() { m_val = m_stream.get(); }
|
||||
int ch() const { return m_val; }
|
||||
void next() { m_val = m_stream.get(); }
|
||||
bool eof() const { return ch() == EOF; }
|
||||
unsigned line() const { return m_line; }
|
||||
void skip_whitespace() {
|
||||
while ((ch() >= 9 && ch() <= 13) || ch() == 32) {
|
||||
if (ch() == 10) ++m_line;
|
||||
next();
|
||||
}
|
||||
}
|
||||
void skip_space() {
|
||||
while (ch() != 10 && ((ch() >= 9 && ch() <= 13) || ch() == 32)) {
|
||||
next();
|
||||
}
|
||||
}
|
||||
void skip_line() {
|
||||
while(true) {
|
||||
if (eof()) {
|
||||
return;
|
||||
}
|
||||
if (ch() == '\n') {
|
||||
++m_line;
|
||||
next();
|
||||
return;
|
||||
}
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
bool parse_token(char const* token) {
|
||||
skip_whitespace();
|
||||
char const* t = token;
|
||||
while (ch() == *t) {
|
||||
next();
|
||||
++t;
|
||||
}
|
||||
return 0 == *t;
|
||||
}
|
||||
|
||||
int parse_int() {
|
||||
int val = 0;
|
||||
bool neg = false;
|
||||
skip_whitespace();
|
||||
|
||||
if (ch() == '-') {
|
||||
neg = true;
|
||||
next();
|
||||
}
|
||||
else if (ch() == '+') {
|
||||
next();
|
||||
}
|
||||
if (ch() < '0' || ch() > '9') {
|
||||
std::cerr << "(error line " << line() << " \"unexpected char: " << ((char)ch()) << "\" )\n";
|
||||
exit(3);
|
||||
}
|
||||
while (ch() >= '0' && ch() <= '9') {
|
||||
val = val*10 + (ch() - '0');
|
||||
next();
|
||||
}
|
||||
return neg ? -val : val;
|
||||
}
|
||||
|
||||
unsigned parse_unsigned() {
|
||||
skip_space();
|
||||
if (ch() == '\n') {
|
||||
return UINT_MAX;
|
||||
}
|
||||
unsigned val = 0;
|
||||
while (ch() >= '0' && ch() <= '9') {
|
||||
val = val*10 + (ch() - '0');
|
||||
next();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
class wcnf {
|
||||
opt::context& opt;
|
||||
ast_manager& m;
|
||||
opt_stream_buffer& in;
|
||||
|
||||
app_ref read_clause(unsigned& weight) {
|
||||
int parsed_lit;
|
||||
int var;
|
||||
weight = in.parse_unsigned();
|
||||
app_ref result(m), p(m);
|
||||
expr_ref_vector ors(m);
|
||||
while (true) {
|
||||
parsed_lit = in.parse_int();
|
||||
if (parsed_lit == 0)
|
||||
break;
|
||||
var = abs(parsed_lit);
|
||||
p = m.mk_const(symbol(var), m.mk_bool_sort());
|
||||
if (parsed_lit < 0) p = m.mk_not(p);
|
||||
ors.push_back(p);
|
||||
}
|
||||
result = to_app(mk_or(m, ors.size(), ors.c_ptr()));
|
||||
return result;
|
||||
}
|
||||
|
||||
void parse_spec(unsigned& num_vars, unsigned& num_clauses, unsigned& max_weight) {
|
||||
in.parse_token("wcnf");
|
||||
num_vars = in.parse_unsigned();
|
||||
num_clauses = in.parse_unsigned();
|
||||
max_weight = in.parse_unsigned();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
wcnf(opt::context& opt, opt_stream_buffer& in): opt(opt), m(opt.get_manager()), in(in) {
|
||||
opt.set_clausal(true);
|
||||
}
|
||||
|
||||
void parse() {
|
||||
unsigned num_vars = 0, num_clauses = 0, max_weight = 0;
|
||||
while (true) {
|
||||
in.skip_whitespace();
|
||||
if (in.eof()) {
|
||||
break;
|
||||
}
|
||||
else if (*in == 'c') {
|
||||
in.skip_line();
|
||||
}
|
||||
else if (*in == 'p') {
|
||||
++in;
|
||||
parse_spec(num_vars, num_clauses, max_weight);
|
||||
}
|
||||
else {
|
||||
unsigned weight = 0;
|
||||
app_ref cls = read_clause(weight);
|
||||
if (weight >= max_weight) {
|
||||
opt.add_hard_constraint(cls);
|
||||
}
|
||||
else {
|
||||
unsigned id = opt.add_soft_constraint(cls, rational(weight), symbol::null);
|
||||
if (g_handles.empty()) {
|
||||
g_handles.push_back(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class opb {
|
||||
opt::context& opt;
|
||||
ast_manager& m;
|
||||
opt_stream_buffer& in;
|
||||
arith_util arith;
|
||||
|
||||
app_ref parse_id() {
|
||||
bool negated = in.parse_token("~");
|
||||
if (!in.parse_token("x")) {
|
||||
std::cerr << "(error line " << in.line() << " \"unexpected char: " << ((char)in.ch()) << "\" expected \"x\")\n";
|
||||
exit(3);
|
||||
}
|
||||
app_ref p(m);
|
||||
int id = in.parse_int();
|
||||
p = m.mk_const(symbol(id), m.mk_bool_sort());
|
||||
if (negated) p = m.mk_not(p);
|
||||
in.skip_whitespace();
|
||||
return p;
|
||||
}
|
||||
|
||||
app_ref parse_ids() {
|
||||
app_ref result = parse_id();
|
||||
while (*in == '~' || *in == 'x') {
|
||||
result = m.mk_and(result, parse_id());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
rational parse_coeff_r() {
|
||||
in.skip_whitespace();
|
||||
svector<char> num;
|
||||
bool pos = true;
|
||||
if (*in == '-') pos = false, ++in;
|
||||
if (*in == '+') ++in;
|
||||
if (!pos) num.push_back('-');
|
||||
in.skip_whitespace();
|
||||
while ('0' <= *in && *in <='9') num.push_back(*in), ++in;
|
||||
num.push_back(0);
|
||||
return rational(num.c_ptr());
|
||||
}
|
||||
|
||||
app_ref parse_coeff() {
|
||||
return app_ref(arith.mk_numeral(parse_coeff_r(), true), m);
|
||||
}
|
||||
|
||||
app_ref parse_term() {
|
||||
app_ref c = parse_coeff();
|
||||
app_ref e = parse_ids();
|
||||
return app_ref(m.mk_ite(e, c, arith.mk_numeral(rational(0), true)), m);
|
||||
}
|
||||
|
||||
void parse_objective(bool is_min) {
|
||||
app_ref t = parse_term();
|
||||
while (!in.parse_token(";") && !in.eof()) {
|
||||
if (is_min) {
|
||||
t = arith.mk_add(t, parse_term());
|
||||
}
|
||||
else {
|
||||
t = arith.mk_sub(t, parse_term());
|
||||
}
|
||||
}
|
||||
g_handles.push_back(opt.add_objective(t, false));
|
||||
}
|
||||
|
||||
void parse_constraint() {
|
||||
app_ref t = parse_term();
|
||||
while (!in.eof()) {
|
||||
if (in.parse_token(">=")) {
|
||||
t = arith.mk_ge(t, parse_coeff());
|
||||
in.parse_token(";");
|
||||
break;
|
||||
}
|
||||
if (in.parse_token("=")) {
|
||||
t = m.mk_eq(t, parse_coeff());
|
||||
in.parse_token(";");
|
||||
break;
|
||||
}
|
||||
if (in.parse_token("<=")) {
|
||||
t = arith.mk_le(t, parse_coeff());
|
||||
in.parse_token(";");
|
||||
break;
|
||||
}
|
||||
t = arith.mk_add(t, parse_term());
|
||||
}
|
||||
opt.add_hard_constraint(t);
|
||||
}
|
||||
public:
|
||||
opb(opt::context& opt, opt_stream_buffer& in):
|
||||
opt(opt), m(opt.get_manager()),
|
||||
in(in), arith(m) {}
|
||||
|
||||
void parse() {
|
||||
while (true) {
|
||||
in.skip_whitespace();
|
||||
if (in.eof()) {
|
||||
break;
|
||||
}
|
||||
else if (*in == '*') {
|
||||
in.skip_line();
|
||||
}
|
||||
else if (in.parse_token("min:")) {
|
||||
parse_objective(true);
|
||||
}
|
||||
else if (in.parse_token("max:")) {
|
||||
parse_objective(false);
|
||||
}
|
||||
else {
|
||||
parse_constraint();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static void display_results() {
|
||||
|
@ -348,14 +80,11 @@ static unsigned parse_opt(std::istream& in, bool is_wcnf) {
|
|||
g_opt = &opt;
|
||||
params_ref p = gparams::get_module("opt");
|
||||
opt.updt_params(p);
|
||||
opt_stream_buffer _in(in);
|
||||
if (is_wcnf) {
|
||||
wcnf wcnf(opt, _in);
|
||||
wcnf.parse();
|
||||
parse_wcnf(opt, in, g_handles);
|
||||
}
|
||||
else {
|
||||
opb opb(opt, _in);
|
||||
opb.parse();
|
||||
parse_opb(opt, in, g_handles);
|
||||
}
|
||||
try {
|
||||
lbool r = opt.optimize();
|
||||
|
|
38
src/util/file_path.h
Normal file
38
src/util/file_path.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
file_path.h
|
||||
|
||||
Abstract:
|
||||
|
||||
File path functions.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2017-11-19
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef FILE_PATH_H_
|
||||
#define FILE_PATH_H_
|
||||
|
||||
inline char const * get_extension(char const * file_name) {
|
||||
if (file_name == 0)
|
||||
return 0;
|
||||
char const * last_dot = 0;
|
||||
for (;;) {
|
||||
char const * tmp = strchr(file_name, '.');
|
||||
if (tmp == 0) {
|
||||
return last_dot;
|
||||
}
|
||||
last_dot = tmp + 1;
|
||||
file_name = last_dot;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* FILE_PATH_H_ */
|
||||
|
||||
|
Loading…
Reference in a new issue