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

python: more conventional __repr__ for several types

* NEWS: Mention the change.
* python/spot/__init__.py: Add _repr_latex_ for twa_word, and
remove __repr__ and __str__ for atomic_prop_set.
* python/spot/impl.i: Implement __repr__ and __str__ for
atomic_prop_set.  Fix __repr__ for trival, acc_code, acc_cond,
mark_t.  Remove __repr__ for twa_run and twa_word.
* tests/python/acc_cond.ipynb, tests/python/accparse.ipynb,
tests/python/atva16-fig2a.ipynb, tests/python/automata.ipynb,
tests/python/bdditer.py, tests/python/contains.ipynb,
tests/python/gen.ipynb, tests/python/highlighting.ipynb,
tests/python/ltlsimple.py, tests/python/ltsmin-dve.ipynb,
tests/python/product.ipynb, tests/python/relabel.py,
tests/python/satmin.ipynb tests/python/stutter-inv.ipynb,
tests/python/word.ipynb: Adjust test cases.
* tests/python/formulas.ipynb: Add test for atomic_prop_set.
parent c3b7a691
Pipeline #4512 passed with stages
in 143 minutes and 32 seconds
......@@ -82,6 +82,22 @@ New in spot 2.6.3.dev (not yet released)
vector_rs_pairs) by acc_cond::is_rabin_like() and
acc_cond::is_streett_like() were not usable in Python.
- Many object types had __repr__() methods that would return the
same string as __str__(), contrary to Python usage where repr(x)
should try to show how to rebuild x. The following types have
been changed to follow this convention:
spot.acc_code
spot.acc_cond
spot.atomic_prop_set
spot.formula
spot.mark_t
spot.twa_run (__repr__ shows type and address)
spot.twa_word (likewise, but _repr_latex_ used in notebooks)
Note that this you were relying on the fact that Jupyter calls
repr() to display returned values, you may want to call print()
explicitely if you prefer the old representation.
New in spot 2.6.3 (2018-10-17)
Bugs fixed:
......
......@@ -352,19 +352,6 @@ class formula:
@_extend(atomic_prop_set)
class atomic_prop_set:
def __repr__(self):
res = '{'
comma = ''
for ap in self:
res += comma
comma = ', '
res += '"' + ap.ap_name() + '"'
res += '}'
return res
def __str__(self):
return self.__repr__()
def _repr_latex_(self):
res = '$\{'
comma = ''
......@@ -1147,6 +1134,22 @@ formula.show_mp_hierarchy = show_mp_hierarchy
@_extend(twa_word)
class twa_word:
def _repr_latex_(self):
bd = self.get_dict()
res = '$'
for idx, letter in enumerate(self.prefix):
if idx:
res += '; '
res += bdd_to_formula(letter, bd).to_str('j')
if len(res) > 1:
res += '; ';
res += '\\mathsf{cycle}\\{';
for idx, letter in enumerate(self.cycle):
if idx:
res += '; '
res += bdd_to_formula(letter, bd).to_str('j')
return res + '\\}$'
def as_svg(self):
"""
Build an SVG picture representing the word as a collection of
......
......@@ -669,13 +669,42 @@ def state_is_accepting(self, src) -> "bool":
%include <spot/taalgos/stats.hh>
%include <spot/taalgos/minimize.hh>
%extend std::set<spot::formula> {
std::string __str__()
{
std::ostringstream os;
os << '{';
const char* sep = "";
for (spot::formula s: *self)
{
os << sep << '"' << spot::escape_str(spot::str_psl(s)) << '"';
sep = ", ";
}
os << '}';
return os.str();
}
std::string __repr__()
{
std::ostringstream os;
os << "spot.atomic_prop_set([";
const char* sep = "";
for (spot::formula s: *self)
{
os << sep
<< "spot.formula(\"" << spot::escape_str(spot::str_psl(s)) << "\")";
sep = ", ";
}
os << "])";
return os.str();
}
}
%extend spot::acc_cond::rs_pair {
std::string __repr__()
{
std::ostringstream os;
os << "spot.rs_pair(fin=[";
char* sep = "";
const char* sep = "";
for (unsigned s: self->fin.sets())
{
os << sep << s;
......@@ -696,9 +725,11 @@ def state_is_accepting(self, src) -> "bool":
%extend spot::trival {
std::string __repr__()
{
std::ostringstream os;
os << *self;
return os.str();
if (self->is_true())
return "spot.trival(True)";
if (self->is_false())
return "spot.trival(False)";
return "spot.trival_maybe()";
}
std::string __str__()
......@@ -752,7 +783,9 @@ def state_is_accepting(self, src) -> "bool":
unsigned __len__() { return self->size(); }
formula __getitem__(unsigned pos) { return (*self)[pos]; }
std::string __repr__() { return spot::str_psl(*self); }
std::string __repr__() {
return "spot.formula(\"" + spot::escape_str(spot::str_psl(*self)) + "\")";
}
std::string __str__() { return spot::str_psl(*self); }
}
......@@ -929,7 +962,7 @@ def state_is_accepting(self, src) -> "bool":
std::string __repr__()
{
std::ostringstream os;
os << *self;
os << "spot.acc_code(\"" << *self << "\")";
return os.str();
}
......@@ -951,7 +984,14 @@ def state_is_accepting(self, src) -> "bool":
std::string __repr__()
{
std::ostringstream os;
os << *self;
os << "spot.mark_t([";
const char* sep = "";
for (unsigned s: self->sets())
{
os << sep << s;
sep = ", ";
}
os << "])";
return os.str();
}
......@@ -967,7 +1007,8 @@ def state_is_accepting(self, src) -> "bool":
std::string __repr__()
{
std::ostringstream os;
os << *self;
os << "spot.acc_cond(" << self->num_sets() << ", \""
<< self->get_acceptance() << "\")";
return os.str();
}
......@@ -980,13 +1021,6 @@ def state_is_accepting(self, src) -> "bool":
}
%extend spot::twa_run {
std::string __repr__()
{
std::ostringstream os;
os << *self;
return os.str();
}
std::string __str__()
{
std::ostringstream os;
......@@ -996,13 +1030,6 @@ def state_is_accepting(self, src) -> "bool":
}
%extend spot::twa_word {
std::string __repr__()
{
std::ostringstream os;
os << *self;
return os.str();
}
std::string __str__()
{
std::ostringstream os;
......
This diff is collapsed.
%% Cell type:code id: tags:
``` python
import spot
spot.setup()
```
%% Cell type:code id: tags:
``` python
c = spot.acc_code('Inf(0)&Fin(1)|Inf(2)&Fin(3)'); c
c = spot.acc_code('Inf(0)&Fin(1)|Inf(2)&Fin(3)'); print(c)
```
%% Output
(Inf(0) & Fin(1)) | (Inf(2) & Fin(3))
%% Cell type:code id: tags:
``` python
c.to_dnf()
print(c.to_dnf())
```
%% Output
(Fin(1) & Inf(0)) | (Fin(3) & Inf(2))
%% Cell type:code id: tags:
``` python
c.to_cnf()
print(c.to_cnf())
```
%% Output
(Inf(0) | Inf(2)) & (Inf(0) | Fin(3)) & (Inf(2) | Fin(1)) & (Fin(1)|Fin(3))
%% Cell type:code id: tags:
``` python
for acc in ['all', 't',
'Buchi', 'generalized-Buchi 3', 'generalized-Buchi 0',
'co-Buchi', 'generalized-co-Buchi 3', 'generalized-co-Buchi 0',
'Rabin 2', 'Rabin 0',
'Streett 2', 'Streett 0',
'generalized-Rabin 3 1 2 3', 'generalized-Rabin 0',
'parity min even 6', 'parity max odd 6', 'parity max even 6', 'parity min odd 6',
'parity min even 5', 'parity max odd 5', 'parity max even 5', 'parity min odd 5',
'parity min even 2', 'parity max odd 2', 'parity max even 2', 'parity min odd 2',
'parity min even 1', 'parity max odd 1', 'parity max even 1', 'parity min odd 1',
'parity min even 0', 'parity max odd 0', 'parity max even 0', 'parity min odd 0',
]:
print(acc, ': ', spot.acc_code(acc), sep='')
```
%% Output
all: t
t: t
Buchi: Inf(0)
generalized-Buchi 3: Inf(0)&Inf(1)&Inf(2)
generalized-Buchi 0: t
co-Buchi: Fin(0)
generalized-co-Buchi 3: Fin(0)|Fin(1)|Fin(2)
generalized-co-Buchi 0: f
Rabin 2: (Fin(0) & Inf(1)) | (Fin(2) & Inf(3))
Rabin 0: f
Streett 2: (Fin(0) | Inf(1)) & (Fin(2) | Inf(3))
Streett 0: t
generalized-Rabin 3 1 2 3: (Fin(0) & Inf(1)) | (Fin(2) & (Inf(3)&Inf(4))) | (Fin(5) & (Inf(6)&Inf(7)&Inf(8)))
generalized-Rabin 0: f
parity min even 6: Inf(0) | (Fin(1) & (Inf(2) | (Fin(3) & (Inf(4) | Fin(5)))))
parity max odd 6: Inf(5) | (Fin(4) & (Inf(3) | (Fin(2) & (Inf(1) | Fin(0)))))
parity max even 6: Fin(5) & (Inf(4) | (Fin(3) & (Inf(2) | (Fin(1) & Inf(0)))))
parity min odd 6: Fin(0) & (Inf(1) | (Fin(2) & (Inf(3) | (Fin(4) & Inf(5)))))
parity min even 5: Inf(0) | (Fin(1) & (Inf(2) | (Fin(3) & Inf(4))))
parity max odd 5: Fin(4) & (Inf(3) | (Fin(2) & (Inf(1) | Fin(0))))
parity max even 5: Inf(4) | (Fin(3) & (Inf(2) | (Fin(1) & Inf(0))))
parity min odd 5: Fin(0) & (Inf(1) | (Fin(2) & (Inf(3) | Fin(4))))
parity min even 2: Inf(0) | Fin(1)
parity max odd 2: Inf(1) | Fin(0)
parity max even 2: Fin(1) & Inf(0)
parity min odd 2: Fin(0) & Inf(1)
parity min even 1: Inf(0)
parity max odd 1: Fin(0)
parity max even 1: Inf(0)
parity min odd 1: Fin(0)
parity min even 0: t
parity max odd 0: t
parity max even 0: f
parity min odd 0: f
%% Cell type:code id: tags:
``` python
```
......
%% Cell type:markdown id: tags:
This example is the left part of Fig.2 in our ATVA'16 paper titled ["*Spot 2.0 — a framework for LTL and ω-automata manipulation*"](https://www.lrde.epita.fr/~adl/dl/adl/duret.16.atva2.pdf), slightly updated to the current version of Spot.
%% Cell type:code id: tags:
``` python
import spot
spot.setup(show_default='.b')
```
%% Cell type:code id: tags:
``` python
f = spot.formula('GFa <-> GFb'); f
```
%% Output
$\mathsf{G} \mathsf{F} a \leftrightarrow \mathsf{G} \mathsf{F} b$
GFa <-> GFb
spot.formula("GFa <-> GFb")
%% Cell type:code id: tags:
``` python
f.translate()
```
%% Output
<spot.impl.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f81a85ea1e0> >
<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f62d41ff690> >
%% Cell type:code id: tags:
``` python
def implies(f, g):
f = spot.formula(f)
g = spot.formula.Not(g)
return spot.product(f.translate(), g.translate()).is_empty()
def equiv(f, g):
return implies(f, g) and implies(g, f)
```
%% Cell type:code id: tags:
``` python
equiv('a U (b U a)', 'b U a')
```
%% Output
True
%% Cell type:code id: tags:
``` python
equiv('!(a U b)', '!a U !b')
```
%% Output
False
......
%% Cell type:code id: tags:
``` python
from IPython.display import display
import spot
from spot.jupyter import display_inline
spot.setup()
```
%% Cell type:markdown id: tags:
To build an automaton, simply call `translate()` with a formula, and a list of options to characterize the automaton you want (those options have the same name as the long options name of the `ltl2tgba` tool, and they can be abbreviated).
To build an automaton from an LTL formula, simply call `translate()` with a formula, and a list of options to characterize the automaton you want (those options have the same name as the long options name of the `ltl2tgba` tool, and they can be abbreviated).
%% Cell type:code id: tags:
``` python
a = spot.translate('(a U b) & GFc & GFd', 'BA', 'complete'); a
```
%% Output