implement SVA's first_match operator

* NEWS, doc/tl/tl.tex, doc/tl/tl.bib: Document it.
* spot/parsetl/parsetl.yy, spot/parsetl/scantl.ll: Parse it.
* spot/tl/formula.cc, spot/tl/formula.hh, spot/tl/dot.cc,
spot/tl/mutation.cc, spot/tl/print.cc, spot/tl/randomltl.cc,
spot/twaalgos/ltl2tgba_fm.cc: Adjust to support first_match.
* spot/tl/mark.cc, spot/tl/simplify.cc, spot/tl/snf.cc,
spot/tl/unabbrev.cc, spot/twa/formula2bdd.cc,
spot/twaalgos/ltl2taa.cc: Ignore it.
* tests/core/acc_word.test, tests/core/randpsl.test: Add more tests.
* tests/core/rand.test, tests/core/unambig.test,
tests/python/randltl.ipynb: Adjust.
* tests/python/formulas.ipynb: Show first_match.
This commit is contained in:
Alexandre Duret-Lutz 2019-05-06 14:59:05 +02:00
parent caf1eaa4ce
commit 6fac026454
24 changed files with 359 additions and 162 deletions

7
NEWS
View file

@ -46,6 +46,13 @@ New in spot 2.7.4.dev (not yet released)
acceptance condition. The output can be alternating only if the acceptance condition. The output can be alternating only if the
input was alternating. input was alternating.
- SVA's first_match operator can now be used in SERE formulas and
that is supported by the ltl_to_tgba_fm() translation. See
doc/tl/tl.pdf for the semantics. *WARNING* Because this adds a
new operator, any code that switches over the spot::op type may
need a new case for op::first_match. Furthermore, the output of
"randltl --psl" will be different from previous releases.
- The parser for SERE learned to recognize the ##n and ##[i:j] - The parser for SERE learned to recognize the ##n and ##[i:j]
operators from SVA. So {##2 a ##0 b[+] ##1 c ##2 e} is another operators from SVA. So {##2 a ##0 b[+] ##1 c ##2 e} is another
way to write {[*2];a:b[+];c;1;e}, and {a ##[i:j] b} is parsed as way to write {[*2];a:b[+];c;1;e}, and {a ##[i:j] b} is parsed as

View file

@ -216,6 +216,15 @@
publisher = {Springer-Verlag} publisher = {Springer-Verlag}
} }
@Book{ systemverilog.04.lrm,
title = {SystemVerilog 3.1a Language Reference Manual:
Accelleras Extensions to Ver- ilog},
publisher = {Accellera},
year = {2004},
month = may,
note = {\url{http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.366.6206}}
}
@TechReport{ tauriainen.03.a83, @TechReport{ tauriainen.03.a83,
author = {Heikki Tauriainen}, author = {Heikki Tauriainen},
title = {On Translating Linear Temporal Logic into Alternating and title = {On Translating Linear Temporal Logic into Alternating and

View file

@ -98,6 +98,7 @@
\newcommand{\GOTO}[1]{\texttt{[->#1]}} \newcommand{\GOTO}[1]{\texttt{[->#1]}}
\newcommand{\PLUS}{\texttt{[+]}} \newcommand{\PLUS}{\texttt{[+]}}
\newcommand{\FPLUS}{\texttt{[:+]}} \newcommand{\FPLUS}{\texttt{[:+]}}
\newcommand{\FIRSTMATCH}{\texttt{first\_match}}
\newcommand{\eword}{\texttt{[*0]}} \newcommand{\eword}{\texttt{[*0]}}
\newcommand{\Esuffix}{\texttt{<>->}} \newcommand{\Esuffix}{\texttt{<>->}}
@ -609,6 +610,7 @@ denote arbitrary SERE.
& $f\FSTAR{\mvar{i}:}$ & $f\FSTAR{\mvar{i}:}$
& $f\FSTAR{\mvar{i} to}$ & $f\FSTAR{\mvar{i} to}$
& $f\FSTAR{\mvar{i},}$\\ & $f\FSTAR{\mvar{i},}$\\
first match & $\mathclap{\FIRSTMATCH\code(f\code)}$ \\
\end{tabular} \end{tabular}
\end{center} \end{center}
@ -679,7 +681,9 @@ $a$ is an atomic proposition.
\text{or} & \mvar{i}>0 \land (\exists k\in\N,\, \text{or} & \mvar{i}>0 \land (\exists k\in\N,\,
(\sigma^{0..k}\VDash f) \land (\sigma^{k..} (\sigma^{0..k}\VDash f) \land (\sigma^{k..}
\VDash f\FSTAR{\mvar{i-1}..}))\\ \VDash f\FSTAR{\mvar{i-1}..}))\\
\end{cases} \end{cases}\\
\sigma\VDash \FIRSTMATCH\code(f\code) & \iff
(\sigma\VDash f)\land (\nexists k<|\sigma|,\,\sigma^{0..k}\nVDash f)
\end{align*}} \end{align*}}
Notes: Notes:
@ -713,6 +717,11 @@ operands are Boolean formulas.
by~\citet{dax.09.atva}. With this simple addition, it is possible by~\citet{dax.09.atva}. With this simple addition, it is possible
to define a subset of PSL that expresses exactly the to define a subset of PSL that expresses exactly the
stutter-invariant $\omega$-regular languages. stutter-invariant $\omega$-regular languages.
\item The $\FIRSTMATCH$ operator does not exist in PSL. It comes
from SystemVerilog Assertions (SVA)~\cite{systemverilog.04.lrm}.
One intuition behind $\FIRSTMATCH\code(f\code)$ is that the
DFA for $\FIRSTMATCH\code(f\code)$ can be obtained from the DFA
for $f$ by removing all transitions leaving accepting states.
\end{itemize} \end{itemize}
\subsection{Syntactic Sugar} \subsection{Syntactic Sugar}
@ -757,10 +766,11 @@ it for output. $b$ must be a Boolean formula.
\end{align*} \end{align*}
The following adds input support for the SVA concatenation (or delay) The following adds input support for the SVA concatenation (or delay)
operator. The simplest equivalence are that $f \DELAY{0} g$, operator~\cite{systemverilog.04.lrm}. The simplest equivalence are
$f \DELAY{1} g$, $f \DELAY{2} g$ mean respectively $f \FUSION g$, that $f \DELAY{0} g$, $f \DELAY{1} g$, $f \DELAY{2} g$ mean
$f \CONCAT g$, and $f \CONCAT \1\CONCAT g$, but the delay can be a respectively $f \FUSION g$, $f \CONCAT g$, and
range, and $f$ can be omitted. $f \CONCAT \1\CONCAT g$, but the delay can be a range, and $f$ can be
omitted.
\begin{align*} \begin{align*}
f\DELAY{\mvar{i}} g &\equiv f\DELAYR{\mvar{i}..\mvar{i}} g & {}\DELAY{\mvar{i}} g &\equiv {}\DELAYR{\mvar{i}..\mvar{i}} g\\ f\DELAY{\mvar{i}} g &\equiv f\DELAYR{\mvar{i}..\mvar{i}} g & {}\DELAY{\mvar{i}} g &\equiv {}\DELAYR{\mvar{i}..\mvar{i}} g\\
@ -790,8 +800,8 @@ $b_1$, $b_2$ are assumed to be Boolean formulas.
\eword\FSTAR{\mvar{i}..\mvar{j}} &\equiv \0\text{~if~}i>0 \\ \eword\FSTAR{\mvar{i}..\mvar{j}} &\equiv \0\text{~if~}i>0 \\
&& &&
f\FSTAR{\mvar{i}..\mvar{j}}\FSTAR{\mvar{k}..\mvar{l}} &\equiv f\FSTAR{\mvar{ik}..\mvar{jl}}\text{~if~}i(k+1)\le jk+1 \\ f\FSTAR{\mvar{i}..\mvar{j}}\FSTAR{\mvar{k}..\mvar{l}} &\equiv f\FSTAR{\mvar{ik}..\mvar{jl}}\text{~if~}i(k+1)\le jk+1 \\
f\FSTAR{0}&\equiv \1 & f\FSTAR{0}&\equiv \1 & f\FSTAR{1}&\equiv f\text{~if~}\varepsilon\nVDash f\\
f\FSTAR{1}&\equiv f\text{~if~}\varepsilon\nVDash f\\ \FIRSTMATCH\code(b\code) &\equiv b & \FIRSTMATCH\code(f\code) &\equiv \eword\text{~if~}\varepsilon\VDash f
\end{align*} \end{align*}
\noindent \noindent
@ -958,41 +968,49 @@ operator, even if the operator has multiple synonyms (like \samp{|},
\samp{||}, and {`\verb=\/='}). \samp{||}, and {`\verb=\/='}).
\begin{align*} \begin{align*}
\mathit{constant} ::={}& \0 \mid \1 & \mathit{tformula} ::={}&\mathit{bformula}\\ \mathit{constant} ::={} & \0 \mid \1 \\
\mathit{atomic\_prop} ::={}& \text{see section~\ref{sec:ap}} & \mid{}&\tsamp{(}\,\mathit{tformula}\,\tsamp{)} \\ \mathit{atomic\_prop} ::={} & \text{see secn~\ref{sec:ap}} \\[1ex]
\mathit{bformula} ::={}& \mathit{constant} & \mid{}&\msamp{\NOT}\,\mathit{tformula}\,\\ \mathit{bformula} ::={} & \mathit{constant} & \mid{} & \tsamp{(}\,\mathit{bformula}\,\tsamp{)} & \mid{} & \mathit{bformula}\,\msamp{\XOR}\,\mathit{bformula} \\
\mid{}&\mathit{atomic\_prop} & \mid{}&\mathit{tformula}\,\msamp{\AND}\,\mathit{tformula} \\ \mid{} & \mathit{atomic\_prop} & \mid{} & \msamp{\NOT}\,\mathit{bformula} & \mid{} & \mathit{bformula}\,\msamp{\EQUIV}\,\mathit{bformula} \\
\mid{}&\mathit{atomic\_prop}\code{=0} & \mid{}&\mathit{tformula}\,\msamp{\OR}\,\mathit{tformula} \\ \mid{} & \mathit{atomic\_prop}\code{=0} & \mid{} & \mathit{bformula}\,\msamp{\AND}\,\mathit{bformula} & \mid{} & \mathit{bformula}\,\msamp{\IMPLIES}\,\mathit{bformula} \\
\mid{}&\mathit{atomic\_prop}\code{=1} & \mid{}&\mathit{tformula}\,\msamp{\IMPLIES}\,\mathit{tformula} \\ \mid{} & \mathit{atomic\_prop}\code{=1} & \mid{} & \mathit{bformula}\,\msamp{\OR}\,\mathit{bformula} \\[1ex]
\mid{}&\tsamp{(}\,\mathit{bformula}\,\tsamp{)} & \mid{}&\mathit{tformula}\,\msamp{\XOR}\,\mathit{tformula} \\ \mathit{sere} ::={} & \mathit{bformula} & \mid{} & \msamp{\STAR{\mvar{i}..\mvar{j}}} & \mid{} & \DELAY{\mvar{i}}\mathit{sere} \\
\mid{}&\msamp{\NOT}\,\mathit{bformula} & \mid{}&\mathit{tformula}\,\msamp{\EQUIV}\,\mathit{tformula} \\ \mid{} & \tsamp{\{}\,\mathit{sere}\,\tsamp{\}} & \mid{} & \msamp{\PLUS{}} & \mid{} & \DELAYR{\mvar{i}..\mvar{j}}\mathit{sere} \\
\mid{}&\mathit{bformula}\,\msamp{\AND}\,\mathit{bformula} & \mid{}&\msamp{\X}\,\mathit{tformula} \\ \mid{} & \tsamp{(}\,\mathit{sere}\,\tsamp{)} & \mid{} & \mathit{sere}\msamp{\STAR{\mvar{i}..\mvar{j}}} & \mid{} & \mathit{sere}\DELAY{\mvar{i}}\mathit{sere} \\
\mid{}&\mathit{bformula}\,\msamp{\OR}\,\mathit{bformula} & \mid{}&\msamp{\XREP{\mvar{i}..\mvar{j}}}\,\mathit{tformula} \\ \mid{} & \mathit{sere}\msamp{\OR}\mathit{sere} & \mid{} & \mathit{sere}\msamp{\PLUS} & \mid{} & \mathit{sere}\DELAYR{\mvar{i}..\mvar{j}}\mathit{sere} \\
\mid{}&\mathit{bformula}\,\msamp{\IMPLIES}\,\mathit{bformula} & \mid{}&\msamp{\F}\,\mathit{tformula}\\ \mid{} & \mathit{sere}\msamp{\AND}\mathit{sere} & \mid{} & \mathit{sere}\msamp{\FSTAR{\mvar{i}..\mvar{j}}} & \mid{} & \FIRSTMATCH\code(\,sere\,\code) \\
\mid{}&\mathit{bformula}\,\msamp{\XOR}\,\mathit{bformula} & \mid{}&\msamp{\FREP{\mvar{i}..\mvar{j}}}\,\mathit{tformula} \\ \mid{} & \mathit{sere}\msamp{\ANDALT}\mathit{sere} & \mid{} & \mathit{sere}\msamp{\FPLUS} \\
\mid{}&\mathit{bformula}\,\msamp{\EQUIV}\,\mathit{bformula} & \mid{}&\msamp{\G}\,\mathit{tformula}\\ \mid{} & \mathit{sere}\msamp{\CONCAT}\mathit{sere} & \mid{} & \mathit{sere}\msamp{\EQUAL{\mvar{i}..\mvar{j}}} \\
\mathit{sere} ::={}&\mathit{bformula} & \mid{}&\msamp{\GREP{\mvar{i}..\mvar{j}}}\,\mathit{tformula} \\ \mid{} & \mathit{sere}\msamp{\FUSION}\mathit{sere} & \mid{} & \mathit{sere}\msamp{\GOTO{\mvar{i}..\mvar{j}}} \\[1ex]
\mid{}&\tsamp{\{}\,\mathit{sere}\,\tsamp{\}} & \mid{}&\mathit{tformula}\,\msamp{\U}\,\mathit{tformula} \\ \mathit{tformula} ::={} & \mathit{bformula} & \mid{} & \msamp{\X}\,\mathit{tformula} & \mid{} & \tsamp{\{}\mathit{sere}\tsamp{\}}\,\msamp{\Asuffix}\,\mathit{tformula} \\
\mid{}&\tsamp{(}\,\mathit{sere}\,\tsamp{)} & \mid{}&\mathit{tformula}\,\msamp{\W}\,\mathit{tformula} \\ \mid{} & \tsamp{(}\,\mathit{tformula}\,\tsamp{)} & \mid{} & \msamp{\XREP{\mvar{i}..\mvar{j}}}\,\mathit{tformula} & \mid{} & \tsamp{\{}\mathit{sere}\tsamp{\}}\,\msamp{\AsuffixEQ}\,\mathit{tformula} \\
\mid{}&\mathit{sere}\msamp{\OR}\mathit{sere} & \mid{}&\mathit{tformula}\,\msamp{\R}\,\mathit{tformula} \\ \mid{} & \msamp{\NOT}\,\mathit{tformula}\, & \mid{} & \msamp{\F}\,\mathit{tformula} & \mid{} & \tsamp{\{}\mathit{sere}\tsamp{\}}\,\msamp{\Esuffix}\,\mathit{tformula} \\
\mid{}&\mathit{sere}\msamp{\AND}\mathit{sere} & \mid{}&\mathit{tformula}\,\msamp{\M}\,\mathit{tformula} \\ \mid{} & \mathit{tformula}\,\msamp{\AND}\,\mathit{tformula} & \mid{} & \msamp{\FREP{\mvar{i}..\mvar{j}}}\,\mathit{tformula} & \mid{} & \tsamp{\{}\mathit{sere}\tsamp{\}}\,\msamp{\EsuffixEQ}\,\mathit{tformula} \\
\mid{}&\mathit{sere}\msamp{\ANDALT}\mathit{sere} & \mid{}&\tsamp{\{}\mathit{sere}\tsamp{\}}\,\msamp{\Asuffix}\,\mathit{tformula}\\ \mid{} & \mathit{tformula}\,\msamp{\OR}\,\mathit{tformula} & \mid{} & \msamp{\G}\,\mathit{tformula} & \mid{} & \tsamp{\{}\mathit{sere}\tsamp{\}} \\
\mid{}&\mathit{sere}\msamp{\CONCAT}\mathit{sere} & \mid{}&\tsamp{\{}\mathit{sere}\tsamp{\}}\,\msamp{\AsuffixEQ}\,\mathit{tformula}\\ \mid{} & \mathit{tformula}\,\msamp{\IMPLIES}\,\mathit{tformula} & \mid{} & \msamp{\GREP{\mvar{i}..\mvar{j}}}\,\mathit{tformula} & \mid{} & \tsamp{\{}\mathit{sere}\tsamp{\}}\msamp{\NOT} \\
\mid{}&\mathit{sere}\msamp{\FUSION}\mathit{sere} & \mid{}&\tsamp{\{}\mathit{sere}\tsamp{\}}\,\msamp{\Esuffix}\,\mathit{tformula}\\ \mid{} & \mathit{tformula}\,\msamp{\XOR}\,\mathit{tformula} & \mid{} & \mathit{tformula}\,\msamp{\U}\,\mathit{tformula} \\
\mid{}&\msamp{\STAR{\mvar{i}..\mvar{j}}} & \mid{}&\tsamp{\{}\mathit{sere}\tsamp{\}}\,\msamp{\EsuffixEQ}\,\mathit{tformula} \\ \mid{} & \mathit{tformula}\,\msamp{\EQUIV}\,\mathit{tformula} & \mid{} & \mathit{tformula}\,\msamp{\W}\,\mathit{tformula} \\
\mid{}&\msamp{\PLUS{}} & \mid{}&\tsamp{\{}\mathit{sere}\tsamp{\}} \\ & & \mid{} & \mathit{tformula}\,\msamp{\R}\,\mathit{tformula} \\
\mid{}&\mathit{sere}\msamp{\STAR{\mvar{i}..\mvar{j}}} & \mid{}&\tsamp{\{}\mathit{sere}\tsamp{\}}\msamp{\NOT} \\ & & \mid{} & \mathit{tformula}\,\msamp{\M}\,\mathit{tformula} \\
\mid{}&\mathit{sere}\msamp{\PLUS} \\
\mid{}&\mathit{sere}\msamp{\FSTAR{\mvar{i}..\mvar{j}}} \\
\mid{}&\mathit{sere}\msamp{\FPLUS} \\
\mid{}&\mathit{sere}\msamp{\EQUAL{\mvar{i}..\mvar{j}}} \\
\mid{}&\mathit{sere}\msamp{\GOTO{\mvar{i}..\mvar{j}}} \\
\mid{}&\DELAY{\mvar{i}}\mathit{sere} \\
\mid{}&\DELAYR{\mvar{i}..\mvar{j}}\mathit{sere} \\
\mid{}&\mathit{sere}\DELAY{\mvar{i}}\mathit{sere} \\
\mid{}&\mathit{sere}\DELAYR{\mvar{i}..\mvar{j}}\mathit{sere} \\
\end{align*} \end{align*}
\section{Operator precedence} \section{Operator precedence}
The following operator precedence describes the current parser of The following operator precedence describes the current parser of

View file

@ -224,6 +224,7 @@ using namespace spot;
%token OP_ECONCAT "existential concat operator" %token OP_ECONCAT "existential concat operator"
%token OP_UCONCAT_NONO "universal non-overlapping concat operator" %token OP_UCONCAT_NONO "universal non-overlapping concat operator"
%token OP_ECONCAT_NONO "existential non-overlapping concat operator" %token OP_ECONCAT_NONO "existential non-overlapping concat operator"
%token OP_FIRST_MATCH "first_match"
%token <str> ATOMIC_PROP "atomic proposition" %token <str> ATOMIC_PROP "atomic proposition"
%token OP_CONCAT "concat operator" OP_FUSION "fusion operator" %token OP_CONCAT "concat operator" OP_FUSION "fusion operator"
%token CONST_TRUE "constant true" CONST_FALSE "constant false" %token CONST_TRUE "constant true" CONST_FALSE "constant false"
@ -678,6 +679,8 @@ sere: booleanatom
} }
| sere OP_EQUIV error | sere OP_EQUIV error
{ missing_right_binop($$, $1, @2, "equivalent operator"); } { missing_right_binop($$, $1, @2, "equivalent operator"); }
| OP_FIRST_MATCH PAR_OPEN sere PAR_CLOSE
{ $$ = fnode::unop(op::first_match, $3); }
bracedsere: BRACE_OPEN sere BRACE_CLOSE bracedsere: BRACE_OPEN sere BRACE_CLOSE
{ $$ = $2; } { $$ = $2; }

View file

@ -217,6 +217,8 @@ eol2 (\n\r)+|(\r\n)+
/* ~ comes from Goal, ! from everybody else */ /* ~ comes from Goal, ! from everybody else */
{NOT} BEGIN(0); return token::OP_NOT; {NOT} BEGIN(0); return token::OP_NOT;
"first_match" BEGIN(0); return token::OP_FIRST_MATCH;
/* SVA operators */ /* SVA operators */
"##"[0-9]+ { "##"[0-9]+ {
errno = 0; errno = 0;

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2009-2015, 2018 Laboratoire de Recherche et // Copyright (C) 2009-2015, 2018-2019 Laboratoire de Recherche et
// Développement de l'Epita (LRDE). // Développement de l'Epita (LRDE).
// Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 // Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6
// (LIP6), département Systèmes Répartis Coopératifs (SRC), Université // (LIP6), département Systèmes Répartis Coopératifs (SRC), Université
@ -88,6 +88,7 @@ namespace spot
case op::AndNLM: case op::AndNLM:
case op::Star: case op::Star:
case op::FStar: case op::FStar:
case op::first_match:
childnum = 0; // No number for children childnum = 0; // No number for children
break; break;
case op::Xor: case op::Xor:

View file

@ -241,6 +241,7 @@ namespace spot
C(Fusion); C(Fusion);
C(Star); C(Star);
C(FStar); C(FStar);
C(first_match);
#undef C #undef C
} }
SPOT_UNREACHABLE(); SPOT_UNREACHABLE();
@ -826,6 +827,18 @@ namespace spot
if (f->is_boolean()) if (f->is_boolean())
return unop(op::Not, f); return unop(op::Not, f);
break; break;
case op::first_match:
// first_match(first_match(sere)) = first_match(sere);
// first_match(b) = b
if (f->is(o) || f->is_boolean())
return f;
// first_match(r*) = [*0]
if (f->accepts_eword())
{
f->destroy();
return eword();
}
break;
default: default:
SPOT_UNREACHABLE(); SPOT_UNREACHABLE();
} }
@ -1617,6 +1630,23 @@ namespace spot
} }
} }
break; break;
case op::first_match:
props = children[0]->props;
// If first_match(r) == r && !(r;[*]), then it should follow
// that if r is stutter-inv, then first_match(r) is
// stutter-inv, so we do not reset the syntactic_si bit.
assert(is_.sere_formula);
is_.boolean = false;
is_.ltl_formula = false;
is_.psl_formula = false;
is_.eventual = false;
is_.universal = false;
is_.syntactic_safety = false;
is_.syntactic_guarantee = false;
is_.syntactic_obligation = false;
is_.syntactic_recurrence = false;
is_.syntactic_persistence = false;
break;
} }
} }

View file

@ -97,6 +97,7 @@ namespace spot
// star-like operators // star-like operators
Star, ///< Star Star, ///< Star
FStar, ///< Fustion Star FStar, ///< Fustion Star
first_match, ///< first_match(sere)
}; };
#ifndef SWIG #ifndef SWIG
@ -942,6 +943,11 @@ namespace spot
/// @{ /// @{
SPOT_DEF_UNOP(NegClosureMarked); SPOT_DEF_UNOP(NegClosureMarked);
/// @} /// @}
/// \brief Construct first_match(sere)
/// @{
SPOT_DEF_UNOP(first_match);
/// @}
#undef SPOT_DEF_UNOP #undef SPOT_DEF_UNOP
/// @{ /// @{
@ -1680,6 +1686,7 @@ namespace spot
case op::Closure: case op::Closure:
case op::NegClosure: case op::NegClosure:
case op::NegClosureMarked: case op::NegClosureMarked:
case op::first_match:
return unop(o, trans((*this)[0], std::forward<Args>(args)...)); return unop(o, trans((*this)[0], std::forward<Args>(args)...));
case op::Xor: case op::Xor:
case op::Implies: case op::Implies:

View file

@ -1,6 +1,6 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2010, 2012, 2014, 2015, 2018 Laboratoire de Recherche // Copyright (C) 2010, 2012, 2014-2015, 2018-2019 Laboratoire de
// et Développement de l'Epita (LRDE). // Recherche et Développement de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
// //
@ -59,6 +59,7 @@ namespace spot
case op::UConcat: case op::UConcat:
case op::Concat: case op::Concat:
case op::Fusion: case op::Fusion:
case op::first_match:
res = f; res = f;
break; break;
case op::NegClosure: case op::NegClosure:
@ -120,6 +121,7 @@ namespace spot
case op::EConcat: case op::EConcat:
case op::EConcatMarked: case op::EConcatMarked:
case op::UConcat: case op::UConcat:
case op::first_match:
res = f; res = f;
break; break;
case op::Or: case op::Or:

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2014-2016, 2018 Laboratoire de Recherche et // Copyright (C) 2014-2016, 2018-2019 Laboratoire de Recherche et
// Developpement de l'Epita (LRDE). // Developpement de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
@ -83,6 +83,7 @@ namespace spot
case op::X: case op::X:
case op::F: case op::F:
case op::G: case op::G:
case op::first_match:
if ((opts_ & Mut_Remove_Ops) if ((opts_ & Mut_Remove_Ops)
&& mutation_counter_-- == 0) && mutation_counter_-- == 0)
return f[0]; return f[0];

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2008, 2010, 2012-2016, 2018 Laboratoire de // Copyright (C) 2008, 2010, 2012-2016, 2018, 2019 Laboratoire de
// Recherche et Développement de l'Epita (LRDE) // Recherche et Développement de l'Epita (LRDE)
// Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6), // Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre // département Systèmes Répartis Coopératifs (SRC), Université Pierre
@ -71,6 +71,7 @@ namespace spot
KFPlusBunop, KFPlusBunop,
KEqualBunop, KEqualBunop,
KGotoBunop, KGotoBunop,
KFirstMatch,
}; };
const char* spot_kw[] = { const char* spot_kw[] = {
@ -110,6 +111,7 @@ namespace spot
"[:+]", "[:+]",
"[=", "[=",
"[->", "[->",
"first_match",
}; };
const char* spin_kw[] = { const char* spin_kw[] = {
@ -149,6 +151,7 @@ namespace spot
"[:+]", // not supported "[:+]", // not supported
"[=", // not supported "[=", // not supported
"[->", // not supported "[->", // not supported
"first_match", // not supported
}; };
const char* wring_kw[] = { const char* wring_kw[] = {
@ -188,6 +191,7 @@ namespace spot
"[:+]", // not supported "[:+]", // not supported
"[=", // not supported "[=", // not supported
"[->", // not supported "[->", // not supported
"first_match", // not supported
}; };
const char* utf8_kw[] = { const char* utf8_kw[] = {
@ -227,6 +231,7 @@ namespace spot
"[:+]", "[:+]",
"[=", "[=",
"[->", "[->",
"first_match",
}; };
const char* latex_kw[] = { const char* latex_kw[] = {
@ -266,6 +271,7 @@ namespace spot
"\\SereFPlus{}", "\\SereFPlus{}",
"\\SereEqual{", "\\SereEqual{",
"\\SereGoto{", "\\SereGoto{",
"\\FirstMatch",
}; };
const char* sclatex_kw[] = { const char* sclatex_kw[] = {
@ -309,6 +315,7 @@ namespace spot
"^{\\mathsf{:}+}", "^{\\mathsf{:}+}",
"^{=", "^{=",
"^{\\to", "^{\\to",
"\\mathsf{first\\_match}",
}; };
static bool static bool
@ -840,6 +847,13 @@ namespace spot
} }
} }
break; break;
case op::first_match:
emit(KFirstMatch);
os_ << '(';
top_level_ = true;
visit(f[0]);
os_ << ')';
break;
} }
if (want_par) if (want_par)
closep(); closep();
@ -1113,6 +1127,7 @@ namespace spot
case op::Fusion: case op::Fusion:
case op::Star: case op::Star:
case op::FStar: case op::FStar:
case op::first_match:
SPOT_UNIMPLEMENTED(); SPOT_UNIMPLEMENTED();
} }
for (auto c: f) for (auto c: f)

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2008-2012, 2014-2016, 2018 Laboratoire de Recherche // Copyright (C) 2008-2012, 2014-2016, 2018-2019 Laboratoire de Recherche
// et Développement de l'Epita (LRDE). // et Développement de l'Epita (LRDE).
// Copyright (C) 2005 Laboratoire d'Informatique de Paris 6 // Copyright (C) 2005 Laboratoire d'Informatique de Paris 6
// (LIP6), département Systèmes Répartis Coopératifs (SRC), Université // (LIP6), département Systèmes Répartis Coopératifs (SRC), Université
@ -311,7 +311,7 @@ namespace spot
// SEREs // SEREs
random_sere::random_sere(const atomic_prop_set* ap) random_sere::random_sere(const atomic_prop_set* ap)
: random_formula(11, ap), rb(ap) : random_formula(12, ap), rb(ap)
{ {
proba_[0].setup("eword", 1, eword_builder); proba_[0].setup("eword", 1, eword_builder);
proba_2_ = proba_ + 1; proba_2_ = proba_ + 1;
@ -321,11 +321,12 @@ namespace spot
proba_[3].setup("star_b", 2, bunop_bounded_builder<op::Star>); proba_[3].setup("star_b", 2, bunop_bounded_builder<op::Star>);
proba_[4].setup("fstar", 2, bunop_unbounded_builder<op::FStar>); proba_[4].setup("fstar", 2, bunop_unbounded_builder<op::FStar>);
proba_[5].setup("fstar_b", 2, bunop_bounded_builder<op::FStar>); proba_[5].setup("fstar_b", 2, bunop_bounded_builder<op::FStar>);
proba_[6].setup("and", 3, multop_builder<op::AndRat>); proba_[6].setup("first_match", 2, unop_builder<op::first_match>);
proba_[7].setup("andNLM", 3, multop_builder<op::AndNLM>); proba_[7].setup("and", 3, multop_builder<op::AndRat>);
proba_[8].setup("or", 3, multop_builder<op::OrRat>); proba_[8].setup("andNLM", 3, multop_builder<op::AndNLM>);
proba_[9].setup("concat", 3, multop_builder<op::Concat>); proba_[9].setup("or", 3, multop_builder<op::OrRat>);
proba_[10].setup("fusion", 3, multop_builder<op::Fusion>); proba_[10].setup("concat", 3, multop_builder<op::Concat>);
proba_[11].setup("fusion", 3, multop_builder<op::Fusion>);
update_sums(); update_sums();
} }

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2011-2018 Laboratoire de Recherche et Developpement // Copyright (C) 2011-2019 Laboratoire de Recherche et Developpement
// de l'Epita (LRDE). // de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
@ -498,6 +498,7 @@ namespace spot
case op::Fusion: case op::Fusion:
case op::Star: case op::Star:
case op::FStar: case op::FStar:
case op::first_match:
// !(a*) etc. should never occur. // !(a*) etc. should never occur.
{ {
assert(!negated); assert(!negated);
@ -855,6 +856,7 @@ namespace spot
case op::ap: case op::ap:
case op::Not: case op::Not:
case op::FStar: case op::FStar:
case op::first_match:
return f; return f;
case op::X: case op::X:
{ {

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2012, 2014, 2015, 2016, 2018 Laboratoire de Recherche // Copyright (C) 2012, 2014, 2015, 2016, 2018, 2019 Laboratoire de Recherche
// et Developpement de l'Epita (LRDE). // et Developpement de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
@ -35,7 +35,6 @@ namespace spot
class snf_visitor final class snf_visitor final
{ {
protected: protected:
formula result_;
snf_cache* cache_; snf_cache* cache_;
public: public:
snf_visitor(snf_cache* c) snf_visitor(snf_cache* c)
@ -125,6 +124,7 @@ namespace spot
SPOT_UNREACHABLE(); SPOT_UNREACHABLE();
case op::AndRat: // Can AndRat be handled better? case op::AndRat: // Can AndRat be handled better?
case op::FStar: // Can FStar be handled better? case op::FStar: // Can FStar be handled better?
case op::first_match: // Can first_match be handled better?
out = f; out = f;
break; break;
} }

View file

@ -1,6 +1,6 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2015, 2018 Laboratoire de Recherche et Développement // Copyright (C) 2015, 2018-2019 Laboratoire de Recherche et
// de l'Epita (LRDE). // Développement de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
// //
@ -113,6 +113,7 @@ namespace spot
case op::Fusion: case op::Fusion:
case op::Star: case op::Star:
case op::FStar: case op::FStar:
case op::first_match:
break; break;
case op::F: case op::F:
// F e = e if e eventual // F e = e if e eventual

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2009-2018 Laboratoire de Recherche et Développement // Copyright (C) 2009-2019 Laboratoire de Recherche et Développement
// de l'Epita (LRDE). // de l'Epita (LRDE).
// Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris // Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris
// 6 (LIP6), département Systèmes Répartis Coopératifs (SRC), // 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
@ -99,6 +99,7 @@ namespace spot
case op::AndNLM: case op::AndNLM:
case op::OrRat: case op::OrRat:
case op::AndRat: case op::AndRat:
case op::first_match:
SPOT_UNIMPLEMENTED(); SPOT_UNIMPLEMENTED();
case op::ap: case op::ap:
return bdd_ithvar(d->register_proposition(f, owner)); return bdd_ithvar(d->register_proposition(f, owner));

View file

@ -121,6 +121,7 @@ namespace spot
case op::AndNLM: case op::AndNLM:
case op::AndRat: case op::AndRat:
case op::OrRat: case op::OrRat:
case op::first_match:
SPOT_UNIMPLEMENTED(); SPOT_UNIMPLEMENTED();
case op::U: case op::U:

View file

@ -867,6 +867,35 @@ namespace spot
} }
return res; return res;
} }
case op::first_match:
{
assert(f.size() == 1);
assert(!f.accepts_eword());
// Build deterministic successors, and
// rewrite each destination D as first_match(D).
// This will handle the semantic of the operator automatically,
// since first_match(D) = [*0] if D accepts [*0].
bdd res_ndet = recurse(f[0]);
bdd res_det = bddfalse;
bdd var_set = bdd_existcomp(bdd_support(res_ndet), dict_.var_set);
bdd all_props = bdd_existcomp(res_ndet, dict_.var_set);
while (all_props != bddfalse)
{
bdd label = bdd_satoneset(all_props, var_set, bddtrue);
all_props -= label;
formula dest =
dict_.bdd_to_sere(bdd_appex(res_ndet, label, bddop_and,
dict_.var_set));
dest = formula::first_match(dest);
if (to_concat_)
dest = formula::Concat({dest, to_concat_});
if (!dest.is_ff())
res_det |= label
& bdd_ithvar(dict_.register_next_variable(dest));
}
return res_det;
}
} }
SPOT_UNREACHABLE(); SPOT_UNREACHABLE();
} }
@ -1311,6 +1340,7 @@ namespace spot
} }
case op::Star: case op::Star:
case op::FStar: case op::FStar:
case op::first_match:
SPOT_UNREACHABLE(); // Not an LTL operator SPOT_UNREACHABLE(); // Not an LTL operator
// r(f1 logical-op f2) = r(f1) logical-op r(f2) // r(f1 logical-op f2) = r(f1) logical-op r(f2)
case op::Xor: case op::Xor:

View file

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2016, 2017, 2018 Laboratoire de Recherche et Développement # Copyright (C) 2016, 2017, 2018, 2019 Laboratoire de Recherche et Développement
# de l'Epita (LRDE). # de l'Epita (LRDE).
# #
# This file is part of Spot, a model checking library. # This file is part of Spot, a model checking library.
@ -141,3 +141,22 @@ grep 'highlight-word.*Fin' stderr
ltlfilt -f 'GFa' --accept-word 'cycle{!a}' && exit 1 ltlfilt -f 'GFa' --accept-word 'cycle{!a}' && exit 1
ltlfilt -f 'GF!a' --accept-word 'cycle{!a}' ltlfilt -f 'GF!a' --accept-word 'cycle{!a}'
cat >input <<EOF
{a ##[2:3] b} |-> c
{first_match(a ##[2:3] b)} |-> c
EOF
test 2 = `ltlfilt -c input --accept-word 'a;!b&!c;!b&!c;b&c;cycle{1}'`
test 2 = `ltlfilt -c input --accept-word 'a;!b&!c;b&c;cycle{1}'`
test 0 = `ltlfilt -c input --accept-word 'a;!b;b&!c;b&c;cycle{1}'`
test 2 = `ltlfilt -c input --accept-word 'a;!b;b&c;b&c;cycle{1}'`
test 1 = `ltlfilt -c input --accept-word 'a;!b;b&c;b&!c;cycle{1}'`
L='ltlfilt -c input --accept-word'
cat >input <<EOF
{(a ##[2:3] b):(c ##[1:2] d)} |-> e
{first_match(a ##[2:3] b):first_match(c ##[1:2] d)} |-> e
EOF
test 2 = `$L 'a;!b&!c;!b&!c;b&c;b&c&d&e;cycle{1}'`
test 1 = `$L 'a;!b&!c;!b&!c;b&c;b&c&d&e;b&c&d&!e;cycle{1}'`
test 1 = `$L 'a;!b&!c;b&c;b&c&d&e;b&c&d&!e;cycle{1}'`

View file

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2014, 2015, 2017, 2018 Laboratoire de Recherche et # Copyright (C) 2014, 2015, 2017, 2018, 2019 Laboratoire de Recherche et
# Développement de l'Epita (LRDE). # Développement de l'Epita (LRDE).
# #
# This file is part of Spot, a model checking library. # This file is part of Spot, a model checking library.
@ -34,6 +34,7 @@ star 1
star_b 1 star_b 1
fstar 1 fstar 1
fstar_b 1 fstar_b 1
first_match 1
and 0 and 0
andNLM 0 andNLM 0
or 1 or 1
@ -54,7 +55,7 @@ diff stdout expected
sere='eword=0,and=0,andNLM=0,fusion=0,star=0,star_b=0' sere='eword=0,and=0,andNLM=0,fusion=0,star=0,star_b=0'
sere="$sere,or=0,concat=0,fstar=0,fstar_b=0" sere="$sere,or=0,concat=0,fstar=0,fstar_b=0,first_match=0"
run 0 randltl -S -n 10000 a b c --tree-size=10..20 \ run 0 randltl -S -n 10000 a b c --tree-size=10..20 \
--sere-p=$sere \ --sere-p=$sere \
@ -69,6 +70,7 @@ star 0
star_b 0 star_b 0
fstar 0 fstar 0
fstar_b 0 fstar_b 0
first_match 0
and 0 and 0
andNLM 0 andNLM 0
or 0 or 0

View file

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2011, 2012, 2014, 2015, 2016 Laboratoire de Recherche # Copyright (C) 2011, 2012, 2014, 2015, 2016, 2019 Laboratoire de Recherche
# et Développement de l'Epita (LRDE). # et Développement de l'Epita (LRDE).
# #
# This file is part of Spot, a model checking library. # This file is part of Spot, a model checking library.
@ -25,10 +25,15 @@ set -e
# Generate 50 random unique PSL formula that do not simplify to LTL # Generate 50 random unique PSL formula that do not simplify to LTL
# formulae, and that have a size of at least 12. # formulae, and that have a size of at least 12.
randltl -n -1 --tree-size 30 --seed 12 --psl a b c | # The seed is selected so the test is fast enough, feel free to
# adjust it whenever something changes in formula generation.
randltl -n -1 --tree-size 30 --seed 13 --psl a b c |
ltlfilt -r --size 12.. --unique | ltlfilt -r --size 12.. --unique |
ltlfilt -v --ltl -n 50 | tee formulas | ltlfilt -v --ltl -n 50 | tee formulas |
ltlcross '../ikwiad -R3 -t %f >%T' '../ikwiad -x -R3 -t %f >%T' \ ltlcross '../ikwiad -R3 -t %f >%T' '../ikwiad -x -R3 -t %f >%T' \
-F - -f '{{(p1)}[*]:{(p3) && {{!(p1)} xor {!(p3)}}}}' -F - -f '{{(p1)}[*]:{(p3) && {{!(p1)} xor {!(p3)}}}}'
test `wc -l < formulas` = 50 test `wc -l < formulas` = 50
randltl --psl --sere-priorities=first_match=10 -n 100 2 | grep first_match

View file

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2013, 2015-2018 Laboratoire de Recherche et # Copyright (C) 2013, 2015-2019 Laboratoire de Recherche et
# Developpement de l'Epita # Developpement de l'Epita
# #
# This file is part of Spot, a model checking library. # This file is part of Spot, a model checking library.
@ -152,7 +152,7 @@ run 0 autfilt --check input > output
test `grep -c unambiguous output` = 0 test `grep -c unambiguous output` = 0
# Check 1000 random PSL formulas # Check 1000 random PSL formulas
randltl --psl -n 1000 3 | ltl2tgba -U -H | randltl --seed=12 --psl -n 1000 3 | ltl2tgba -U -H |
autfilt -v --is-unamb --stats=%M && exit 1 autfilt -v --is-unamb --stats=%M && exit 1
cat >input <<EOF cat >input <<EOF

View file

@ -57,10 +57,10 @@
{ {
"data": { "data": {
"text/latex": [ "text/latex": [
"$\\{a \\mathbin{\\mathsf{;}} b^{\\star} \\mathbin{\\mathsf{;}} c^+\\}\\mathrel{\\Diamond\\kern-1.7pt\\raise.4pt\\hbox{$\\mathord{\\rightarrow}$}} (c \\land \\mathsf{G} \\mathsf{F} b)$" "$\\{a \\mathbin{\\mathsf{;}} \\mathsf{first\\_match}(b^{\\star} \\mathbin{\\mathsf{;}} c^+ \\mathbin{\\mathsf{;}} d)\\}\\mathrel{\\Diamond\\kern-1.7pt\\raise.4pt\\hbox{$\\mathord{\\rightarrow}$}} (c \\land \\mathsf{G} \\mathsf{F} b)$"
], ],
"text/plain": [ "text/plain": [
"spot.formula(\"{a;b[*];c[+]}<>-> (c & GFb)\")" "spot.formula(\"{a;first_match(b[*];c[+];d)}<>-> (c & GFb)\")"
] ]
}, },
"execution_count": 3, "execution_count": 3,
@ -69,7 +69,7 @@
} }
], ],
"source": [ "source": [
"g = spot.formula('{a;b*;c[+]}<>->(GFb & c)'); g" "g = spot.formula('{a;first_match(b*;c[+];d)}<>->(GFb & c)'); g"
] ]
}, },
{ {
@ -497,47 +497,47 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"{a;b[*];c[+]}<>-> (c & GFb)\n" "{a;first_match(b[*];c[+];d)}<>-> (c & GFb)\n"
] ]
}, },
{ {
"data": { "data": {
"image/svg+xml": [ "image/svg+xml": [
"<svg height=\"332pt\" viewBox=\"0.00 0.00 299.00 332.00\" width=\"299pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", "<svg height=\"404pt\" viewBox=\"0.00 0.00 371.00 404.00\" width=\"371pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 328)\">\n", "<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 400)\">\n",
"<title>G</title>\n", "<title>G</title>\n",
"<polygon fill=\"#ffffff\" points=\"-4,4 -4,-328 295,-328 295,4 -4,4\" stroke=\"transparent\"/>\n", "<polygon fill=\"#ffffff\" points=\"-4,4 -4,-400 367,-400 367,4 -4,4\" stroke=\"transparent\"/>\n",
"<!-- 0 -->\n", "<!-- 0 -->\n",
"<g class=\"node\" id=\"node1\">\n", "<g class=\"node\" id=\"node1\">\n",
"<title>0</title>\n", "<title>0</title>\n",
"<ellipse cx=\"177\" cy=\"-306\" fill=\"none\" rx=\"40.8928\" ry=\"18\" stroke=\"#000000\"/>\n", "<ellipse cx=\"161\" cy=\"-378\" fill=\"none\" rx=\"40.8928\" ry=\"18\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"177\" y=\"-302.3\">EConcat</text>\n", "<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"161\" y=\"-374.3\">EConcat</text>\n",
"</g>\n", "</g>\n",
"<!-- 1 -->\n", "<!-- 1 -->\n",
"<g class=\"node\" id=\"node2\">\n", "<g class=\"node\" id=\"node2\">\n",
"<title>1</title>\n", "<title>1</title>\n",
"<ellipse cx=\"114\" cy=\"-162\" fill=\"none\" rx=\"35.9954\" ry=\"18\" stroke=\"#000000\"/>\n", "<ellipse cx=\"129\" cy=\"-306\" fill=\"none\" rx=\"35.9954\" ry=\"18\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"114\" y=\"-158.3\">Concat</text>\n", "<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"129\" y=\"-302.3\">Concat</text>\n",
"</g>\n", "</g>\n",
"<!-- 0&#45;&gt;1 -->\n", "<!-- 0&#45;&gt;1 -->\n",
"<g class=\"edge\" id=\"edge6\">\n", "<g class=\"edge\" id=\"edge9\">\n",
"<title>0-&gt;1</title>\n", "<title>0-&gt;1</title>\n",
"<path d=\"M169.1484,-288.0535C158.2902,-263.2347 138.5973,-218.2224 125.9187,-189.2428\" fill=\"none\" stroke=\"#000000\"/>\n", "<path d=\"M153.0899,-360.2022C149.4473,-352.0064 145.0455,-342.1024 141.0065,-333.0145\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"128.9675,-187.4791 121.7527,-179.7204 122.5543,-190.2848 128.9675,-187.4791\" stroke=\"#000000\"/>\n", "<polygon fill=\"#000000\" points=\"144.0789,-331.3096 136.8191,-323.593 137.6822,-334.1527 144.0789,-331.3096\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"164.6484\" y=\"-276.8535\">L</text>\n", "<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"148.5899\" y=\"-349.0022\">L</text>\n",
"</g>\n", "</g>\n",
"<!-- 7 -->\n", "<!-- 10 -->\n",
"<g class=\"node\" id=\"node8\">\n", "<g class=\"node\" id=\"node11\">\n",
"<title>7</title>\n", "<title>10</title>\n",
"<ellipse cx=\"209\" cy=\"-234\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"#000000\"/>\n", "<ellipse cx=\"225\" cy=\"-234\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"209\" y=\"-230.3\">And</text>\n", "<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"225\" y=\"-230.3\">And</text>\n",
"</g>\n", "</g>\n",
"<!-- 0&#45;&gt;7 -->\n", "<!-- 0&#45;&gt;10 -->\n",
"<g class=\"edge\" id=\"edge11\">\n", "<g class=\"edge\" id=\"edge14\">\n",
"<title>0-&gt;7</title>\n", "<title>0-&gt;10</title>\n",
"<path d=\"M184.9101,-288.2022C188.619,-279.8574 193.1148,-269.7417 197.2135,-260.5197\" fill=\"none\" stroke=\"#000000\"/>\n", "<path d=\"M168.9762,-360.0535C180.0668,-335.0998 200.23,-289.7326 213.1015,-260.7717\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"200.4282,-261.9042 201.2913,-251.3446 194.0315,-259.0612 200.4282,-261.9042\" stroke=\"#000000\"/>\n", "<polygon fill=\"#000000\" points=\"216.4602,-261.8321 217.3233,-251.2725 210.0635,-258.9891 216.4602,-261.8321\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"179.9101\" y=\"-277.0022\">R</text>\n", "<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"163.9762\" y=\"-348.8535\">R</text>\n",
"</g>\n", "</g>\n",
"<!-- 2 -->\n", "<!-- 2 -->\n",
"<g class=\"node\" id=\"node3\">\n", "<g class=\"node\" id=\"node3\">\n",
@ -548,95 +548,133 @@
"<!-- 1&#45;&gt;2 -->\n", "<!-- 1&#45;&gt;2 -->\n",
"<g class=\"edge\" id=\"edge1\">\n", "<g class=\"edge\" id=\"edge1\">\n",
"<title>1-&gt;2</title>\n", "<title>1-&gt;2</title>\n",
"<path d=\"M89.6281,-148.603C74.758,-139.1708 56.625,-125.1808 46,-108 34.5017,-89.407 29.8676,-64.9633 28.0445,-46.243\" fill=\"none\" stroke=\"#000000\"/>\n", "<path d=\"M106.7369,-291.6428C93.666,-282.0164 77.9949,-268.1646 69,-252 31.7473,-185.0541 26.4358,-92.1681 26.3309,-46.1548\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"31.5318,-45.9421 27.2801,-36.2378 24.5521,-46.4754 31.5318,-45.9421\" stroke=\"#000000\"/>\n", "<polygon fill=\"#000000\" points=\"29.8315,-46.0506 26.3923,-36.0296 22.8317,-46.0081 29.8315,-46.0506\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"86.1281\" y=\"-137.403\">1</text>\n", "<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"103.2369\" y=\"-280.4428\">1</text>\n",
"</g>\n", "</g>\n",
"<!-- 3 -->\n", "<!-- 3 -->\n",
"<g class=\"node\" id=\"node4\">\n", "<g class=\"node\" id=\"node4\">\n",
"<title>3</title>\n", "<title>3</title>\n",
"<ellipse cx=\"154\" cy=\"-90\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"#000000\"/>\n", "<ellipse cx=\"129\" cy=\"-234\" fill=\"none\" rx=\"51.1914\" ry=\"18\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"154\" y=\"-86.3\">Star</text>\n", "<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"129\" y=\"-230.3\">first_match</text>\n",
"</g>\n", "</g>\n",
"<!-- 1&#45;&gt;3 -->\n", "<!-- 1&#45;&gt;3 -->\n",
"<g class=\"edge\" id=\"edge3\">\n", "<g class=\"edge\" id=\"edge8\">\n",
"<title>1-&gt;3</title>\n", "<title>1-&gt;3</title>\n",
"<path d=\"M123.6829,-144.5708C128.3996,-136.0807 134.1706,-125.6929 139.407,-116.2674\" fill=\"none\" stroke=\"#000000\"/>\n", "<path d=\"M129,-287.8314C129,-280.131 129,-270.9743 129,-262.4166\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"142.6094,-117.71 144.4063,-107.2687 136.4903,-114.3105 142.6094,-117.71\" stroke=\"#000000\"/>\n", "<polygon fill=\"#000000\" points=\"132.5001,-262.4132 129,-252.4133 125.5001,-262.4133 132.5001,-262.4132\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"120.1829\" y=\"-133.3708\">2</text>\n", "<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"125.5\" y=\"-276.6314\">2</text>\n",
"</g>\n",
"<!-- 5 -->\n",
"<g class=\"node\" id=\"node6\">\n",
"<title>5</title>\n",
"<ellipse cx=\"82\" cy=\"-90\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"82\" y=\"-86.3\">Star</text>\n",
"</g>\n",
"<!-- 1&#45;&gt;5 -->\n",
"<g class=\"edge\" id=\"edge5\">\n",
"<title>1-&gt;5</title>\n",
"<path d=\"M106.0899,-144.2022C102.381,-135.8574 97.8852,-125.7417 93.7865,-116.5197\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"96.9685,-115.0612 89.7087,-107.3446 90.5718,-117.9042 96.9685,-115.0612\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"102.5899\" y=\"-133.0022\">3</text>\n",
"</g>\n", "</g>\n",
"<!-- 4 -->\n", "<!-- 4 -->\n",
"<g class=\"node\" id=\"node5\">\n", "<g class=\"node\" id=\"node5\">\n",
"<title>4</title>\n", "<title>4</title>\n",
"<polygon fill=\"none\" points=\"267,-36 213,-36 213,0 267,0 267,-36\" stroke=\"#000000\"/>\n", "<ellipse cx=\"137\" cy=\"-162\" fill=\"none\" rx=\"35.9954\" ry=\"18\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"240\" y=\"-14.3\">b</text>\n", "<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"137\" y=\"-158.3\">Concat</text>\n",
"</g>\n", "</g>\n",
"<!-- 3&#45;&gt;4 -->\n", "<!-- 3&#45;&gt;4 -->\n",
"<g class=\"edge\" id=\"edge2\">\n",
"<title>3-&gt;4</title>\n",
"<path d=\"M170.9908,-75.7751C182.2603,-66.3402 197.3476,-53.709 210.5409,-42.6634\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"213.039,-45.1367 218.4598,-36.0336 208.5454,-39.7694 213.039,-45.1367\" stroke=\"#000000\"/>\n",
"</g>\n",
"<!-- 6 -->\n",
"<g class=\"node\" id=\"node7\">\n",
"<title>6</title>\n",
"<polygon fill=\"none\" points=\"172,-36 118,-36 118,0 172,0 172,-36\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"145\" y=\"-14.3\">c</text>\n",
"</g>\n",
"<!-- 5&#45;&gt;6 -->\n",
"<g class=\"edge\" id=\"edge4\">\n",
"<title>5-&gt;6</title>\n",
"<path d=\"M95.6701,-74.3771C103.514,-65.4125 113.5574,-53.9344 122.5323,-43.6774\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"125.1819,-45.9643 129.1329,-36.1338 119.9138,-41.3548 125.1819,-45.9643\" stroke=\"#000000\"/>\n",
"</g>\n",
"<!-- 7&#45;&gt;6 -->\n",
"<g class=\"edge\" id=\"edge7\">\n", "<g class=\"edge\" id=\"edge7\">\n",
"<title>7-&gt;6</title>\n", "<title>3-&gt;4</title>\n",
"<path d=\"M210.1584,-215.6415C211.4052,-184.6687 210.9012,-120.6548 190,-72 185.6198,-61.8035 178.6732,-52.0371 171.5362,-43.6819\" fill=\"none\" stroke=\"#000000\"/>\n", "<path d=\"M131.0187,-215.8314C131.8743,-208.131 132.8917,-198.9743 133.8426,-190.4166\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"174.0158,-41.2056 164.7127,-36.1357 168.8236,-45.9005 174.0158,-41.2056\" stroke=\"#000000\"/>\n", "<polygon fill=\"#000000\" points=\"137.3283,-190.7386 134.9541,-180.4133 130.3711,-189.9656 137.3283,-190.7386\" stroke=\"#000000\"/>\n",
"</g>\n", "</g>\n",
"<!-- 8 -->\n", "<!-- 5 -->\n",
"<g class=\"node\" id=\"node9\">\n", "<g class=\"node\" id=\"node6\">\n",
"<title>8</title>\n", "<title>5</title>\n",
"<ellipse cx=\"264\" cy=\"-162\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"#000000\"/>\n", "<ellipse cx=\"264\" cy=\"-90\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"264\" y=\"-158.3\">G</text>\n", "<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"264\" y=\"-86.3\">Star</text>\n",
"</g>\n", "</g>\n",
"<!-- 7&#45;&gt;8 -->\n", "<!-- 4&#45;&gt;5 -->\n",
"<g class=\"edge\" id=\"edge10\">\n", "<g class=\"edge\" id=\"edge3\">\n",
"<title>7-&gt;8</title>\n", "<title>4-&gt;5</title>\n",
"<path d=\"M221.4804,-217.6621C228.5124,-208.4564 237.4347,-196.7764 245.2883,-186.4953\" fill=\"none\" stroke=\"#000000\"/>\n", "<path d=\"M160.8877,-148.4574C181.7279,-136.6424 212.0459,-119.4543 234.416,-106.772\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"248.28,-188.3446 251.569,-178.2733 242.7172,-184.0953 248.28,-188.3446\" stroke=\"#000000\"/>\n", "<polygon fill=\"#000000\" points=\"236.191,-109.7891 243.1641,-101.8125 232.7387,-103.6997 236.191,-109.7891\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"157.3877\" y=\"-137.2574\">1</text>\n",
"</g>\n",
"<!-- 7 -->\n",
"<g class=\"node\" id=\"node8\">\n",
"<title>7</title>\n",
"<ellipse cx=\"154\" cy=\"-90\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"154\" y=\"-86.3\">Star</text>\n",
"</g>\n",
"<!-- 4&#45;&gt;7 -->\n",
"<g class=\"edge\" id=\"edge5\">\n",
"<title>4-&gt;7</title>\n",
"<path d=\"M141.2898,-143.8314C143.1562,-135.9266 145.385,-126.4872 147.4511,-117.7365\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"150.8788,-118.4501 149.7704,-107.9134 144.0661,-116.8415 150.8788,-118.4501\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"137.7898\" y=\"-132.6314\">2</text>\n",
"</g>\n", "</g>\n",
"<!-- 9 -->\n", "<!-- 9 -->\n",
"<g class=\"node\" id=\"node10\">\n", "<g class=\"node\" id=\"node10\">\n",
"<title>9</title>\n", "<title>9</title>\n",
"<ellipse cx=\"264\" cy=\"-90\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"#000000\"/>\n", "<polygon fill=\"none\" points=\"126,-36 72,-36 72,0 126,0 126,-36\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"264\" y=\"-86.3\">F</text>\n", "<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"99\" y=\"-14.3\">d</text>\n",
"</g>\n", "</g>\n",
"<!-- 8&#45;&gt;9 -->\n", "<!-- 4&#45;&gt;9 -->\n",
"<g class=\"edge\" id=\"edge9\">\n", "<g class=\"edge\" id=\"edge6\">\n",
"<title>8-&gt;9</title>\n", "<title>4-&gt;9</title>\n",
"<path d=\"M264,-143.8314C264,-136.131 264,-126.9743 264,-118.4166\" fill=\"none\" stroke=\"#000000\"/>\n", "<path d=\"M130.0742,-144.187C126.1822,-133.7494 121.4322,-120.2494 118,-108 112.2642,-87.5291 107.3558,-64.0109 103.9655,-46.1505\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"267.5001,-118.4132 264,-108.4133 260.5001,-118.4133 267.5001,-118.4132\" stroke=\"#000000\"/>\n", "<polygon fill=\"#000000\" points=\"107.3661,-45.2923 102.1034,-36.097 100.4832,-46.5672 107.3661,-45.2923\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"126.5742\" y=\"-132.987\">3</text>\n",
"</g>\n", "</g>\n",
"<!-- 9&#45;&gt;4 -->\n", "<!-- 6 -->\n",
"<g class=\"edge\" id=\"edge8\">\n", "<g class=\"node\" id=\"node7\">\n",
"<title>9-&gt;4</title>\n", "<title>6</title>\n",
"<path d=\"M258.0674,-72.2022C255.4049,-64.2146 252.2015,-54.6045 249.2362,-45.7087\" fill=\"none\" stroke=\"#000000\"/>\n", "<polygon fill=\"none\" points=\"299,-36 245,-36 245,0 299,0 299,-36\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"252.5138,-44.4731 246.031,-36.0931 245.873,-46.6868 252.5138,-44.4731\" stroke=\"#000000\"/>\n", "<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"272\" y=\"-14.3\">b</text>\n",
"</g>\n",
"<!-- 5&#45;&gt;6 -->\n",
"<g class=\"edge\" id=\"edge2\">\n",
"<title>5-&gt;6</title>\n",
"<path d=\"M266.0187,-71.8314C266.8743,-64.131 267.8917,-54.9743 268.8426,-46.4166\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"272.3283,-46.7386 269.9541,-36.4133 265.3711,-45.9656 272.3283,-46.7386\" stroke=\"#000000\"/>\n",
"</g>\n",
"<!-- 8 -->\n",
"<g class=\"node\" id=\"node9\">\n",
"<title>8</title>\n",
"<polygon fill=\"none\" points=\"213,-36 159,-36 159,0 213,0 213,-36\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"186\" y=\"-14.3\">c</text>\n",
"</g>\n",
"<!-- 7&#45;&gt;8 -->\n",
"<g class=\"edge\" id=\"edge4\">\n",
"<title>7-&gt;8</title>\n",
"<path d=\"M161.7463,-72.5708C165.398,-64.3544 169.8396,-54.3608 173.9191,-45.1821\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"177.1277,-46.5802 177.9908,-36.0206 170.7311,-43.7372 177.1277,-46.5802\" stroke=\"#000000\"/>\n",
"</g>\n",
"<!-- 10&#45;&gt;8 -->\n",
"<g class=\"edge\" id=\"edge10\">\n",
"<title>10-&gt;8</title>\n",
"<path d=\"M221.742,-215.9555C214.9457,-178.3144 199.2143,-91.1867 191.078,-46.1246\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"194.4974,-45.364 189.2762,-36.1451 187.6088,-46.6079 194.4974,-45.364\" stroke=\"#000000\"/>\n",
"</g>\n",
"<!-- 11 -->\n",
"<g class=\"node\" id=\"node12\">\n",
"<title>11</title>\n",
"<ellipse cx=\"300\" cy=\"-162\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"300\" y=\"-158.3\">G</text>\n",
"</g>\n",
"<!-- 10&#45;&gt;11 -->\n",
"<g class=\"edge\" id=\"edge13\">\n",
"<title>10-&gt;11</title>\n",
"<path d=\"M240.54,-219.0816C251.099,-208.945 265.2444,-195.3654 277.0892,-183.9944\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"279.6898,-186.3495 284.4799,-176.8993 274.8421,-181.2998 279.6898,-186.3495\" stroke=\"#000000\"/>\n",
"</g>\n",
"<!-- 12 -->\n",
"<g class=\"node\" id=\"node13\">\n",
"<title>12</title>\n",
"<ellipse cx=\"336\" cy=\"-90\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"#000000\"/>\n",
"<text fill=\"#000000\" font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"336\" y=\"-86.3\">F</text>\n",
"</g>\n",
"<!-- 11&#45;&gt;12 -->\n",
"<g class=\"edge\" id=\"edge12\">\n",
"<title>11-&gt;12</title>\n",
"<path d=\"M308.7146,-144.5708C312.9597,-136.0807 318.1536,-125.6929 322.8663,-116.2674\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"326.024,-117.7782 327.3657,-107.2687 319.763,-114.6477 326.024,-117.7782\" stroke=\"#000000\"/>\n",
"</g>\n",
"<!-- 12&#45;&gt;6 -->\n",
"<g class=\"edge\" id=\"edge11\">\n",
"<title>12-&gt;6</title>\n",
"<path d=\"M322.113,-74.3771C314.1445,-65.4125 303.9417,-53.9344 294.8244,-43.6774\" fill=\"none\" stroke=\"#000000\"/>\n",
"<polygon fill=\"#000000\" points=\"297.3785,-41.2826 288.1189,-36.1338 292.1466,-45.9332 297.3785,-41.2826\" stroke=\"#000000\"/>\n",
"</g>\n", "</g>\n",
"</g>\n", "</g>\n",
"</svg>" "</svg>"
@ -927,7 +965,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.1" "version": "3.7.3"
} }
}, },
"nbformat": 4, "nbformat": 4,

View file

@ -171,12 +171,12 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"{{p0 && p2}[*]}<>-> (Fp2 & Fp0)\n" "{{1 | [*0]}[:*] & [*2]}\n"
] ]
} }
], ],
"source": [ "source": [
"f = spot.randltl(3, output='psl', seed=332)\n", "f = spot.randltl(3, output='psl', seed=26)\n",
"print(next(f))" "print(next(f))"
] ]
}, },
@ -370,6 +370,7 @@
"star_b\t1\n", "star_b\t1\n",
"fstar\t1\n", "fstar\t1\n",
"fstar_b\t1\n", "fstar_b\t1\n",
"first_match\t1\n",
"and\t1\n", "and\t1\n",
"andNLM\t1\n", "andNLM\t1\n",
"or\t1\n", "or\t1\n",
@ -403,6 +404,7 @@
"star_b\t1\n", "star_b\t1\n",
"fstar\t1\n", "fstar\t1\n",
"fstar_b\t1\n", "fstar_b\t1\n",
"first_match\t1\n",
"and\t1\n", "and\t1\n",
"andNLM\t1\n", "andNLM\t1\n",
"or\t1\n", "or\t1\n",
@ -618,7 +620,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.6.6+" "version": "3.7.3"
} }
}, },
"nbformat": 4, "nbformat": 4,