diff --git a/src/math/lp/nra_solver.cpp b/src/math/lp/nra_solver.cpp index 0f30272e9..98002d7cb 100644 --- a/src/math/lp/nra_solver.cpp +++ b/src/math/lp/nra_solver.cpp @@ -433,16 +433,26 @@ struct solver::imp { if (falsified.empty()) return l_undef; - // Pick the falsified constraint with the smallest substitution - // expansion as a cheap LRA-side proxy for the lowest-degree - // heuristic that nlsat_solver::check(rvalues, clause) would apply. + // Pick the falsified constraint according to + // arith.nl.nra_check_assignment_pick: + // 0 - minimal substitution expansion (cheap LRA-side proxy + // for the lowest-degree-in-max-var heuristic that + // nlsat::solver::check(rvalues, clause) applies). + // 1 - uniformly random falsified constraint. lp::constraint_index best = falsified[0]; - unsigned best_score = constraint_expansion_size(best); - for (unsigned k = 1; k < falsified.size(); ++k) { - unsigned sc = constraint_expansion_size(falsified[k]); - if (sc < best_score) { - best_score = sc; - best = falsified[k]; + unsigned pick_mode = m_nla_core.params().arith_nl_nra_check_assignment_pick(); + if (pick_mode == 1) { + unsigned k = m_nla_core.random() % falsified.size(); + best = falsified[k]; + } + else { + unsigned best_score = constraint_expansion_size(best); + for (unsigned k = 1; k < falsified.size(); ++k) { + unsigned sc = constraint_expansion_size(falsified[k]); + if (sc < best_score) { + best_score = sc; + best = falsified[k]; + } } } diff --git a/src/params/smt_params_helper.pyg b/src/params/smt_params_helper.pyg index 6c8ce796d..204bc0e80 100644 --- a/src/params/smt_params_helper.pyg +++ b/src/params/smt_params_helper.pyg @@ -63,6 +63,7 @@ def_module_params(module_name='smt', ('arith.nl.nra', BOOL, True, 'call nra_solver when incremental linearization does not produce a lemma, this option is ignored when arith.nl=false, relevant only if smt.arith.solver=6'), ('arith.nl.nra_check_assignment', BOOL, True, 'call check_assignment in nra_solver to verify current assignment against nlsat constraints'), ('arith.nl.nra_check_assignment_max_fail', UINT, 7, 'maximum consecutive check_assignment failures before disabling it'), + ('arith.nl.nra_check_assignment_pick', UINT, 0, 'falsified-literal selection in check_assignment: 0 - minimal degree (size) of the max variable (default), 1 - random'), ('arith.nl.branching', BOOL, True, 'branching on integer variables in non linear clusters'), ('arith.nl.expensive_patching', BOOL, False, 'use the expensive of monomials'), ('arith.nl.rounds', UINT, 1024, 'threshold for number of (nested) final checks for non linear arithmetic, relevant only if smt.arith.solver=2'),