mealy: improve error reporting
* spot/twaalgos/mealy_machine.cc: Add more exceptions. * tests/python/except.py: Test them.
This commit is contained in:
parent
fafe40c530
commit
5c5133348e
2 changed files with 86 additions and 28 deletions
|
|
@ -100,7 +100,8 @@ namespace
|
||||||
, f{std::fopen(name.c_str(), "a")}
|
, f{std::fopen(name.c_str(), "a")}
|
||||||
{
|
{
|
||||||
if (!f)
|
if (!f)
|
||||||
throw std::runtime_error("File could not be oppened for writing.");
|
throw std::runtime_error("`" + name +
|
||||||
|
"' could not be oppened for writing.");
|
||||||
}
|
}
|
||||||
~fwrapper()
|
~fwrapper()
|
||||||
{
|
{
|
||||||
|
|
@ -120,21 +121,36 @@ namespace
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static bdd
|
||||||
|
ensure_mealy(const char* function_name,
|
||||||
|
const const_twa_graph_ptr& m)
|
||||||
|
{
|
||||||
|
if (SPOT_UNLIKELY(!m->acc().is_t()))
|
||||||
|
throw std::runtime_error(std::string(function_name) +
|
||||||
|
"(): Mealy machines must have "
|
||||||
|
"true acceptance condition");
|
||||||
|
bdd* out = m->get_named_prop<bdd>("synthesis-outputs");
|
||||||
|
if (SPOT_UNLIKELY(!out))
|
||||||
|
throw std::runtime_error(std::string(function_name) +
|
||||||
|
"(): \"synthesis-outputs\" not defined");
|
||||||
|
return *out;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_mealy(const const_twa_graph_ptr& m)
|
is_mealy(const const_twa_graph_ptr& m)
|
||||||
{
|
{
|
||||||
if (!m->acc().is_t())
|
if (!m->acc().is_t())
|
||||||
{
|
{
|
||||||
trace << "is_mealy(): Mealy machines must have "
|
trace << "is_mealy(): Mealy machines must have "
|
||||||
"true acceptance condition.\n";
|
"true acceptance condition.\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m->get_named_prop<bdd>("synthesis-outputs"))
|
if (!m->get_named_prop<bdd>("synthesis-outputs"))
|
||||||
{
|
{
|
||||||
trace << "is_mealy(): \"synthesis-outputs\" not found!\n";
|
trace << "is_mealy(): \"synthesis-outputs\" not found!\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -252,9 +268,7 @@ namespace spot
|
||||||
void
|
void
|
||||||
split_separated_mealy_here(const twa_graph_ptr& m)
|
split_separated_mealy_here(const twa_graph_ptr& m)
|
||||||
{
|
{
|
||||||
assert(is_mealy(m));
|
bdd output_bdd = ensure_mealy("split_separated_mealy_here", m);
|
||||||
|
|
||||||
auto output_bdd = get_synthesis_outputs(m);
|
|
||||||
|
|
||||||
struct dst_cond_color_t
|
struct dst_cond_color_t
|
||||||
{
|
{
|
||||||
|
|
@ -323,10 +337,10 @@ namespace spot
|
||||||
twa_graph_ptr
|
twa_graph_ptr
|
||||||
split_separated_mealy(const const_twa_graph_ptr& m)
|
split_separated_mealy(const const_twa_graph_ptr& m)
|
||||||
{
|
{
|
||||||
assert(is_mealy((m)));
|
bdd outputs = ensure_mealy("split_separated_mealy", m);
|
||||||
auto m2 = make_twa_graph(m, twa::prop_set::all());
|
auto m2 = make_twa_graph(m, twa::prop_set::all());
|
||||||
m2->copy_acceptance_of(m);
|
m2->copy_acceptance_of(m);
|
||||||
set_synthesis_outputs(m2, get_synthesis_outputs(m));
|
set_synthesis_outputs(m2, outputs);
|
||||||
split_separated_mealy_here(m2);
|
split_separated_mealy_here(m2);
|
||||||
return m2;
|
return m2;
|
||||||
}
|
}
|
||||||
|
|
@ -767,7 +781,7 @@ namespace spot
|
||||||
twa_graph_ptr reduce_mealy(const const_twa_graph_ptr& mm,
|
twa_graph_ptr reduce_mealy(const const_twa_graph_ptr& mm,
|
||||||
bool output_assignment)
|
bool output_assignment)
|
||||||
{
|
{
|
||||||
assert(is_mealy(mm));
|
bdd outputs = ensure_mealy("reduce_mealy", mm);
|
||||||
if (mm->get_named_prop<std::vector<bool>>("state-player"))
|
if (mm->get_named_prop<std::vector<bool>>("state-player"))
|
||||||
throw std::runtime_error("reduce_mealy(): "
|
throw std::runtime_error("reduce_mealy(): "
|
||||||
"Only works on unsplit machines.\n");
|
"Only works on unsplit machines.\n");
|
||||||
|
|
@ -775,7 +789,7 @@ namespace spot
|
||||||
auto mmc = make_twa_graph(mm, twa::prop_set::all());
|
auto mmc = make_twa_graph(mm, twa::prop_set::all());
|
||||||
mmc->copy_ap_of(mm);
|
mmc->copy_ap_of(mm);
|
||||||
mmc->copy_acceptance_of(mm);
|
mmc->copy_acceptance_of(mm);
|
||||||
set_synthesis_outputs(mmc, get_synthesis_outputs(mm));
|
set_synthesis_outputs(mmc, outputs);
|
||||||
|
|
||||||
reduce_mealy_here(mmc, output_assignment);
|
reduce_mealy_here(mmc, output_assignment);
|
||||||
|
|
||||||
|
|
@ -785,7 +799,7 @@ namespace spot
|
||||||
|
|
||||||
void reduce_mealy_here(twa_graph_ptr& mm, bool output_assignment)
|
void reduce_mealy_here(twa_graph_ptr& mm, bool output_assignment)
|
||||||
{
|
{
|
||||||
assert(is_mealy(mm));
|
ensure_mealy("reduce_mealy_here", mm);
|
||||||
|
|
||||||
// Only consider infinite runs
|
// Only consider infinite runs
|
||||||
mm->purge_dead_states();
|
mm->purge_dead_states();
|
||||||
|
|
@ -902,6 +916,8 @@ namespace
|
||||||
// Writing also "flushes"
|
// Writing also "flushes"
|
||||||
void write()
|
void write()
|
||||||
{
|
{
|
||||||
|
if (!sat_csv_file)
|
||||||
|
return;
|
||||||
auto f = [](std::ostream& o, auto& v, bool sep = true)
|
auto f = [](std::ostream& o, auto& v, bool sep = true)
|
||||||
{
|
{
|
||||||
if (v >= 0)
|
if (v >= 0)
|
||||||
|
|
@ -910,8 +926,6 @@ namespace
|
||||||
o.put(',');
|
o.put(',');
|
||||||
v = -1;
|
v = -1;
|
||||||
};
|
};
|
||||||
if (!sat_csv_file)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto& out = *sat_csv_file;
|
auto& out = *sat_csv_file;
|
||||||
if (out.tellp() == 0)
|
if (out.tellp() == 0)
|
||||||
|
|
@ -3786,7 +3800,7 @@ namespace spot
|
||||||
twa_graph_ptr minimize_mealy(const const_twa_graph_ptr& mm,
|
twa_graph_ptr minimize_mealy(const const_twa_graph_ptr& mm,
|
||||||
int premin)
|
int premin)
|
||||||
{
|
{
|
||||||
assert(is_mealy(mm));
|
bdd outputs = ensure_mealy("minimize_mealy", mm);
|
||||||
|
|
||||||
satprob_info si(sat_instance_name);
|
satprob_info si(sat_instance_name);
|
||||||
si.task = "presat";
|
si.task = "presat";
|
||||||
|
|
@ -3916,7 +3930,7 @@ namespace spot
|
||||||
// Set state players!
|
// Set state players!
|
||||||
if (!minmachine)
|
if (!minmachine)
|
||||||
return early_exit();
|
return early_exit();
|
||||||
set_synthesis_outputs(minmachine, get_synthesis_outputs(mm));
|
set_synthesis_outputs(minmachine, outputs);
|
||||||
|
|
||||||
si.done=1;
|
si.done=1;
|
||||||
si.n_min_states = minmachine->num_states();
|
si.n_min_states = minmachine->num_states();
|
||||||
|
|
@ -3931,17 +3945,23 @@ namespace spot
|
||||||
minimize_mealy(const const_twa_graph_ptr& mm,
|
minimize_mealy(const const_twa_graph_ptr& mm,
|
||||||
synthesis_info& si)
|
synthesis_info& si)
|
||||||
{
|
{
|
||||||
if ((si.minimize_lvl < 3) || (5 < si.minimize_lvl))
|
if ((si.minimize_lvl < 3) || (si.minimize_lvl > 5))
|
||||||
throw std::runtime_error("Invalid option");
|
throw std::runtime_error("minimize_mealy(): "
|
||||||
|
"minimize_lvl should be between 3 and 5.");
|
||||||
|
|
||||||
std::string csvfile = si.opt.get_str("satlogcsv");
|
std::string csvfile = si.opt.get_str("satlogcsv");
|
||||||
std::string dimacsfile = si.opt.get_str("satlogdimacs");
|
std::string dimacsfile = si.opt.get_str("satlogdimacs");
|
||||||
|
|
||||||
if (!csvfile.empty())
|
if (!csvfile.empty())
|
||||||
sat_csv_file
|
{
|
||||||
= std::make_unique<std::ofstream>(csvfile,
|
sat_csv_file = std::make_unique<std::ofstream>
|
||||||
std::ios_base::ate
|
(csvfile, std::ios_base::ate | std::ios_base::app);
|
||||||
| std::ios_base::app);
|
if (!*sat_csv_file)
|
||||||
|
throw std::runtime_error("could not open `" + csvfile
|
||||||
|
+ "' for writing");
|
||||||
|
sat_csv_file->exceptions(std::ofstream::failbit
|
||||||
|
| std::ofstream::badbit);
|
||||||
|
}
|
||||||
if (!dimacsfile.empty())
|
if (!dimacsfile.empty())
|
||||||
sat_dimacs_file
|
sat_dimacs_file
|
||||||
= std::make_unique<fwrapper>(dimacsfile);
|
= std::make_unique<fwrapper>(dimacsfile);
|
||||||
|
|
|
||||||
|
|
@ -321,3 +321,41 @@ except RuntimeError as e:
|
||||||
tc.assertIn("already registered", se)
|
tc.assertIn("already registered", se)
|
||||||
else:
|
else:
|
||||||
report_missing_exception()
|
report_missing_exception()
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
spot.minimize_mealy(a, 100)
|
||||||
|
except RuntimeError as e:
|
||||||
|
se = str(e)
|
||||||
|
tc.assertIn("minimize_mealy", se)
|
||||||
|
tc.assertIn("minimize_lvl", se)
|
||||||
|
else:
|
||||||
|
report_missing_exception()
|
||||||
|
|
||||||
|
opt = spot.synthesis_info()
|
||||||
|
opt.minimize_lvl = 3
|
||||||
|
try:
|
||||||
|
spot.minimize_mealy(a, opt)
|
||||||
|
except RuntimeError as e:
|
||||||
|
se = str(e)
|
||||||
|
tc.assertIn("minimize_mealy", se)
|
||||||
|
tc.assertIn("synthesis-output", se)
|
||||||
|
|
||||||
|
spot.set_synthesis_outputs(a, buddy.bdd_ithvar(a.register_ap("b")))
|
||||||
|
filename = "/THIS-FILE/SHOULD/NOT/EXIST"
|
||||||
|
opt.opt.set_str("satlogdimacs", filename)
|
||||||
|
try:
|
||||||
|
spot.minimize_mealy(a, opt)
|
||||||
|
except RuntimeError as e:
|
||||||
|
tc.assertIn(filename, str(e))
|
||||||
|
else:
|
||||||
|
report_missing_exception()
|
||||||
|
|
||||||
|
opt.opt.set_str("satlogdimacs", "")
|
||||||
|
opt.opt.set_str("satlogcsv", filename)
|
||||||
|
try:
|
||||||
|
spot.minimize_mealy(a, opt)
|
||||||
|
except RuntimeError as e:
|
||||||
|
tc.assertIn(filename, str(e))
|
||||||
|
else:
|
||||||
|
report_missing_exception()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue