mirror of
https://github.com/Z3Prover/z3
synced 2025-06-09 15:43:25 +00:00
fix regressions in nl/smt
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
5632900f35
commit
e8811748d3
7 changed files with 49 additions and 35 deletions
|
@ -85,6 +85,7 @@ VS_PAR=False
|
||||||
VS_PAR_NUM=8
|
VS_PAR_NUM=8
|
||||||
GPROF=False
|
GPROF=False
|
||||||
GIT_HASH=False
|
GIT_HASH=False
|
||||||
|
OPTIMIZE=False
|
||||||
|
|
||||||
FPMATH="Default"
|
FPMATH="Default"
|
||||||
FPMATH_FLAGS="-mfpmath=sse -msse -msse2"
|
FPMATH_FLAGS="-mfpmath=sse -msse -msse2"
|
||||||
|
@ -551,6 +552,8 @@ def display_help(exit_code):
|
||||||
print(" -v, --vsproj generate Visual Studio Project Files.")
|
print(" -v, --vsproj generate Visual Studio Project Files.")
|
||||||
if IS_WINDOWS:
|
if IS_WINDOWS:
|
||||||
print(" -n, --nodotnet do not generate Microsoft.Z3.dll make rules.")
|
print(" -n, --nodotnet do not generate Microsoft.Z3.dll make rules.")
|
||||||
|
if IS_WINDOWS:
|
||||||
|
print(" --optimize generate optimized code during linking.")
|
||||||
print(" -j, --java generate Java bindings.")
|
print(" -j, --java generate Java bindings.")
|
||||||
print(" --ml generate OCaml bindings.")
|
print(" --ml generate OCaml bindings.")
|
||||||
print(" --staticlib build Z3 static library.")
|
print(" --staticlib build Z3 static library.")
|
||||||
|
@ -577,13 +580,13 @@ def display_help(exit_code):
|
||||||
def parse_options():
|
def parse_options():
|
||||||
global VERBOSE, DEBUG_MODE, IS_WINDOWS, VS_X64, ONLY_MAKEFILES, SHOW_CPPS, VS_PROJ, TRACE, VS_PAR, VS_PAR_NUM
|
global VERBOSE, DEBUG_MODE, IS_WINDOWS, VS_X64, ONLY_MAKEFILES, SHOW_CPPS, VS_PROJ, TRACE, VS_PAR, VS_PAR_NUM
|
||||||
global DOTNET_ENABLED, JAVA_ENABLED, ML_ENABLED, STATIC_LIB, PREFIX, GMP, FOCI2, FOCI2LIB, PYTHON_PACKAGE_DIR, GPROF, GIT_HASH
|
global DOTNET_ENABLED, JAVA_ENABLED, ML_ENABLED, STATIC_LIB, PREFIX, GMP, FOCI2, FOCI2LIB, PYTHON_PACKAGE_DIR, GPROF, GIT_HASH
|
||||||
global LINUX_X64
|
global LINUX_X64, OPTIMIZE
|
||||||
try:
|
try:
|
||||||
options, remainder = getopt.gnu_getopt(sys.argv[1:],
|
options, remainder = getopt.gnu_getopt(sys.argv[1:],
|
||||||
'b:df:sxhmcvtnp:gj',
|
'b:df:sxhmcvtnp:gj',
|
||||||
['build=', 'debug', 'silent', 'x64', 'help', 'makefiles', 'showcpp', 'vsproj',
|
['build=', 'debug', 'silent', 'x64', 'help', 'makefiles', 'showcpp', 'vsproj',
|
||||||
'trace', 'nodotnet', 'staticlib', 'prefix=', 'gmp', 'foci2=', 'java', 'parallel=', 'gprof',
|
'trace', 'nodotnet', 'staticlib', 'prefix=', 'gmp', 'foci2=', 'java', 'parallel=', 'gprof',
|
||||||
'githash=', 'x86', 'ml'])
|
'githash=', 'x86', 'ml', 'optimize'])
|
||||||
except:
|
except:
|
||||||
print("ERROR: Invalid command line option")
|
print("ERROR: Invalid command line option")
|
||||||
display_help(1)
|
display_help(1)
|
||||||
|
@ -618,6 +621,8 @@ def parse_options():
|
||||||
DOTNET_ENABLED = False
|
DOTNET_ENABLED = False
|
||||||
elif opt in ('--staticlib'):
|
elif opt in ('--staticlib'):
|
||||||
STATIC_LIB = True
|
STATIC_LIB = True
|
||||||
|
elif opt in ('--optimize'):
|
||||||
|
OPTIMIZE = True
|
||||||
elif not IS_WINDOWS and opt in ('-p', '--prefix'):
|
elif not IS_WINDOWS and opt in ('-p', '--prefix'):
|
||||||
PREFIX = arg
|
PREFIX = arg
|
||||||
PYTHON_PACKAGE_DIR = os.path.join(PREFIX, 'lib', 'python%s' % distutils.sysconfig.get_python_version(), 'dist-packages')
|
PYTHON_PACKAGE_DIR = os.path.join(PREFIX, 'lib', 'python%s' % distutils.sysconfig.get_python_version(), 'dist-packages')
|
||||||
|
@ -1781,8 +1786,9 @@ def mk_config():
|
||||||
'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n')
|
'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n')
|
||||||
else:
|
else:
|
||||||
# Windows Release mode
|
# Windows Release mode
|
||||||
|
if OPTIMIZE:
|
||||||
|
config.write('AR_FLAGS=/nologo /LTCG\n')
|
||||||
config.write(
|
config.write(
|
||||||
'AR_FLAGS=/nologo /LTCG\n'
|
|
||||||
'LINK_FLAGS=/nologo /MD\n'
|
'LINK_FLAGS=/nologo /MD\n'
|
||||||
'SLINK_FLAGS=/nologo /LD\n')
|
'SLINK_FLAGS=/nologo /LD\n')
|
||||||
if TRACE:
|
if TRACE:
|
||||||
|
|
|
@ -882,10 +882,10 @@ namespace smt {
|
||||||
template<bool invert>
|
template<bool invert>
|
||||||
void add_tmp_row_entry(row & r, numeral const & coeff, theory_var v);
|
void add_tmp_row_entry(row & r, numeral const & coeff, theory_var v);
|
||||||
enum max_min_t { UNBOUNDED, AT_BOUND, OPTIMIZED, BEST_EFFORT};
|
enum max_min_t { UNBOUNDED, AT_BOUND, OPTIMIZED, BEST_EFFORT};
|
||||||
max_min_t max_min(theory_var v, bool max, bool& has_shared);
|
max_min_t max_min(theory_var v, bool max, bool maintain_integrality, bool& has_shared);
|
||||||
bool max_min(svector<theory_var> const & vars);
|
bool max_min(svector<theory_var> const & vars);
|
||||||
|
|
||||||
max_min_t max_min(row& r, bool max, bool& has_shared);
|
max_min_t max_min(row& r, bool max, bool maintain_integrality, bool& has_shared);
|
||||||
bool unbounded_gain(inf_numeral const & max_gain) const;
|
bool unbounded_gain(inf_numeral const & max_gain) const;
|
||||||
bool safe_gain(inf_numeral const& min_gain, inf_numeral const & max_gain) const;
|
bool safe_gain(inf_numeral const& min_gain, inf_numeral const & max_gain) const;
|
||||||
void normalize_gain(numeral const& divisor, inf_numeral & max_gain) const;
|
void normalize_gain(numeral const& divisor, inf_numeral & max_gain) const;
|
||||||
|
|
|
@ -1133,7 +1133,7 @@ namespace smt {
|
||||||
inf_eps_rational<inf_rational> theory_arith<Ext>::maximize(theory_var v, expr_ref& blocker, bool& has_shared) {
|
inf_eps_rational<inf_rational> theory_arith<Ext>::maximize(theory_var v, expr_ref& blocker, bool& has_shared) {
|
||||||
TRACE("bound_bug", display_var(tout, v); display(tout););
|
TRACE("bound_bug", display_var(tout, v); display(tout););
|
||||||
has_shared = false;
|
has_shared = false;
|
||||||
max_min_t r = max_min(v, true, has_shared);
|
max_min_t r = max_min(v, true, true, has_shared);
|
||||||
if (r == UNBOUNDED) {
|
if (r == UNBOUNDED) {
|
||||||
has_shared = false;
|
has_shared = false;
|
||||||
blocker = get_manager().mk_false();
|
blocker = get_manager().mk_false();
|
||||||
|
@ -1553,13 +1553,14 @@ namespace smt {
|
||||||
typename theory_arith<Ext>::max_min_t theory_arith<Ext>::max_min(
|
typename theory_arith<Ext>::max_min_t theory_arith<Ext>::max_min(
|
||||||
row & r,
|
row & r,
|
||||||
bool max,
|
bool max,
|
||||||
|
bool maintain_integrality,
|
||||||
bool& has_shared) {
|
bool& has_shared) {
|
||||||
m_stats.m_max_min++;
|
m_stats.m_max_min++;
|
||||||
unsigned best_efforts = 0;
|
unsigned best_efforts = 0;
|
||||||
bool inc = false;
|
bool inc = false;
|
||||||
context& ctx = get_context();
|
context& ctx = get_context();
|
||||||
|
|
||||||
SASSERT(valid_assignment());
|
SASSERT(!maintain_integrality || valid_assignment());
|
||||||
|
|
||||||
numeral a_ij, curr_a_ij, coeff, curr_coeff;
|
numeral a_ij, curr_a_ij, coeff, curr_coeff;
|
||||||
inf_numeral min_gain, max_gain, curr_min_gain, curr_max_gain;
|
inf_numeral min_gain, max_gain, curr_min_gain, curr_max_gain;
|
||||||
|
@ -1633,7 +1634,7 @@ namespace smt {
|
||||||
|
|
||||||
if (x_j == null_theory_var) {
|
if (x_j == null_theory_var) {
|
||||||
TRACE("opt", tout << "row is " << (max ? "maximized" : "minimized") << "\n";);
|
TRACE("opt", tout << "row is " << (max ? "maximized" : "minimized") << "\n";);
|
||||||
SASSERT(valid_assignment());
|
SASSERT(!maintain_integrality || valid_assignment());
|
||||||
result = OPTIMIZED;
|
result = OPTIMIZED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1648,7 +1649,7 @@ namespace smt {
|
||||||
SASSERT(!unbounded_gain(max_gain));
|
SASSERT(!unbounded_gain(max_gain));
|
||||||
update_value(x_j, max_gain);
|
update_value(x_j, max_gain);
|
||||||
TRACE("opt", tout << "moved v" << x_j << " to upper bound\n";);
|
TRACE("opt", tout << "moved v" << x_j << " to upper bound\n";);
|
||||||
SASSERT(valid_assignment());
|
SASSERT(!maintain_integrality || valid_assignment());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!inc && lower(x_j)) {
|
if (!inc && lower(x_j)) {
|
||||||
|
@ -1656,7 +1657,7 @@ namespace smt {
|
||||||
max_gain.neg();
|
max_gain.neg();
|
||||||
update_value(x_j, max_gain);
|
update_value(x_j, max_gain);
|
||||||
TRACE("opt", tout << "moved v" << x_j << " to lower bound\n";);
|
TRACE("opt", tout << "moved v" << x_j << " to lower bound\n";);
|
||||||
SASSERT(valid_assignment());
|
SASSERT(!maintain_integrality || valid_assignment());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ctx.is_shared(get_enode(x_j))) {
|
if (ctx.is_shared(get_enode(x_j))) {
|
||||||
|
@ -1681,7 +1682,7 @@ namespace smt {
|
||||||
TRACE("opt", tout << "moved v" << x_j << " to lower bound\n";);
|
TRACE("opt", tout << "moved v" << x_j << " to lower bound\n";);
|
||||||
}
|
}
|
||||||
update_value(x_j, max_gain);
|
update_value(x_j, max_gain);
|
||||||
SASSERT(valid_assignment());
|
SASSERT(!maintain_integrality || valid_assignment());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1709,7 +1710,7 @@ namespace smt {
|
||||||
coeff.neg();
|
coeff.neg();
|
||||||
add_tmp_row(r, coeff, r2);
|
add_tmp_row(r, coeff, r2);
|
||||||
SASSERT(r.get_idx_of(x_j) == -1);
|
SASSERT(r.get_idx_of(x_j) == -1);
|
||||||
SASSERT(valid_assignment());
|
SASSERT(!maintain_integrality || valid_assignment());
|
||||||
}
|
}
|
||||||
TRACE("opt", display(tout););
|
TRACE("opt", display(tout););
|
||||||
return (best_efforts>0)?BEST_EFFORT:result;
|
return (best_efforts>0)?BEST_EFFORT:result;
|
||||||
|
@ -1781,10 +1782,10 @@ namespace smt {
|
||||||
\brief Maximize/Minimize the given variable. The bounds of v are update if procedure succeeds.
|
\brief Maximize/Minimize the given variable. The bounds of v are update if procedure succeeds.
|
||||||
*/
|
*/
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
typename theory_arith<Ext>::max_min_t theory_arith<Ext>::max_min(theory_var v, bool max, bool& has_shared) {
|
typename theory_arith<Ext>::max_min_t theory_arith<Ext>::max_min(theory_var v, bool max, bool maintain_integrality, bool& has_shared) {
|
||||||
expr* e = get_enode(v)->get_owner();
|
expr* e = get_enode(v)->get_owner();
|
||||||
|
|
||||||
SASSERT(valid_assignment());
|
SASSERT(!maintain_integrality || valid_assignment());
|
||||||
SASSERT(!is_quasi_base(v));
|
SASSERT(!is_quasi_base(v));
|
||||||
if ((max && at_upper(v)) || (!max && at_lower(v))) {
|
if ((max && at_upper(v)) || (!max && at_lower(v))) {
|
||||||
TRACE("opt", tout << "At bound: " << mk_pp(e, get_manager()) << "...\n";);
|
TRACE("opt", tout << "At bound: " << mk_pp(e, get_manager()) << "...\n";);
|
||||||
|
@ -1803,7 +1804,7 @@ namespace smt {
|
||||||
add_tmp_row_entry<true>(m_tmp_row, it->m_coeff, it->m_var);
|
add_tmp_row_entry<true>(m_tmp_row, it->m_coeff, it->m_var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
max_min_t r = max_min(m_tmp_row, max, has_shared);
|
max_min_t r = max_min(m_tmp_row, max, maintain_integrality, has_shared);
|
||||||
if (r == OPTIMIZED) {
|
if (r == OPTIMIZED) {
|
||||||
TRACE("opt", tout << mk_pp(e, get_manager()) << " " << (max ? "max" : "min") << " value is: " << get_value(v) << "\n";
|
TRACE("opt", tout << mk_pp(e, get_manager()) << " " << (max ? "max" : "min") << " value is: " << get_value(v) << "\n";
|
||||||
display_row(tout, m_tmp_row, true); display_row_info(tout, m_tmp_row););
|
display_row(tout, m_tmp_row, true); display_row_info(tout, m_tmp_row););
|
||||||
|
@ -1830,9 +1831,9 @@ namespace smt {
|
||||||
svector<theory_var>::const_iterator it = vars.begin();
|
svector<theory_var>::const_iterator it = vars.begin();
|
||||||
svector<theory_var>::const_iterator end = vars.end();
|
svector<theory_var>::const_iterator end = vars.end();
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
if (max_min(*it, true, has_shared) == OPTIMIZED && !has_shared)
|
if (max_min(*it, true, false, has_shared) == OPTIMIZED && !has_shared)
|
||||||
succ = true;
|
succ = true;
|
||||||
if (max_min(*it, false, has_shared) == OPTIMIZED && !has_shared)
|
if (max_min(*it, false, false, has_shared) == OPTIMIZED && !has_shared)
|
||||||
succ = true;
|
succ = true;
|
||||||
}
|
}
|
||||||
if (succ) {
|
if (succ) {
|
||||||
|
|
|
@ -214,10 +214,13 @@ namespace smt {
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
bool theory_arith<Ext>::valid_assignment() const {
|
bool theory_arith<Ext>::valid_assignment() const {
|
||||||
return
|
if (valid_row_assignment() &&
|
||||||
valid_row_assignment() &&
|
|
||||||
satisfy_bounds() &&
|
satisfy_bounds() &&
|
||||||
satisfy_integrality();
|
satisfy_integrality()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
TRACE("arith", display(tout););
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -549,9 +549,10 @@ struct is_non_qfufnra_functor {
|
||||||
case OP_IRRATIONAL_ALGEBRAIC_NUM:
|
case OP_IRRATIONAL_ALGEBRAIC_NUM:
|
||||||
return;
|
return;
|
||||||
case OP_MUL:
|
case OP_MUL:
|
||||||
if (n->get_num_args() == 2 ||
|
if (n->get_num_args() == 2 &&
|
||||||
(!u.is_numeral(n->get_arg(0)) &&
|
u.is_real(n->get_arg(0)) &&
|
||||||
!u.is_numeral(n->get_arg(1)))) {
|
!u.is_numeral(n->get_arg(0)) &&
|
||||||
|
!u.is_numeral(n->get_arg(1))) {
|
||||||
m_has_nonlinear = true;
|
m_has_nonlinear = true;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -311,6 +311,7 @@ private:
|
||||||
// assert equalities between equal interface real variables.
|
// assert equalities between equal interface real variables.
|
||||||
|
|
||||||
model_ref mdl_nl, mdl_smt;
|
model_ref mdl_nl, mdl_smt;
|
||||||
|
if (mdl_nl.get()) {
|
||||||
model_converter2model(m, nl_mc.get(), mdl_nl);
|
model_converter2model(m, nl_mc.get(), mdl_nl);
|
||||||
update_eq_values(mdl_nl);
|
update_eq_values(mdl_nl);
|
||||||
enforce_equalities(mdl_nl, m_nl_g);
|
enforce_equalities(mdl_nl, m_nl_g);
|
||||||
|
@ -320,7 +321,7 @@ private:
|
||||||
TRACE("nlsat_smt",
|
TRACE("nlsat_smt",
|
||||||
model_smt2_pp(tout << "nl model\n", m, *mdl_nl.get(), 0);
|
model_smt2_pp(tout << "nl model\n", m, *mdl_nl.get(), 0);
|
||||||
m_solver->display(tout << "smt goal:\n"); tout << "\n";);
|
m_solver->display(tout << "smt goal:\n"); tout << "\n";);
|
||||||
|
}
|
||||||
result.reset();
|
result.reset();
|
||||||
lbool r = m_solver->check_sat(m_asms.size(), m_asms.c_ptr());
|
lbool r = m_solver->check_sat(m_asms.size(), m_asms.c_ptr());
|
||||||
if (r == l_false) {
|
if (r == l_false) {
|
||||||
|
@ -352,7 +353,9 @@ private:
|
||||||
TRACE("nlsat_smt",
|
TRACE("nlsat_smt",
|
||||||
m_fmc->display(tout << "joint state is sat\n");
|
m_fmc->display(tout << "joint state is sat\n");
|
||||||
nl_mc->display(tout << "nl\n"););
|
nl_mc->display(tout << "nl\n"););
|
||||||
|
if (mdl_nl.get()) {
|
||||||
merge_models(*mdl_nl.get(), mdl_smt);
|
merge_models(*mdl_nl.get(), mdl_smt);
|
||||||
|
}
|
||||||
mc = m_fmc.get();
|
mc = m_fmc.get();
|
||||||
apply(mc, mdl_smt, 0);
|
apply(mc, mdl_smt, 0);
|
||||||
mc = model2model_converter(mdl_smt.get());
|
mc = model2model_converter(mdl_smt.get());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue