Commit 19a27392 authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz
Browse files

python: rewrite translate() to deal with unambiguous and sbacc

and make it easier to extend and use.

* src/twaalgos/postproc.hh, src/twaalgos/translate.cc,
src/twaalgos/translate.hh: Incorporate the Unambiguous option
with the other preferences.  It's cleaner this way, and the
previous setup did not work well with Python.
* src/bin/ltl2tgba.cc: Adjust to this change.
* wrap/python/spot.py (translate): Rewrite.
* wrap/python/tests/automata.ipynb: Adjust existing cases, and
add more as well as some comments.
parent 1ef3e5f3
......@@ -83,7 +83,7 @@ const struct argp_child children[] =
};
static spot::option_map extra_options;
bool unambiguous = false;
static spot::postprocessor::output_pref unambig = 0;
static int
parse_opt(int key, char* arg, struct argp_state*)
......@@ -98,7 +98,7 @@ parse_opt(int key, char* arg, struct argp_state*)
type = spot::postprocessor::Monitor;
break;
case 'U':
unambiguous = true;
unambig = spot::postprocessor::Unambiguous;
break;
case 'x':
{
......@@ -186,11 +186,9 @@ main(int argc, char** argv)
program_name);
spot::translator trans(&extra_options);
trans.set_pref(pref | comp | sbacc);
trans.set_pref(pref | comp | sbacc | unambig);
trans.set_type(type);
trans.set_level(level);
if (unambiguous)
trans.set_pref(spot::translator::Unambiguous);
try
{
......
......@@ -74,13 +74,11 @@ namespace spot
enum
{
Any = 0,
Small = 1,
Deterministic = 2,
// 3 reserved for unambiguous
// Combine Complete as 'Small | Complete' or 'Deterministic | Complete'
Small = 1, // Small and Deterministic
Deterministic = 2, // are exclusive choices.
Complete = 4,
// Likewise. State-based acceptance.
SBAcc = 8,
SBAcc = 8, // State-based acceptance.
Unambiguous = 16,
};
typedef int output_pref;
......
......@@ -28,7 +28,6 @@ namespace spot
void translator::setup_opt(const option_map* opt)
{
comp_susp_ = early_susp_ = skel_wdba_ = skel_simul_ = 0;
unambiguous_ = false;
if (!opt)
return;
......@@ -64,12 +63,13 @@ namespace spot
twa_graph_ptr translator::run(const ltl::formula** f)
{
if (unambiguous_ && type_ == postprocessor::Monitor)
bool unambiguous = (pref_ & postprocessor::Unambiguous);
if (unambiguous && type_ == postprocessor::Monitor)
{
// Deterministic monitor are unambiguous, so the unambiguous
// option is not really relevant for monitors.
unambiguous_ = false;
set_pref(postprocessor::Deterministic);
unambiguous = false;
set_pref(pref_ | postprocessor::Deterministic);
}
const ltl::formula* r = simpl_->simplify(*f);
......@@ -94,9 +94,9 @@ namespace spot
}
else
{
bool exprop = unambiguous_ || level_ == postprocessor::High;
bool exprop = unambiguous || level_ == postprocessor::High;
aut = ltl_to_tgba_fm(r, simpl_->get_dict(), exprop,
true, false, false, 0, 0, unambiguous_);
true, false, false, 0, 0, unambiguous);
}
aut = this->postprocessor::run(aut, r);
return aut;
......
// -*- coding: utf-8 -*-
// Copyright (C) 2013, 2014 Laboratoire de Recherche et Développement
// de l'Epita (LRDE).
// Copyright (C) 2013, 2014, 2015 Laboratoire de Recherche et
// Développement de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
//
......@@ -82,22 +82,12 @@ namespace spot
this->postprocessor::set_type(type);
}
typedef postprocessor::output_pref output_pref;
enum output_pref_extra { Unambiguous };
void
set_pref(output_pref pref)
{
this->postprocessor::set_pref(pref);
}
void
set_pref(output_pref_extra)
{
unambiguous_ = true;
}
typedef postprocessor::optimization_level optimization_level;
void
......@@ -130,7 +120,6 @@ namespace spot
int early_susp_;
int skel_wdba_;
int skel_simul_;
bool unambiguous_;
};
/// @}
}
......@@ -219,65 +219,135 @@ def automaton(filename):
except StopIteration:
raise RuntimeError("Failed to read automaton from {}".format(filename))
def translate(formula, output='tgba', pref='small', level='high',
complete=False):
def translate(formula, *args):
"""Translate a formula into an automaton.
Keep in mind that pref expresses just a preference that may not be
satisfied.
Keyword arguments:
output -- the type of automaton to build ('tgba', 'ba', 'monitor')
pref -- prefered characteristic of the produced automaton
('small', 'deterministic', 'any')
level -- level of optimizations ('low', 'medium', 'high')
complete -- whether to produce a complete automaton (True, False)
The optional arguments should be strings among the following:
- at most one in 'TGBA', 'BA', or 'Monitor'
(type of automaton to build)
- at most one in 'Small', 'Deterministic', 'Any'
(perefered characteristics of the produced automaton)
- at most one in 'Low', 'Medium', 'High'
(optimization level)
- any combination of 'Complete', 'Unambiguous', and
'StateBasedAcceptance' (or 'SBAcc' for short)
The default correspond to 'tgba', 'small' and 'high'.
"""
if type(formula) == str:
formula = parse_formula(formula)
a = translator(_bdd_dict)
if type(output) == str:
output_ = output.lower()
if output_ == 'tgba':
output = postprocessor.TGBA
elif output_ == 'ba':
output = postprocessor.BA
elif output_.startswith('mon'):
output = postprocessor.Monitor
type_ = None
pref_ = None
optm_ = None
comp_ = 0
unam_ = 0
sbac_ = 0
def type_set(val):
nonlocal type_
if type_ != None and type_ != val:
raise ValueError("type cannot be both {} and {}"
.format(type_, val))
elif val == 'tgba':
type_ = postprocessor.TGBA
elif val == 'ba':
type_ = postprocessor.BA
else:
raise ValueError("unknown output type: " + output)
a.set_type(output)
if complete:
complete = postprocessor.Complete
else:
complete = 0
if type(pref) == str:
pref_ = pref.lower()
if pref_.startswith('sm'):
pref = postprocessor.Small
elif pref_.startswith('det'):
pref = postprocessor.Deterministic
elif pref_ == 'any':
pref = postprocessor.Any
assert(val == 'monitor')
type_ = postprocessor.Monitor
def pref_set(val):
nonlocal pref_
if pref_ != None and pref_ != val:
raise ValueError("preference cannot be both {} and {}"
.format(pref_, val))
elif val == 'small':
pref_ = postprocessor.Small
elif val == 'deterministic':
pref_ = postprocessor.Deterministic
else:
assert(val == 'any')
pref_ = postprocessor.Any
def optm_set(val):
nonlocal optm_
if optm_ != None and optm_ != val:
raise ValueError("optimization level cannot be both {} and {}"
.format(optm_, val))
if optm_ == 'high':
optm_ = postprocessor.High
elif optm_.startswith('med'):
optm_ = postprocessor.Medium
else:
raise ValueError("unknown output preference: " + pref)
a.set_pref(pref | complete)
if type(level) == str:
level_ = level.lower()
if level_ == 'high':
level = postprocessor.High
elif level_.startswith('med'):
level = postprocessor.Medium
elif level_ == 'low':
level = postprocessor.Low
assert(level_ == 'low')
optm_ = postprocessor.Low
def misc_set(val):
nonlocal comp_, unam_, sbac_
if val == 'complete':
comp_ = postprocessor.Complete
elif val == 'sbacc' or val == 'state-based-acceptance':
sbac_ = postprocessor.SBAcc
else:
assert(val == 'unambiguous')
unam_ = postprocessor.Unambiguous
options = {
'tgba': type_set,
'ba': type_set,
'monitor': type_set,
'small': pref_set,
'deterministic': pref_set,
'any': pref_set,
'high': optm_set,
'medium': optm_set,
'low': optm_set,
'complete': misc_set,
'unambiguous': misc_set,
'statebasedacceptance': misc_set,
'sbacc': misc_set,
}
for arg in args:
arg = arg.lower()
fn = options.get(arg)
if fn:
fn(arg)
else:
raise ValueError("unknown optimization level: " + level)
a.set_level(level)
# arg is not an know option, but maybe it is a prefix of
# one of them
compat = []
f = None
for key, fn in options.items():
if key.startswith(arg):
compat.append(key)
f = fn
lc = len(compat)
if lc == 1:
f(compat[0])
elif lc < 1:
raise ValueError("unknown option '{}'".format(arg))
else:
raise ValueError("ambiguous option '{}' is prefix of {}"
.format(arg, str(compat)))
if type_ == None:
type_ = postprocessor.TGBA
if pref_ == None:
pref_ = postprocessor.Small
if optm_ == None:
optm_ = postprocessor.High
if type(formula) == str:
formula = parse_formula(formula)
a = translator(_bdd_dict)
a.set_type(type_)
a.set_pref(pref_ | comp_ | unam_ | sbac_)
a.set_level(optm_)
return a.run(formula)
......
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment