spot: Implement dt*a_sat_minimize_assume(...) methods

* python/spot/__init__.py: Add 'assume' option.
* spot/misc/satsolver.cc: Add function to handle assumptions.
* spot/misc/satsolver.hh: Declare assumption function.
* spot/twaalgos/dtbasat.cc: Implement dtba_sat_minimize_assume.
* spot/twaalgos/dtbasat.hh: Declare it.
* spot/twaalgos/dtwasat.cc: Implement dtwa_sat_minimize_assume and
handle options.
* spot/twaalgos/dtwasat.hh: Declare it.
* spot/twaalgos/postproc.cc: Handle options.
* spot/twaalgos/postproc.hh: Use param_ var for incr and assume.
* tests/core/satmin.test: Add tests for the new function.
* tests/core/satmin2.test: Add tests for the new function.
* tests/python/satmin.py: Add tests for the new function.
This commit is contained in:
Alexandre GBAGUIDI AISSE 2016-10-11 16:08:46 +02:00
parent ee17c2dee4
commit 9a204b770f
12 changed files with 1021 additions and 69 deletions

View file

@ -532,8 +532,11 @@ namespace spot
typedef std::pair<int, int> sat_stats;
static
sat_stats dtwa_to_sat(satsolver& solver, const_twa_graph_ptr ref,
dict& d, bool state_based, bool colored)
sat_stats dtwa_to_sat(satsolver& solver,
const_twa_graph_ptr ref,
dict& d,
bool state_based,
bool colored)
{
#if DEBUG
debug_dict = ref->get_dict();
@ -1054,6 +1057,166 @@ namespace spot
}
}
static twa_graph_ptr
dichotomy_dtwa_research(int max,
dict& d,
satsolver& solver,
timer_map& t1,
const_twa_graph_ptr& prev,
bool state_based)
{
trace << "dichotomy_dtwa_research(...)\n";
int min = 1;
int target = 0;
twa_graph_ptr res = nullptr;
while (min < max)
{
target = (max + min) / 2;
trace << "min:" << min << ", max:" << max << ", target:" << target
<< '\n';
solver.assume(d.nvars + target);
trace << "solver.assume(" << d.nvars + target << ")\n";
satsolver::solution_pair solution = solver.get_solution();
if (solution.second.empty())
{
trace << "UNSAT\n";
max = target;
}
else
{
trace << "SAT\n";
res = sat_build(solution.second, d, prev, state_based);
min = d.cand_size - stats_reachable(res).states + 1;
}
}
trace << "End with max:" << max << ", min:" << min << '\n';
if (!res)
{
trace << "All assumptions are UNSAT, let's try without...";
satsolver::solution_pair solution = solver.get_solution();
trace << (solution.second.empty() ? "UNSAT!\n" : "SAT\n");
res = solution.second.empty() ? nullptr :
sat_build(solution.second, d, prev, state_based);
}
t1.stop("solve");
print_log(t1, d.cand_size - target , res, solver); // SPOT_SATLOG.
return res ? res : std::const_pointer_cast<spot::twa_graph>(prev);
}
twa_graph_ptr
dtwa_sat_minimize_assume(const const_twa_graph_ptr& a,
unsigned target_acc_number,
const acc_cond::acc_code& target_acc,
bool state_based,
int max_states,
bool colored,
int sat_incr_steps)
{
if (sat_incr_steps < 0)
throw std::runtime_error("with 'assume' algorithm, sat_incr_steps value "
"must be >= 0");
const_twa_graph_ptr prev = a;
dict d(prev);
d.cand_size = (max_states < 0) ?
stats_reachable(prev).states - 1 : max_states;
d.cand_nacc = target_acc_number;
d.cand_acc = target_acc;
if (d.cand_size == 0)
return nullptr;
trace << "dtwa_sat_minimize_assume(..., nacc = " << target_acc_number
<< ", acc = \"" << target_acc << "\", states = " << d.cand_size
<< ", state_based = " << state_based << ")\n";
trace << "sat_incr_steps: " << sat_incr_steps << '\n';
twa_graph_ptr next = spot::make_twa_graph(spot::make_bdd_dict());
while (next && d.cand_size > 0)
{
// Warns the satsolver of the number of assumptions.
int n_assumptions = (int) d.cand_size < sat_incr_steps ?
d.cand_size - 1 : sat_incr_steps;
trace << "number of assumptions:" << n_assumptions << '\n';
satsolver solver;
solver.set_nassumptions_vars(n_assumptions);
// First iteration of classic solving.
timer_map t1;
t1.start("encode");
dtwa_to_sat(solver, prev, d, state_based, colored);
// Compute the AP used.
bdd ap = prev->ap_vars();
// Add all assumptions clauses.
unsigned dst = d.cand_size - 1;
unsigned alpha_size = d.alpha_vect.size();
for (int i = 1; i <= n_assumptions; i++, dst--)
{
cnf_comment("Next iteration:", dst, "\n");
int assume_lit = d.nvars + i;
cnf_comment("Add clauses to forbid the dst state.\n");
for (unsigned l = 0; l < alpha_size; ++l)
for (unsigned j = 0; j < d.cand_size; ++j)
{
cnf_comment(assume_lit, "→ ¬", d.fmt_t(j, l, dst), '\n');
solver.add({-assume_lit, -d.transid(j, l, dst), 0});
}
// The assumption which has just been encoded implies the preceding
// ones.
if (i != 1)
{
cnf_comment(assume_lit, "", assume_lit - 1, '\n');
solver.add({-assume_lit, assume_lit - 1, 0});
}
}
t1.stop("encode");
t1.start("solve");
if (n_assumptions)
{
trace << "solver.assume(" << d.nvars + n_assumptions << ")\n";
solver.assume(d.nvars + n_assumptions);
}
satsolver::solution_pair solution = solver.get_solution();
if (solution.second.empty() && n_assumptions) // UNSAT
{
trace << "UNSAT\n";
twa_graph_ptr res = dichotomy_dtwa_research(n_assumptions, d, solver,
t1, prev, state_based);
return res == a ? nullptr : res;
}
t1.stop("solve");
trace << "SAT, restarting from zero\n";
next = solution.second.empty() ? nullptr :
sat_build(solution.second, d, prev, state_based);
print_log(t1, d.cand_size - n_assumptions, next, solver); // SPOT_SATLOG.
if (next)
{
prev = next;
d = dict(prev);
d.cand_size = stats_reachable(prev).states - 1;
d.cand_nacc = target_acc_number;
d.cand_acc = target_acc;
if (d.cand_size == 0)
next = nullptr;
}
}
return prev == a ? nullptr : std::const_pointer_cast<spot::twa_graph>(prev);
}
twa_graph_ptr
dtwa_sat_minimize_incr(const const_twa_graph_ptr& a,
unsigned target_acc_number,
@ -1220,13 +1383,14 @@ namespace spot
("SAT-based minimization only works with deterministic automata");
bool dicho = om.get("dichotomy", 0);
bool incr = om.get("incr", 0);
bool assume = om.get("assume", 0);
int param = om.get("param", 0);
int states = om.get("states", -1);
int max_states = om.get("max-states", -1);
auto accstr = om.get_str("acc");
bool colored = om.get("colored", 0);
int preproc = om.get("preproc", 3);
bool incr = om.get("incr", 0);
int param = om.get("param", 0);
// No more om.get() below this.
om.report_unused_options();
@ -1323,6 +1487,11 @@ namespace spot
if (incr)
a = dtwa_sat_minimize_incr(a, nacc, target_acc, state_based,
max_states, colored, param);
else if (assume)
a = dtwa_sat_minimize_assume(a, nacc, target_acc, state_based,
max_states, colored, param);
else
a = (dicho ? dtwa_sat_minimize_dichotomy
: dtwa_sat_minimize)
@ -1332,6 +1501,10 @@ namespace spot
{
if (incr)
a = dtba_sat_minimize_incr(a, state_based, max_states, param);
else if (assume)
a = dtba_sat_minimize_assume(a, state_based, max_states, assume);
else
a = (dicho ? dtba_sat_minimize_dichotomy
: dtba_sat_minimize)