sat: skip reference transitions that are out of any cycle
* src/tgbaalgos/dtbasat.cc, src/tgbaalgos/dtgbasat.cc: Greatly reduce the number of clauses and variable by removing any path variable that reference a reference transition that is not in a SCC.
This commit is contained in:
parent
e9f60df857
commit
484c56c6ea
2 changed files with 397 additions and 346 deletions
|
|
@ -217,10 +217,12 @@ namespace spot
|
|||
int size_;
|
||||
bdd ap_;
|
||||
bool state_based_;
|
||||
scc_map& sm_;
|
||||
public:
|
||||
filler_dfs(const tgba* aut, dict& d, bdd ap, bool state_based)
|
||||
filler_dfs(const tgba* aut, dict& d, bdd ap, bool state_based,
|
||||
scc_map& sm)
|
||||
: tgba_reachable_iterator_depth_first(aut), d(d), ap_(ap),
|
||||
state_based_(state_based)
|
||||
state_based_(state_based), sm_(sm)
|
||||
{
|
||||
d.nvars = 0;
|
||||
}
|
||||
|
|
@ -237,14 +239,23 @@ namespace spot
|
|||
if (d.cand_size == -1)
|
||||
d.cand_size = size_ - 1;
|
||||
|
||||
int seen_size = seen.size();
|
||||
for (int i = 1; i <= seen_size; ++i)
|
||||
for (dict::state_map::const_iterator i2 = seen.begin();
|
||||
i2 != seen.end(); ++i2)
|
||||
{
|
||||
int i = i2->second;
|
||||
d.int_to_state[i] = i2->first;
|
||||
unsigned i_scc = sm_.scc_of_state(i2->first);
|
||||
|
||||
for (int j = 1; j <= d.cand_size; ++j)
|
||||
{
|
||||
d.prodid[state_pair(j, i)] = ++d.nvars;
|
||||
|
||||
for (int k = 1; k <= seen_size; ++k)
|
||||
for (dict::state_map::const_iterator k2 = seen.begin();
|
||||
k2 != seen.end(); ++k2)
|
||||
{
|
||||
int k = k2->second;
|
||||
if (sm_.scc_of_state(k2->first) != i_scc)
|
||||
continue;
|
||||
for (int l = 1; l <= d.cand_size; ++l)
|
||||
{
|
||||
path p(j, i, l, k);
|
||||
|
|
@ -253,11 +264,6 @@ namespace spot
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (dict::state_map::const_iterator i = seen.begin();
|
||||
i != seen.end(); ++i)
|
||||
{
|
||||
d.int_to_state[i->second] = i->first;
|
||||
}
|
||||
|
||||
std::swap(d.state_to_int, seen);
|
||||
|
|
@ -314,7 +320,7 @@ namespace spot
|
|||
|
||||
// Number all the SAT variable we may need.
|
||||
{
|
||||
filler_dfs f(ref, d, ap, state_based);
|
||||
filler_dfs f(ref, d, ap, state_based, sm);
|
||||
f.run();
|
||||
ref_size = f.size();
|
||||
}
|
||||
|
|
@ -450,11 +456,17 @@ namespace spot
|
|||
// construction of contraints (4,5) : all loops in the product
|
||||
// where no accepting run is detected in the ref. automaton,
|
||||
// must also be marked as not accepting in the cand. automaton
|
||||
for (int q1 = 1; q1 <= d.cand_size; ++q1)
|
||||
for (int q1p = 1; q1p <= ref_size; ++q1p)
|
||||
{
|
||||
for (int q2 = 1; q2 <= d.cand_size; ++q2)
|
||||
unsigned q1p_scc = sm.scc_of_state(d.int_to_state[q1p]);
|
||||
for (int q2p = 1; q2p <= ref_size; ++q2p)
|
||||
{
|
||||
// We are only interested in transition that can form a
|
||||
// cycle, so they must belong to the same SCC.
|
||||
if (sm.scc_of_state(d.int_to_state[q2p]) != q1p_scc)
|
||||
continue;
|
||||
for (int q1 = 1; q1 <= d.cand_size; ++q1)
|
||||
for (int q2 = 1; q2 <= d.cand_size; ++q2)
|
||||
{
|
||||
path p1(q1, q1p, q2, q2p);
|
||||
|
||||
|
|
@ -463,12 +475,20 @@ namespace spot
|
|||
|
||||
int pid1 = d.pathid_ref[p1];
|
||||
|
||||
tgba_succ_iterator* it = ref->succ_iter(d.int_to_state[q2p]);
|
||||
tgba_succ_iterator* it =
|
||||
ref->succ_iter(d.int_to_state[q2p]);
|
||||
for (it->first(); !it->done(); it->next())
|
||||
{
|
||||
const state* dps = it->current_state();
|
||||
// Skip destinations not in the SCC.
|
||||
if (sm.scc_of_state(dps) != q1p_scc)
|
||||
{
|
||||
dps->destroy();
|
||||
continue;
|
||||
}
|
||||
int dp = d.state_to_int[dps];
|
||||
dps->destroy();
|
||||
|
||||
if (it->current_acceptance_conditions() == all_acc)
|
||||
continue;
|
||||
for (int q3 = 1; q3 <= d.cand_size; ++q3)
|
||||
|
|
@ -523,25 +543,38 @@ namespace spot
|
|||
delete it;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// construction of contraints (6,7): all loops in the product
|
||||
// where accepting run is detected in the ref. automaton, must
|
||||
// also be marked as accepting in the candidate.
|
||||
for (int q1 = 1; q1 <= d.cand_size; ++q1)
|
||||
for (int q1p = 1; q1p <= ref_size; ++q1p)
|
||||
{
|
||||
for (int q2 = 1; q2 <= d.cand_size; ++q2)
|
||||
unsigned q1p_scc = sm.scc_of_state(d.int_to_state[q1p]);
|
||||
for (int q2p = 1; q2p <= ref_size; ++q2p)
|
||||
{
|
||||
// We are only interested in transition that can form a
|
||||
// cycle, so they must belong to the same SCC.
|
||||
if (sm.scc_of_state(d.int_to_state[q2p]) != q1p_scc)
|
||||
continue;
|
||||
for (int q1 = 1; q1 <= d.cand_size; ++q1)
|
||||
for (int q2 = 1; q2 <= d.cand_size; ++q2)
|
||||
{
|
||||
path p1(q1, q1p, q2, q2p);
|
||||
dout << "(6&7) matching paths from candidate based on "
|
||||
<< p1 << "\n";
|
||||
int pid1 = d.pathid_cand[p1];
|
||||
|
||||
tgba_succ_iterator* it = ref->succ_iter(d.int_to_state[q2p]);
|
||||
tgba_succ_iterator* it =
|
||||
ref->succ_iter(d.int_to_state[q2p]);
|
||||
for (it->first(); !it->done(); it->next())
|
||||
{
|
||||
const state* dps = it->current_state();
|
||||
// Skip destinations not in the SCC.
|
||||
if (sm.scc_of_state(dps) != q1p_scc)
|
||||
{
|
||||
dps->destroy();
|
||||
continue;
|
||||
}
|
||||
int dp = d.state_to_int[dps];
|
||||
dps->destroy();
|
||||
for (int q3 = 1; q3 <= d.cand_size; q3++)
|
||||
|
|
@ -601,7 +634,7 @@ namespace spot
|
|||
delete it;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
out.seekp(0);
|
||||
out << "p cnf " << d.nvars << " " << nclauses;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -298,10 +298,12 @@ namespace spot
|
|||
int size_;
|
||||
bdd ap_;
|
||||
bool state_based_;
|
||||
scc_map& sm_;
|
||||
public:
|
||||
filler_dfs(const tgba* aut, dict& d, bdd ap, bool state_based)
|
||||
filler_dfs(const tgba* aut, dict& d, bdd ap, bool state_based,
|
||||
scc_map& sm)
|
||||
: tgba_reachable_iterator_depth_first(aut), d(d), ap_(ap),
|
||||
state_based_(state_based)
|
||||
state_based_(state_based), sm_(sm)
|
||||
{
|
||||
d.nvars = 0;
|
||||
|
||||
|
|
@ -363,15 +365,22 @@ namespace spot
|
|||
if (d.cand_size == -1)
|
||||
d.cand_size = size_ - 1;
|
||||
|
||||
int seen_size = seen.size();
|
||||
for (int i = 1; i <= seen_size; ++i)
|
||||
for (dict::state_map::const_iterator i2 = seen.begin();
|
||||
i2 != seen.end(); ++i2)
|
||||
{
|
||||
int i = i2->second;
|
||||
d.int_to_state[i] = i2->first;
|
||||
unsigned i_scc = sm_.scc_of_state(i2->first);
|
||||
for (int j = 1; j <= d.cand_size; ++j)
|
||||
{
|
||||
d.prodid[state_pair(j, i)] = ++d.nvars;
|
||||
|
||||
|
||||
for (int k = 1; k <= seen_size; ++k)
|
||||
for (dict::state_map::const_iterator k2 = seen.begin();
|
||||
k2 != seen.end(); ++k2)
|
||||
{
|
||||
int k = k2->second;
|
||||
if (sm_.scc_of_state(k2->first) != i_scc)
|
||||
continue;
|
||||
for (int l = 1; l <= d.cand_size; ++l)
|
||||
{
|
||||
size_t sf = d.all_cand_acc.size();
|
||||
|
|
@ -390,10 +399,7 @@ namespace spot
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (dict::state_map::const_iterator i = seen.begin();
|
||||
i != seen.end(); ++i)
|
||||
d.int_to_state[i->second] = i->first;
|
||||
}
|
||||
|
||||
std::swap(d.state_to_int, seen);
|
||||
|
||||
|
|
@ -491,7 +497,7 @@ namespace spot
|
|||
|
||||
// Number all the SAT variable we may need.
|
||||
{
|
||||
filler_dfs f(ref, d, ap, state_based);
|
||||
filler_dfs f(ref, d, ap, state_based, sm);
|
||||
f.run();
|
||||
ref_size = f.size();
|
||||
}
|
||||
|
|
@ -623,10 +629,17 @@ namespace spot
|
|||
bdd all_acc = ref->all_acceptance_conditions();
|
||||
|
||||
// construction of constraints (11,12,13)
|
||||
for (int q1 = 1; q1 <= d.cand_size; ++q1)
|
||||
for (int q1p = 1; q1p <= ref_size; ++q1p)
|
||||
for (int q2 = 1; q2 <= d.cand_size; ++q2)
|
||||
{
|
||||
unsigned q1p_scc = sm.scc_of_state(d.int_to_state[q1p]);
|
||||
for (int q2p = 1; q2p <= ref_size; ++q2p)
|
||||
{
|
||||
// We are only interested in transition that can form a
|
||||
// cycle, so they must belong to the same SCC.
|
||||
if (sm.scc_of_state(d.int_to_state[q2p]) != q1p_scc)
|
||||
continue;
|
||||
for (int q1 = 1; q1 <= d.cand_size; ++q1)
|
||||
for (int q2 = 1; q2 <= d.cand_size; ++q2)
|
||||
{
|
||||
size_t sf = d.all_cand_acc.size();
|
||||
size_t sfp = d.all_ref_acc.size();
|
||||
|
|
@ -646,13 +659,20 @@ namespace spot
|
|||
for (it->first(); !it->done(); it->next())
|
||||
{
|
||||
const state* dps = it->current_state();
|
||||
// Skip destinations not in the SCC.
|
||||
if (sm.scc_of_state(dps) != q1p_scc)
|
||||
{
|
||||
dps->destroy();
|
||||
continue;
|
||||
}
|
||||
int dp = d.state_to_int[dps];
|
||||
dps->destroy();
|
||||
|
||||
for (int q3 = 1; q3 <= d.cand_size; ++q3)
|
||||
{
|
||||
bdd all = it->current_condition();
|
||||
bdd curacc = it->current_acceptance_conditions();
|
||||
bdd curacc =
|
||||
it->current_acceptance_conditions();
|
||||
|
||||
while (all != bddfalse)
|
||||
{
|
||||
|
|
@ -749,9 +769,6 @@ namespace spot
|
|||
<< " " << tai << " 0\n";
|
||||
++nclauses;
|
||||
}
|
||||
// out << -pid << " " << -ti
|
||||
// << " " << pcompid << " 0\n";
|
||||
// ++nclauses;
|
||||
}
|
||||
}
|
||||
// (13) augmenting paths (always).
|
||||
|
|
@ -827,7 +844,8 @@ namespace spot
|
|||
delete it;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
out.seekp(0);
|
||||
out << "p cnf " << d.nvars << " " << nclauses;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue