twa: store property bits as trivals

* spot/twa/twa.hh: Store property bits as trivals.
* NEWS: Mention the change.
* spot/parseaut/parseaut.yy, spot/twaalgos/are_isomorphic.cc,
spot/twaalgos/complete.cc, spot/twaalgos/dot.cc, spot/twaalgos/hoa.cc,
spot/twaalgos/isdet.cc, spot/twaalgos/isunamb.cc, spot/twaalgos/lbtt.cc,
spot/twaalgos/ltl2tgba_fm.cc, spot/twaalgos/postproc.cc,
spot/twaalgos/remfin.cc, spot/twaalgos/strength.cc,
spot/twaalgos/stutter.cc, spot/twaalgos/stutter.hh,
spot/twaalgos/totgba.cc, tests/core/ikwiad.cc,
tests/python/product.ipynb, tests/python/remfin.py: Adjust.
* doc/org/hoa.org, doc/org/tut21.org: Update documentation.
This commit is contained in:
Alexandre Duret-Lutz 2016-01-12 19:37:18 +01:00
parent 1aeb260adf
commit da391492f3
22 changed files with 337 additions and 258 deletions

View file

@ -1,7 +1,7 @@
{
"metadata": {
"name": "",
"signature": "sha256:50d5adbd44f5981c700cec9133b926c8edb75b3ff80a4cf28e7c26cf918fe04a"
"signature": "sha256:08e64ee189c19ed7e56e5f1c841f51faac25e0bd5e4a6b838856ba8b6f2b5344"
},
"nbformat": 3,
"nbformat_minor": 0,
@ -367,7 +367,7 @@
"output_type": "pyout",
"prompt_number": 2,
"text": [
"<IPython.core.display.HTML at 0x7fc8fd6de160>"
"<IPython.core.display.HTML at 0x7ff45181d390>"
]
}
],
@ -711,7 +711,7 @@
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.HTML at 0x7fc8df0b6630>"
"<IPython.core.display.HTML at 0x7ff444140860>"
]
}
],
@ -1066,7 +1066,7 @@
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.HTML at 0x7fc8df07bf28>"
"<IPython.core.display.HTML at 0x7ff451801208>"
]
}
],
@ -1076,7 +1076,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Besides the obvious lack of acceptance condition (which defaults to `t`) and acceptance sets, there is a less obvious problem: we never declared the set of atomic proposition used by the result automaton. This as two consequences:\n",
"Besides the obvious lack of acceptance condition (which defaults to `t`) and acceptance sets, there is a less obvious problem: we never declared the set of atomic propositions used by the result automaton. This as two consequences:\n",
"- calling `p1.ap()` will return an empty set of atomic propositions"
]
},
@ -1487,7 +1487,7 @@
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.HTML at 0x7fc8df015d68>"
"<IPython.core.display.HTML at 0x7ff44409ef98>"
]
},
{
@ -1533,10 +1533,10 @@
"output_type": "stream",
"stream": "stdout",
"text": [
"True\n",
"True\n",
"True\n",
"False\n"
"yes\n",
"yes\n",
"yes\n",
"maybe\n"
]
}
],
@ -1546,11 +1546,76 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Because `a1` and `a2` are deterministic, their product is necessarily deterministic. This is a property that the `spot.product()` algorithm will preserve, but that our version does not yet preserve. We can fix that by adding\n",
"Because `a1` and `a2` are deterministic, their product is necessarily deterministic. This is a property that the `spot.product()` algorithm will preserve, but that our version does not *yet* preserve. We can fix that by adding\n",
"\n",
" if left.prop_deterministic() and right.prop_deterministic():\n",
" result.prop_deterministic(True)\n",
" \n",
"at the end of our function. Note that this is **not** the same as\n",
"\n",
" result.prop_deterministic(left.prop_deterministic() and right.prop_deterministic())\n",
" \n",
"at the end of our function. However the question is in fact more general than just determinism: the product of two weak automata is weak, the product of two stutter-invariant automata is stutter-invariant, etc. So when writing an algorithm one should consider which of the [property bits](https://spot.lrde.epita.fr/hoa.html#property-bits) are naturally preserved by the algorithm, and set the relevant bits: this can save time later if the resulting automaton is used as input for another algorithm."
"\n",
"because the results the `prop_*()` family of functions take and return instances of `spot.trival` values. These `spot.trival`, can, as their name implies, take one amongst three values representing `yes`, `no`, and `maybe`. `yes` and `no` should be used when we actually know that the automaton is deterministic or not (not deterministic meaning that there actually exists some non determinitic state in the automaton), and `maybe` when we do not know. \n",
"\n",
"The one-liner above is wrong for two reasons:\n",
"\n",
" - if `left` and `right` are non-deterministic, their product could be deterministic, so calling prop_deterministic(False) would be wrong. \n",
"\n",
" - the use of the `and` operator on `trival` is misleading in non-Boolean context. The `&` operator would be the correct operator to use if you want to work in threed-valued logic. Compare: "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"yes = spot.trival(True)\n",
"no = spot.trival(False)\n",
"maybe = spot.trival_maybe()\n",
"for u in (no, maybe, yes):\n",
" for v in (no, maybe, yes):\n",
" print(\"{u!s:>5} & {v!s:<5} = {r1!s:<5} {u!s:>5} and {v!s:<5} = {r2!s:<5}\"\n",
" .format(u=u, v=v, r1=(u&v), r2=(u and v)))"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
" no & no = no no and no = no \n",
" no & maybe = no no and maybe = no \n",
" no & yes = no no and yes = no \n",
"maybe & no = no maybe and no = maybe\n",
"maybe & maybe = maybe maybe and maybe = maybe\n",
"maybe & yes = maybe maybe and yes = maybe\n",
" yes & no = no yes and no = no \n",
" yes & maybe = maybe yes and maybe = maybe\n",
" yes & yes = yes yes and yes = yes \n"
]
}
],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The reason `maybe and no` is equal to `maybe` is that Python evaluate it like `no if maybe else maybe`, but when a trival is evaluated in a Boolean context (as in `if maybe`) the result is True only if the trival is equal to yes.\n",
"\n",
"So our\n",
"\n",
" if left.prop_deterministic() and right.prop_deterministic():\n",
" result.prop_deterministic(True)\n",
"\n",
"is OK because the `if` body will only be entered of both input automata are known to be deterministic."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"However the question is in fact more general than just determinism: the product of two weak automata is weak, the product of two stutter-invariant automata is stutter-invariant, etc. So when writing an algorithm one should consider which of the [property bits](https://spot.lrde.epita.fr/hoa.html#property-bits) are naturally preserved by the algorithm, and set the relevant bits: this can save time later if the resulting automaton is used as input for another algorithm."
]
},
{
@ -1598,10 +1663,11 @@
" # Remember the names of our states\n",
" result.set_state_names(names)\n",
" \n",
" # Loop over all the properties we want to preserve if they are in both automata\n",
" # Loop over all the properties we want to preserve if they hold in both automata\n",
" for p in ('prop_deterministic', 'prop_weak', 'prop_inherently_weak', \n",
" 'prop_terminal', 'prop_stutter_invariant', 'prop_state_acc'):\n",
" getattr(result, p)(getattr(left, p)() and getattr(right, p)())\n",
" if getattr(left, p)() and getattr(right, p)():\n",
" getattr(result, p)(True)\n",
" return result\n",
"\n",
"p3 = product3(a1, a2)\n",
@ -1925,18 +1991,18 @@
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.HTML at 0x7fc8df001240>"
"<IPython.core.display.HTML at 0x7ff44408aa58>"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"True\n"
"yes\n"
]
}
],
"prompt_number": 8
"prompt_number": 9
},
{
"cell_type": "markdown",
@ -1960,11 +2026,11 @@
"output_type": "stream",
"stream": "stdout",
"text": [
"1000 loops, best of 3: 353 \u00b5s per loop\n"
"1000 loops, best of 3: 342 \u00b5s per loop\n"
]
}
],
"prompt_number": 9
"prompt_number": 10
},
{
"cell_type": "code",
@ -1979,11 +2045,11 @@
"output_type": "stream",
"stream": "stdout",
"text": [
"100000 loops, best of 3: 6.39 \u00b5s per loop\n"
"100000 loops, best of 3: 6.44 \u00b5s per loop\n"
]
}
],
"prompt_number": 10
"prompt_number": 11
},
{
"cell_type": "markdown",