mirror of
https://github.com/Z3Prover/z3
synced 2025-06-06 22:23:22 +00:00
A few changes based on previous reviews
Tested the optimization procedure with: - unbounded objectives - bounded with rational solutions - bounded with irrational solutions
This commit is contained in:
parent
3dd72f8f16
commit
3441fc2942
8 changed files with 24 additions and 26 deletions
|
@ -68,7 +68,7 @@ namespace opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_objectives.empty()) {
|
if (!m_objectives.empty()) {
|
||||||
vector<inf_eps_rational<rational> > values;
|
vector<inf_eps_rational<inf_rational> > values;
|
||||||
for (unsigned i = 0; i < fmls_copy.size(); ++i) {
|
for (unsigned i = 0; i < fmls_copy.size(); ++i) {
|
||||||
s->assert_expr(fmls_copy[i].get());
|
s->assert_expr(fmls_copy[i].get());
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ namespace opt {
|
||||||
// if (!instsanceof ...) { throw ... invalid usage ..}
|
// if (!instsanceof ...) { throw ... invalid usage ..}
|
||||||
is_sat = optimize_objectives(dynamic_cast<opt_solver&>(*s), m_objectives, m_is_max, values);
|
is_sat = optimize_objectives(dynamic_cast<opt_solver&>(*s), m_objectives, m_is_max, values);
|
||||||
std::cout << "is-sat: " << is_sat << "\n";
|
std::cout << "is-sat: " << is_sat << "\n";
|
||||||
|
|
||||||
if (is_sat != l_true) {
|
if (is_sat != l_true) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ namespace opt {
|
||||||
if (is_bounded) {
|
if (is_bounded) {
|
||||||
m_objective_value = get_optimizer().get_objective_value(m_objective_var);
|
m_objective_value = get_optimizer().get_objective_value(m_objective_var);
|
||||||
} else {
|
} else {
|
||||||
inf_eps_rational<rational> r(rational(1), rational(0));
|
inf_eps_rational<inf_rational> r(rational(1), inf_rational(0));
|
||||||
m_objective_value = r;
|
m_objective_value = r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ namespace opt {
|
||||||
m_objective_enabled = enable;
|
m_objective_enabled = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
inf_eps_rational<rational> opt_solver::get_objective_value() {
|
inf_eps_rational<inf_rational> opt_solver::get_objective_value() {
|
||||||
return m_objective_value;
|
return m_objective_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ Notes:
|
||||||
#ifndef _OPT_SOLVER_H_
|
#ifndef _OPT_SOLVER_H_
|
||||||
#define _OPT_SOLVER_H_
|
#define _OPT_SOLVER_H_
|
||||||
|
|
||||||
|
#include"inf_rational.h"
|
||||||
#include"inf_eps_rational.h"
|
#include"inf_eps_rational.h"
|
||||||
#include"ast.h"
|
#include"ast.h"
|
||||||
#include"params.h"
|
#include"params.h"
|
||||||
|
@ -38,7 +39,7 @@ namespace opt {
|
||||||
symbol m_logic;
|
symbol m_logic;
|
||||||
bool m_objective_enabled;
|
bool m_objective_enabled;
|
||||||
smt::theory_var m_objective_var;
|
smt::theory_var m_objective_var;
|
||||||
inf_eps_rational<rational> m_objective_value;
|
inf_eps_rational<inf_rational> m_objective_value;
|
||||||
public:
|
public:
|
||||||
opt_solver(ast_manager & m, params_ref const & p, symbol const & l);
|
opt_solver(ast_manager & m, params_ref const & p, symbol const & l);
|
||||||
virtual ~opt_solver();
|
virtual ~opt_solver();
|
||||||
|
@ -64,7 +65,7 @@ namespace opt {
|
||||||
void set_objective(app* term);
|
void set_objective(app* term);
|
||||||
void toggle_objective(bool enable);
|
void toggle_objective(bool enable);
|
||||||
|
|
||||||
inf_eps_rational<rational> get_objective_value();
|
inf_eps_rational<inf_rational> get_objective_value();
|
||||||
private:
|
private:
|
||||||
smt::theory_opt& get_optimizer();
|
smt::theory_opt& get_optimizer();
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,23 +33,20 @@ namespace opt {
|
||||||
opt_solver& s,
|
opt_solver& s,
|
||||||
app_ref_vector& objectives,
|
app_ref_vector& objectives,
|
||||||
svector<bool> const& is_max,
|
svector<bool> const& is_max,
|
||||||
vector<inf_eps_rational<rational> >& values)
|
vector<inf_eps_rational<inf_rational> >& values)
|
||||||
{
|
{
|
||||||
SASSERT(is_max.size() == objectives.size());
|
SASSERT(is_max.size() == objectives.size());
|
||||||
|
|
||||||
enable_trace("maximize"); // NSB review: OK for now for debugging. Otherwise, use command-line /tr:maximize
|
|
||||||
|
|
||||||
// First check_sat call for initialize theories
|
// First check_sat call for initialize theories
|
||||||
lbool is_sat = s.check_sat(0, 0);
|
lbool is_sat = s.check_sat(0, 0);
|
||||||
if (is_sat != l_false) {
|
if (is_sat == l_false) {
|
||||||
return is_sat;
|
return is_sat;
|
||||||
}
|
}
|
||||||
|
|
||||||
s.push();
|
s.push();
|
||||||
|
|
||||||
|
// Temporarily ignore the assertion to run the first objective function
|
||||||
// Assume there is only one objective function
|
//SASSERT(is_max.size() == 1);
|
||||||
SASSERT(is_max.size() == 1);
|
|
||||||
ast_manager& m = objectives.get_manager();
|
ast_manager& m = objectives.get_manager();
|
||||||
arith_util autil(m);
|
arith_util autil(m);
|
||||||
bool ismax = is_max[0];
|
bool ismax = is_max[0];
|
||||||
|
@ -62,20 +59,19 @@ namespace opt {
|
||||||
s.set_objective(objective_var); // NSB review: I would change signature of set_objective to take is_max and decide whether to add equation.
|
s.set_objective(objective_var); // NSB review: I would change signature of set_objective to take is_max and decide whether to add equation.
|
||||||
// Otherwise, the difference logic backends will not work.
|
// Otherwise, the difference logic backends will not work.
|
||||||
s.toggle_objective(true);
|
s.toggle_objective(true);
|
||||||
is_sat = s.check_sat(0, 0);
|
is_sat = s.check_sat(0, 0);
|
||||||
|
|
||||||
while (is_sat == l_true) {
|
while (is_sat == l_true) {
|
||||||
// Extract values for objectives
|
// Extract values for objectives
|
||||||
inf_eps_rational<rational> val;
|
inf_eps_rational<inf_rational> val;
|
||||||
val = is_max[0] ? s.get_objective_value() : -s.get_objective_value();
|
val = ismax ? s.get_objective_value() : -s.get_objective_value();
|
||||||
|
|
||||||
// Check whether objective is unbounded
|
// Check whether objective is unbounded
|
||||||
// NSB: review: what if optimal is 1-epsilon. Then the check also fails.
|
|
||||||
|
|
||||||
values.reset();
|
values.reset();
|
||||||
values.push_back(val);
|
values.push_back(val);
|
||||||
|
|
||||||
if (!val.is_rational()) {
|
if (!val.get_infinity().is_zero()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +86,7 @@ namespace opt {
|
||||||
if (is_sat == l_undef) {
|
if (is_sat == l_undef) {
|
||||||
return is_sat;
|
return is_sat;
|
||||||
}
|
}
|
||||||
SASSERT(is_sat == l_false); // NSB review: not really water-tight with cancellation and with infinitesimal solutions.
|
//SASSERT(is_sat == l_false); // NSB review: not really water-tight with cancellation and with infinitesimal solutions.
|
||||||
return l_true;
|
return l_true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +97,7 @@ namespace opt {
|
||||||
|
|
||||||
lbool optimize_objectives(opt_solver& s,
|
lbool optimize_objectives(opt_solver& s,
|
||||||
app_ref_vector& objectives, svector<bool> const& is_max,
|
app_ref_vector& objectives, svector<bool> const& is_max,
|
||||||
vector<inf_eps_rational<rational> >& values) {
|
vector<inf_eps_rational<inf_rational> >& values) {
|
||||||
return mathsat_style_opt(s, objectives, is_max, values);
|
return mathsat_style_opt(s, objectives, is_max, values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace opt {
|
||||||
|
|
||||||
lbool optimize_objectives(opt_solver& s,
|
lbool optimize_objectives(opt_solver& s,
|
||||||
app_ref_vector& objectives, svector<bool> const& is_max,
|
app_ref_vector& objectives, svector<bool> const& is_max,
|
||||||
vector<inf_eps_rational<rational> >& values);
|
vector<inf_eps_rational<inf_rational> >& values);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -994,7 +994,7 @@ namespace smt {
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
virtual bool maximize(theory_var v) { return max_min(v, true); }
|
virtual bool maximize(theory_var v) { return max_min(v, true); }
|
||||||
virtual theory_var add_objective(app* term);
|
virtual theory_var add_objective(app* term);
|
||||||
virtual inf_eps_rational<rational> get_objective_value(theory_var v);
|
virtual inf_eps_rational<inf_rational> get_objective_value(theory_var v);
|
||||||
inf_rational m_objective;
|
inf_rational m_objective;
|
||||||
|
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
|
|
|
@ -961,9 +961,8 @@ namespace smt {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
inf_eps_rational<rational> theory_arith<Ext>::get_objective_value(theory_var v) {
|
inf_eps_rational<inf_rational> theory_arith<Ext>::get_objective_value(theory_var v) {
|
||||||
inf_eps_rational<rational> val;
|
inf_eps_rational<inf_rational> val(m_objective);
|
||||||
val = m_objective.get_rational();
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ Notes:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
#include "inf_rational.h"
|
||||||
#include "inf_eps_rational.h"
|
#include "inf_eps_rational.h"
|
||||||
|
|
||||||
#ifndef _THEORY_OPT_H_
|
#ifndef _THEORY_OPT_H_
|
||||||
|
@ -28,9 +29,9 @@ namespace smt {
|
||||||
public:
|
public:
|
||||||
virtual bool maximize(theory_var v) { UNREACHABLE(); return false; };
|
virtual bool maximize(theory_var v) { UNREACHABLE(); return false; };
|
||||||
virtual theory_var add_objective(app* term) { UNREACHABLE(); return null_theory_var; }
|
virtual theory_var add_objective(app* term) { UNREACHABLE(); return null_theory_var; }
|
||||||
virtual inf_eps_rational<rational> get_objective_value(theory_var v) {
|
virtual inf_eps_rational<inf_rational> get_objective_value(theory_var v) {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
inf_eps_rational<rational> r(rational(1), rational(0));
|
inf_eps_rational<inf_rational> r(rational(1), inf_rational(0));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue