satmin: cleanup interfaces and minimization loops

* src/tgbaalgos/dtbasat.cc, src/tgbaalgos/dtbasat.hh:
(dtba_sat_minimize): Split into...
(dtba_sat_synthetize, dtba_sat_minimize): These.
(dtba_sat_minimize_dichotomy): New function.
* src/tgbaalgos/dtgbasat.cc, src/tgbaalgos/dtgbasat.hh
(dtgba_sat_minimize, dtgba_sat_synthetize): Likewise.
* src/tgbatest/ltl2tgba.cc: Adjust to new interface.
* src/tgbaalgos/postproc.cc, src/tgbaalgos/postproc.hh:
Cleanup option processing for SAT options.
* src/tgbatest/satmin.test: Adjust.
* src/bin/spot-x.cc, src/bin/man/spot-x.x, NEWS: Document.
This commit is contained in:
Alexandre Duret-Lutz 2013-08-22 15:49:30 +02:00
parent b09ef5bea9
commit fdb157bf94
11 changed files with 393 additions and 222 deletions

8
NEWS
View file

@ -58,6 +58,14 @@ New in spot 1.1.4a (not relased)
number of seconds spent building the output automaton (excluding
the time spent parsing the input).
- ltl2tgba and dstar2tgba can use a SAT-solver to minimize
deterministic automata. Doing so is only needed on properties
that are stronger than obligations (for which our
WDBA-minimization procedure will return a minimimal
deterministic automaton more efficiently) and is disabled by
default. See the spot-x(7) man page for documentation about the
related options: sat-minimize, sat-states, sat-acc, state-based.
* All the parsers implemented in Spot now use the same type
to store locations.

View file

@ -1,11 +1,39 @@
[NAME]
spot-x \- Common fine-tuning options.
[SYNOPSIS]
.B \-\-extra-options STRING
.br
.B \-x STRING
[DESCRIPTION]
.\" Add any additional description here
[ENVIRONMENT VARIABLES]
.TP
\fBSPOT_SATSOLVER\fR
If set, this variable should indicate how to call a SAT\-solver. This
is used by the sat\-minimize option described above. The default value
is \f(CW"glucose %I >%O"\fR. The escape sequences \f(CW%I\fR and \f(CW%O\fR
respectively denote the names of the input and output files. These
temporary files are created in the directory specified by \fBSPOT_TMPDIR\fR
or \fBTMPDIR\fR (see below).
.TP
\fBSPOT_TMPDIR\fR, \fBTMPDIR\fR
These variables control in which directory temporary files (e.g.,
those who contain the input and output when interfacing with
translators) are created. \fBTMPDIR\fR is only read if
\fBSPOT_TMPDIR\fR does not exist. If none of these environment
variables exist, or if their value is empty, files are created in the
current directory.
.TP
\fBSPOT_TMPKEEP\fR
When this variable is defined, temporary files are not removed.
This is mostly useful for debugging.
[BIBLIOGRAPHY]
.TP
1.
@ -13,7 +41,10 @@ Christian Dax, Jochen Eisinger, Felix Klaedtke: Mechanizing the
Powerset Construction for Restricted Classes of
ω-Automata. Proceedings of ATVA'07. LNCS 4762.
Describes the WDBA-minimization algorithm implemented in Spot.
Describes the WDBA-minimization algorithm implemented in Spot. The
algorithm used for the tba-det options is also a generalization (to
TBA instead of BA) of what they describe in sections 3.2 and 3.3.
.TP
2.
Tomáš Babiak, Thomas Badie, Alexandre Duret-Lutz, Mojmír Křetínský,
@ -23,6 +54,14 @@ Improvements to LTL Translation. Proceedings of SPIN'13. LNCS 7976.
Describes the compositional suspension, the simulation-based
reductions, and the SCC-based simplifications.
.TP
3.
Rüdiger Ehlers: Minimising Deterministic Büchi Automata Precisely using
SAT Solving. Proceedings of SAT'10. LNCS 6175.
Our SAT-based minimization procedures are generalizations of this
paper to deal with TBA or TGBA.
[SEE ALSO]
.BR ltl2tgba (1)
.BR ltl2tgta (1)

View file

@ -1,3 +1,4 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2013 Laboratoire de Recherche et Développement
// de l'Epita (LRDE).
@ -92,6 +93,37 @@ simulation. Set to 3 to iterate both direct and reverse simulations. \
The default is 3 in --high mode, and 0 otherwise.") },
{ DOC("wdba-minimize", "Set to 0 to disable WDBA-minimization. \
Enabled by default.") },
{ DOC("tba-det", "Set to 1 to attempt a powerset determinization \
if the TGBA is not already deterministic. Doing so will degeneralize \
the automaton. This is disabled by default, unless sat-minimize is set.") },
{ DOC("sat-minimize",
"Set to 1 to enable SAT-based minimization of deterministic \
TGBA: it starts with the number of states of the input, and iteratively \
tries to find a deterministic TGBA with one less state. Set to 2 to perform \
a binary search instead. Disabled (0) by default. The sat solver to use \
can be set with the SPOT_SATSOLVER environment variable (see below). By \
default the procedure looks for a TGBA with the same number of acceptance \
set; this can be changed with the sat-acc option, or of course by using -B \
to construct a Büchi automaton. Enabling SAT-based minimization will \
also enable tba-det.") },
{ DOC("sat-states",
"When this is set to some positive integer, the SAT-based \
minimization will attempt to construct a TGBA with the given number of \
states. It may however return an automaton with less states if some of \
these are unreachable or useless. Setting sat-states automatically \
enables sat-minimize, but no iteration is performed. If no equivalent \
automaton could be constructed with the given number of states, the original \
automaton is returned.") },
{ DOC("sat-acc",
"When this is set to some positive integer, the SAT-based will \
attempt to construct a TGBA with the given number of acceptance sets. \
states. It may however return an automaton with less acceptance sets if \
some of these are useless. Setting sat-acc automatically \
sets sat-minimize to 1 if not set differently.") },
{ DOC("state-based",
"Set to 1 to instruct the SAT-minimization procedure to produce \
a TGBA where all outgoing transition of a state have the same acceptance \
sets. By default this is only enabled when option -B is used.") },
{ 0, 0, 0, 0, 0, 0 }
};

View file

@ -51,8 +51,10 @@
#define DEBUG 0
#if DEBUG
#define dout out << "c "
#define trace std::cerr
#else
#define dout while (0) out
#define dout while (0) std::cout
#define trace dout
#endif
namespace spot
@ -317,8 +319,32 @@ namespace spot
#if DEBUG
debug_dict = ref->get_dict();
dout << "ref_size: " << ref_size << "\n";
dout << "cand_size: " << d.cand_size << "\n";
#endif
// dout << "symmetry-breaking clauses\n";
// int k = 1;
// bdd all = bddtrue;
// while (all != bddfalse)
// {
// bdd s = bdd_satoneset(all, ap, bddfalse);
// all -= s;
// for (int q1 = 1; q1 < d.cand_size; ++q1)
// for (int q2 = q1 + 2; q2 <= d.cand_size; ++q2)
// if ((q1 - 1) * d.cand_size + q2 + 2 <= k)
// {
// transition t(q1, s, q2);
// int ti = d.transid[t];
// dout << "¬" << t << "\n";
// out << -ti << " 0\n";
// ++nclauses;
// }
// ++k;
// }
// if (!nclauses)
// dout << "(none)\n";
dout << "(1) the candidate automaton is complete\n";
for (int q1 = 1; q1 <= d.cand_size; ++q1)
{
@ -712,38 +738,20 @@ namespace spot
}
tgba_explicit_number*
dtba_sat_minimize(const tgba* a, int target_state_number,
dtba_sat_synthetize(const tgba* a, int target_state_number,
bool state_based)
{
int ref_states =
target_state_number == -1
? stats_reachable(a).states - 1
: target_state_number;
std::string current_solution;
std::string last_solution;
dict* last = 0;
trace << "dtba_sat_synthetize(..., states = " << target_state_number
<< ", state_based = " << state_based << ")\n";
std::string solution;
dict* current = 0;
temporary_file* cnf = 0;
temporary_file* out = 0;
do
{
if (DEBUG && current)
{
xrename(out->name(), "dtba-sat.out");
xrename(cnf->name(), "dtba-sat.cnf");
}
delete out;
delete cnf;
std::swap(current_solution, last_solution);
delete last;
last = current;
current = new dict;
current->cand_size = ref_states--;
current->cand_size = target_state_number;
cnf = create_tmpfile("dtba-sat-", ".cnf");
std::fstream cnfs(cnf->name(),
std::ios_base::trunc | std::ios_base::out);
dtba_to_sat(cnfs, a, *current, state_based);
@ -751,47 +759,68 @@ namespace spot
out = create_tmpfile("dtba-sat-", ".out");
satsolver(cnf, out);
current_solution = get_solution(out->name());
}
while (target_state_number == -1 && !current_solution.empty());
if (target_state_number != -1)
{
std::swap(current_solution, last_solution);
if (last_solution.empty())
{
last = 0;
delete current;
}
else
{
last = current;
}
}
else
{
delete current;
}
solution = get_solution(out->name());
tgba_explicit_number* res = 0;
if (!solution.empty())
res = sat_build(solution, *current, a, state_based);
delete current;
tgba_explicit_number* res;
if (last == 0)
{
res = 0;
if (DEBUG)
{
xrename(out->name(), "dtba-sat.out");
xrename(cnf->name(), "dtba-sat.cnf");
}
}
else
{
res = sat_build(last_solution, *last, a, state_based);
delete last;
}
delete out;
delete cnf;
trace << "dtba_sat_synthetize(...) = " << res << "\n";
return res;
}
tgba_explicit_number*
dtba_sat_minimize(const tgba* a, bool state_based)
{
int n_states = stats_reachable(a).states;
tgba_explicit_number* prev = 0;
for (;;)
{
tgba_explicit_number* next =
dtba_sat_synthetize(prev ? prev : a, --n_states, state_based);
if (next == 0)
break;
delete prev;
prev = next;
}
return prev;
}
tgba_explicit_number*
dtba_sat_minimize_dichotomy(const tgba* a, bool state_based)
{
int max_states = stats_reachable(a).states - 1;
int min_states = 1;
tgba_explicit_number* prev = 0;
while (min_states <= max_states)
{
int target = (max_states + min_states) / 2;
tgba_explicit_number* next =
dtba_sat_synthetize(prev ? prev : a, target, state_based);
if (next == 0)
{
min_states = target + 1;
}
else
{
delete prev;
prev = next;
max_states = target - 1;
}
}
return prev;
}
}

View file

@ -20,32 +20,47 @@
#ifndef SPOT_TGBAALGOS_DTBASAT_HH
# define SPOT_TGBAALGOS_DTBASAT_HH
#include <iosfwd>
#include "tgba/tgba.hh"
#include "tgba/tgbaexplicit.hh"
namespace spot
{
/// \brief Attempt to reduce a deterministic TBA with a SAT solver.
/// \brief Attempt to synthetize an equivalent deterministic TBA
/// with a SAT solver.
///
/// \param a the TGBA to reduce. It should have only one acceptance
/// \param a the input TGBA. It should have only one acceptance
/// set and be deterministic. I.e., it should be a deterministic TBA.
///
/// \param target_state_number the expected number of states wanted
/// in the resulting automaton. If \a target_state_number is left
/// to its default value of -1, this function will attempt to build
/// the smallest possible deterministic TBA is can produce.
/// \param target_state_number the desired number of states wanted
/// in the resulting automaton. The result may have less than \a
/// target_state_number reachable states.
///
/// \param state_based set to true to force all outgoing transitions
/// of a state to share the same acceptance condition, effectively
/// turning the TBA into a BA.
///
/// If no automaton with \a target_state_number states is found, or
/// (in case <code>target_state_number == -1</code>) if no smaller
/// automaton is found, then a null pointer is returned.
/// If no equivalent deterministic TBA with \a target_state_number
/// states is found, a null pointer
SPOT_API tgba_explicit_number*
dtba_sat_minimize(const tgba* a, int target_state_number = -1,
dtba_sat_synthetize(const tgba* a, int target_state_number,
bool state_based = false);
/// \brief Attempt to minimize a deterministic TBA with a SAT solver.
///
/// This calls dtba_sat_synthetize() in a loop, with a decreasing
/// number of states, and returns the last successfully built TBA.
///
/// If no smaller TBA exist, this returns a null pointer.
SPOT_API tgba_explicit_number*
dtba_sat_minimize(const tgba* a, bool state_based = false);
/// \brief Attempt to minimize a deterministic TBA with a SAT solver.
///
/// This calls dtba_sat_synthetize() in a loop, but attempting to
/// find the minimum number of states using a binary search.
//
/// If no smaller TBA exist, this returns a null pointer.
SPOT_API tgba_explicit_number*
dtba_sat_minimize_dichotomy(const tgba* a, bool state_based = false);
}
#endif // SPOT_TGBAALGOS_DTBASAT_HH

View file

@ -52,16 +52,16 @@
#define DEBUG 0
#if DEBUG
#define dout out << "c "
#define trace std::cerr
#else
#define dout while (0) out
#define dout while (0) std::cout
#define trace dout
#endif
namespace spot
{
namespace
{
static bdd_dict* debug_dict = 0;
struct transition
@ -477,9 +477,6 @@ namespace spot
sm.build_map();
bdd ap = sm.aprec_set_of(sm.initial());
#if DEBUG
debug_dict = ref->get_dict();
#endif
// Number all the SAT variable we may need.
{
@ -488,6 +485,12 @@ namespace spot
ref_size = f.size();
}
#if DEBUG
debug_dict = ref->get_dict();
dout << "ref_size: " << ref_size << "\n";
dout << "cand_size: " << d.cand_size << "\n";
#endif
// empty automaton is impossible
if (d.cand_size == 0)
{
@ -937,39 +940,22 @@ namespace spot
}
tgba_explicit_number*
dtgba_sat_minimize(const tgba* a, unsigned cand_nacc,
dtgba_sat_synthetize(const tgba* a, unsigned target_acc_number,
int target_state_number, bool state_based)
{
int ref_states =
target_state_number == -1
? stats_reachable(a).states - 1
: target_state_number;
std::string current_solution;
std::string last_solution;
dict* last = 0;
trace << "dtgba_sat_synthetize(..., acc = " << target_acc_number
<< ", states = " << target_state_number
<< ", state_based = " << state_based << ")\n";
std::string solution;
dict* current = 0;
temporary_file* cnf = 0;
temporary_file* out = 0;
do
{
if (DEBUG && current)
{
xrename(out->name(), "dtgba-sat.out");
xrename(cnf->name(), "dtgba-sat.cnf");
}
delete out;
delete cnf;
std::swap(current_solution, last_solution);
delete last;
last = current;
current = new dict(a);
current->cand_size = ref_states--;
current->cand_nacc = cand_nacc;
current->cand_size = target_state_number;
current->cand_nacc = target_acc_number;
cnf = create_tmpfile("dtgba-sat-", ".cnf");
std::fstream cnfs(cnf->name(),
std::ios_base::trunc | std::ios_base::out);
dtgba_to_sat(cnfs, a, *current, state_based);
@ -977,47 +963,73 @@ namespace spot
out = create_tmpfile("dtgba-sat-", ".out");
satsolver(cnf, out);
current_solution = get_solution(out->name());
}
while (target_state_number == -1 && !current_solution.empty());
if (target_state_number != -1)
{
std::swap(current_solution, last_solution);
if (last_solution.empty())
{
last = 0;
delete current;
}
else
{
last = current;
}
}
else
{
delete current;
}
solution = get_solution(out->name());
tgba_explicit_number* res = 0;
if (!solution.empty())
res = sat_build(solution, *current, a, state_based);
delete current;
tgba_explicit_number* res;
if (last == 0)
{
res = 0;
if (DEBUG)
{
xrename(out->name(), "dtgba-sat.out");
xrename(cnf->name(), "dtgba-sat.cnf");
}
}
else
{
res = sat_build(last_solution, *last, a, state_based);
delete last;
}
delete out;
delete cnf;
trace << "dtgba_sat_synthetize(...) = " << res << "\n";
return res;
}
tgba_explicit_number*
dtgba_sat_minimize(const tgba* a, unsigned target_acc_number,
bool state_based)
{
int n_states = stats_reachable(a).states;
tgba_explicit_number* prev = 0;
for (;;)
{
tgba_explicit_number* next =
dtgba_sat_synthetize(prev ? prev : a, target_acc_number,
--n_states, state_based);
if (next == 0)
break;
delete prev;
prev = next;
}
return prev;
}
tgba_explicit_number*
dtgba_sat_minimize_dichotomy(const tgba* a, unsigned target_acc_number,
bool state_based)
{
int max_states = stats_reachable(a).states - 1;
int min_states = 1;
tgba_explicit_number* prev = 0;
while (min_states <= max_states)
{
int target = (max_states + min_states) / 2;
tgba_explicit_number* next =
dtgba_sat_synthetize(prev ? prev : a, target_acc_number, target,
state_based);
if (next == 0)
{
min_states = target + 1;
}
else
{
delete prev;
prev = next;
max_states = target - 1;
}
}
return prev;
}
}

View file

@ -20,35 +20,53 @@
#ifndef SPOT_TGBAALGOS_DTGBASAT_HH
# define SPOT_TGBAALGOS_DTGBASAT_HH
#include <iosfwd>
#include "tgba/tgba.hh"
#include "tgba/tgbaexplicit.hh"
namespace spot
{
/// \brief Attempt to reduce a deterministic TGBA with a SAT solver.
/// \brief Attempt to synthetize am equivalent deterministic TGBA
/// with a SAT solver.
///
/// \param a the TGBA to reduce. It should have only one acceptance
/// set and be deterministic. I.e., it should be a deterministic TBA.
/// \param a the input TGBA. It should be a deterministic TGBA.
///
/// \param cand_nacc is the number of acceptance sets in the result.
/// \param target_acc_number is the number of acceptance sets wanted
/// in the result.
///
/// \param target_state_number is the desired number of states in
/// the result. The output may have less than \a
/// target_state_number reachable states.
///
/// \param state_based set to true to force all outgoing transitions
/// of a state to share the same acceptance conditions, effectively
/// turning the TGBA into a TBA.
///
/// \param target_state_number the expected number of states wanted
/// in the resulting automaton. If \a target_state_number is left
/// to its default value of -1, this function will attempt to build
/// the smallest possible deterministic TGBA is can produce.
///
/// This functions attempts to find a TGBA with \a cand_nacc
/// This functions attempts to find a TGBA with \a target_acc_number
/// acceptance sets and target_state_number states that is
/// equivalent to \a a. If no such TGBA is found, a null pointer is
/// returned.
SPOT_API tgba_explicit_number*
dtgba_sat_minimize(const tgba* a, unsigned cand_nacc,
int target_state_number = -1,
dtgba_sat_synthetize(const tgba* a, unsigned target_acc_number,
int target_state_number,
bool state_based = false);
/// \brief Attempt to minimize a deterministic TGBA with a SAT solver.
///
/// This calls dtgba_sat_synthetize() in a loop, with a decreasing
/// number of states, and returns the last successfully built TGBA.
///
/// If no smaller TGBA exist, this returns a null pointer.
SPOT_API tgba_explicit_number*
dtgba_sat_minimize(const tgba* a, unsigned target_acc_number,
bool state_based = false);
/// \brief Attempt to minimize a deterministic TGBA with a SAT solver.
///
/// This calls dtgba_sat_synthetize() in a loop, but attempting to
/// find the minimum number of states using a binary search.
//
/// If no smaller TBA exist, this returns a null pointer.
SPOT_API tgba_explicit_number*
dtgba_sat_minimize_dichotomy(const tgba* a, unsigned target_acc_number,
bool state_based = false);
}

View file

@ -51,15 +51,24 @@ namespace spot
scc_filter_ = opt->get("scc-filter", -1);
ba_simul_ = opt->get("ba-simul", -1);
tba_determinisation_ = opt->get("tba-det", 0);
dtba_sat_minimize_ = opt->get("dtba-sat-minimize", -1);
dtgba_sat_minimize_ = opt->get("dtgba-sat-minimize", -1);
dtgba_sat_minimize_acc_ = opt->get("dtgba-sat-minimize-acc", -1);
if (dtgba_sat_minimize_ >= 0 && dtgba_sat_minimize_acc_ == -1)
dtgba_sat_minimize_acc_ = 0;
if (dtgba_sat_minimize_ == -1 && dtgba_sat_minimize_acc_ >= 0)
dtgba_sat_minimize_ = 0;
sat_minimize_ = opt->get("sat-minimize", 0);
sat_states_ = opt->get("sat-states", 0);
sat_acc_ = opt->get("sat-acc", 0);
state_based_ = opt->get("state-based", 0);
wdba_minimize_ = opt->get("wdba-minimize", 1);
if (sat_acc_ && sat_minimize_ == 0)
sat_minimize_ = 1; // 2?
if (sat_states_ && sat_minimize_ == 0)
sat_minimize_ = 1;
if (sat_minimize_)
{
tba_determinisation_ = 1;
if (sat_acc_ <= 0)
sat_acc_ = -1;
if (sat_states_ <= 0)
sat_states_ = -1;
}
}
}
@ -128,6 +137,8 @@ namespace spot
ba_simul_ = (level_ == High) ? 3 : 0;
if (scc_filter_ < 0)
scc_filter_ = 1;
if (type_ == BA)
state_based_ = true;
// Remove useless SCCs.
if (type_ == Monitor)
@ -198,6 +209,7 @@ namespace spot
bool dba_is_minimal = false;
const tgba* dba = 0;
const tgba* sim = 0;
int original_acc = a->number_of_acceptance_conditions();
// (Small,Low) is the only configuration where we do not run
// WDBA-minimization.
@ -287,56 +299,60 @@ namespace spot
// that case dba_is_wdba=true), or some deterministic automaton
// that is either the result of the simulation or of the
// TBA-determinization (dba_is_wdba=false in both cases).
// Attempt SAT-minimization if requested.
if (dtba_sat_minimize_ >= 0 && dba && !dba_is_wdba)
if (sat_minimize_ && dba && !dba_is_wdba)
{
// This only work on deterministic TBA, so degeneralize
// if needed.
const tgba* tmpd = 0;
if (dba->number_of_acceptance_conditions() != 1)
unsigned target_acc;
if (type_ == BA)
target_acc = 1;
else if (sat_acc_ != -1)
target_acc = sat_acc_;
else
// Take the number of acceptance conditions from the input
// automaton, not from dba, because dba has always one.
target_acc = original_acc;
const tgba* in = 0;
const tgba* to_free = 0;
if (target_acc == 1)
{
// If we are seeking a minimal DBA with unknown number of
// states, then we should start from the degeneralized,
// because the input TBA might be smaller.
if (state_based_ && dtba_sat_minimize_ == 0)
tmpd = degeneralize(dba);
if (state_based_)
to_free = in = degeneralize(dba);
else if (dba->number_of_acceptance_conditions() != 1)
to_free = in = new tgba_tba_proxy(dba);
else
tmpd = new tgba_tba_proxy(dba);
in = dba;
}
else
{
in = dba;
}
const tgba* in = tmpd ? tmpd : dba;
const tgba* cmp = tgba_complete(in);
const tgba* res = dtba_sat_minimize(cmp,
dtba_sat_minimize_ == 0
? -1 : dtba_sat_minimize_,
state_based_);
delete cmp;
delete tmpd;
if (res != 0)
const tgba* res = 0;
if (target_acc == 1)
{
delete dba;
if (state_based_)
dba = scc_filter_states(res);
if (sat_states_ != -1)
res = dtba_sat_synthetize(cmp, sat_states_, state_based_);
else if (sat_minimize_ == 1)
res = dtba_sat_minimize(cmp, state_based_);
else // sat_minimize_ == 2
res = dtba_sat_minimize_dichotomy(cmp, state_based_);
}
else
dba = scc_filter(res, true);
delete res;
dba_is_minimal = true;
}
}
else if (dtgba_sat_minimize_ >= 0 && dba && !dba_is_wdba)
{
const tgba* cmp = tgba_complete(dba);
const tgba* res =
dtgba_sat_minimize(cmp,
dtgba_sat_minimize_acc_
? dtgba_sat_minimize_acc_
: dba->number_of_acceptance_conditions(),
dtgba_sat_minimize_ == 0
? -1 : dtgba_sat_minimize_,
if (sat_states_ != -1)
res = dtgba_sat_synthetize(cmp, target_acc, sat_states_,
state_based_);
else if (sat_minimize_ == 1)
res = dtgba_sat_minimize(cmp, target_acc, state_based_);
else // sat_minimize_ == 2
res = dtgba_sat_minimize_dichotomy(cmp, target_acc, state_based_);
}
delete cmp;
delete to_free;
if (res != 0)
{
delete dba;
@ -353,10 +369,11 @@ namespace spot
}
}
// Degeneralize the dba resulting from tba-determinization
// or sat-minimization (which is a TBA) if requested.
if (dba && !dba_is_wdba && type_ == BA)
// Degeneralize the dba resulting from tba-determinization or
// sat-minimization (which is a TBA) if requested and needed.
if (dba && !dba_is_wdba && type_ == BA
&& !(dba_is_minimal && state_based_
&& dba->number_of_acceptance_conditions() == 1))
{
const tgba* d = degeneralize(dba);
delete dba;

View file

@ -106,9 +106,9 @@ namespace spot
int scc_filter_;
int ba_simul_;
bool tba_determinisation_;
int dtba_sat_minimize_;
int dtgba_sat_minimize_;
int dtgba_sat_minimize_acc_;
int sat_minimize_;
int sat_acc_;
int sat_states_;
bool state_based_;
bool wdba_minimize_;
};

View file

@ -1528,7 +1528,7 @@ main(int argc, char** argv)
if (opt_dtbasat >= 0)
{
tm.start("dtbasat");
satminimized = dtba_sat_minimize(a, opt_dtbasat);
satminimized = dtba_sat_synthetize(a, opt_dtbasat);
tm.stop("dtbasat");
if (satminimized)
a = satminimized;

View file

@ -89,8 +89,9 @@ $ltlcross -F formulas \
--timeout=60 \
"$ltl2tgba --det --lbtt %f >%T" \
"$ltl2tgba --det --lbtt -x tba-det %f >%T" \
"$ltl2tgba --det --lbtt -x tba-det,dtba-sat-minimize=0 %f >%T" \
"$ltl2tgba --det --lbtt -x tba-det,dtgba-sat-minimize-acc=0 %f >%T" \
"$ltl2tgba --det --lbtt -x dtgba-sat-minimize-acc=0 %f >%T" \
"$ltl2tgba --det --lbtt -x tba-det,dtgba-sat-minimize-acc=3 %f >%T" \
"$ltl2tgba --det --lbtt -x sat-acc=1 %f >%T" \
"$ltl2tgba --det --lbtt -x sat-acc=3 %f >%T" \
"$ltl2tgba --det --lbtt -x sat-states=3 %f >%T" \
"$ltl2tgba --det --lbtt -x sat-minimize %f >%T" \
"$ltl2tgba --det --lbtt -x sat-minimize=2 %f >%T" \
--json=det.json